From 3a73c98e193a476b6940e53497be29aba81c7951 Mon Sep 17 00:00:00 2001 From: Jared Thorne Date: Wed, 21 Aug 2024 13:08:46 +0000 Subject: [PATCH 001/306] Improved server music config loading logging --- Server/src/main/core/game/system/config/MusicConfigLoader.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/config/MusicConfigLoader.kt b/Server/src/main/core/game/system/config/MusicConfigLoader.kt index 4b0a82354..d73fc597d 100644 --- a/Server/src/main/core/game/system/config/MusicConfigLoader.kt +++ b/Server/src/main/core/game/system/config/MusicConfigLoader.kt @@ -42,8 +42,8 @@ class MusicConfigLoader { val id = Integer.parseInt(e["id"].toString()) RegionManager.forId(region).music = MusicEntry.forId(id) count++ - log(this::class.java, Log.FINE, "Parsed $count region music configs.") } + log(this::class.java, Log.FINE, "Parsed $count region music configs.") // Parse the file with tile-specific music locations count = 0 From 083df1aae2065734022cc3576507379c22176087 Mon Sep 17 00:00:00 2001 From: Roderik Date: Wed, 21 Aug 2024 13:13:15 +0000 Subject: [PATCH 002/306] Superheat ore order of precedence has been corrected --- .../skill/magic/modern/ModernListeners.kt | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 230fd75b1..262824d2c 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -183,21 +183,27 @@ class ModernListeners : SpellListener("modern"){ return } - var bar = Bar.forOre(item.id) ?: return - if(bar == Bar.IRON && player.inventory.getAmount(Items.COAL_453) >= 2 && player.skills.getLevel(Skills.SMITHING) >= Bar.STEEL.level && player.inventory.contains(Items.IRON_ORE_441,1)) bar = Bar.STEEL + fun returnBar(player: Player,item: Item): Bar? { + // Loop through all metal bars starting with the highest tier + for (potentialBar in Bar.values().reversed()) { + // Check if the ore being cast on is needed for the current bar being considered + val inputOreInBar = potentialBar.ores.map{it.id}.contains(item.id) + // Check the player has all the required ores (and corresponding quantities) to make the current bar being considered + val playerHasNecessaryOres = potentialBar.ores.all{ore -> inInventory(player, ore.id, ore.amount)} + // If both tests pass return the current bar being considered as the one the spell should try to make + if (inputOreInBar && playerHasNecessaryOres) return potentialBar + } + // If none of the bars passed both tests the player must be missing a required ore + player.packetDispatch.sendMessage("You do not have the required ores to make this bar.") + return null + } + var bar = returnBar(player,item)?: return if(player.skills.getLevel(Skills.SMITHING) < bar.level){ player.sendMessage("You need a smithing level of ${bar.level} to superheat that ore.") return } - for (items in bar.ores) { - if (!player.inventory.contains(items.id, items.amount)) { - player.packetDispatch.sendMessage("You do not have the required ores to make this bar.") - return - } - } - player.lock(3) removeRunes(player) addXP(player,53.0) From 29fa9a5a21d60e7c4b309f1270e7cd77071372ce Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Wed, 21 Aug 2024 13:25:10 +0000 Subject: [PATCH 003/306] Rune hasta requirements fix --- Server/data/configs/item_configs.json | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index f3cf0c2da..7bfe8b36d 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -98752,6 +98752,7 @@ "bonuses": "36,36,36,0,0,-10,-10,-9,0,-10,0,42,0,0,0" }, { + "requirements": "{0,40}", "ge_buy_limit": "100", "turn90cw_anim": "1207", "examine": "A rune-tipped, one-handed hasta.", From e25c7d782472588b26efd1f4d7d0a8fb33919cdf Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Wed, 21 Aug 2024 14:04:44 +0000 Subject: [PATCH 004/306] Implemented Recruitment Drive quest --- Server/data/configs/ground_spawns.json | 4 + Server/data/configs/item_configs.json | 108 ++-- Server/data/configs/npc_configs.json | 105 +++- Server/data/configs/npc_spawns.json | 28 + .../castlewars/CastleWarsListeners.kt | 1 - .../quest/trollstronghold/TrollStronghold.kt | 2 +- .../dialogue/SirTiffyCashienDialogue.java | 89 --- .../dialogue/SirTiffyCashienDialogue.kt | 106 ++++ .../SirAmikVarzeDialogue.java | 33 +- .../quest/recruitmentdrive/AlchemicalNotes.kt | 248 +++++++++ .../recruitmentdrive/LadyTableDialogue.kt | 114 ++++ .../recruitmentdrive/MissCheeversDialogue.kt | 512 ++++++++++++++++++ .../MsHynnTerprettDialogue.kt | 154 ++++++ .../recruitmentdrive/RecruitmentDrive.kt | 133 +++++ .../RecruitmentDriveListeners.kt | 316 +++++++++++ .../SirAmikVarzeDialogueFile.kt | 74 +++ .../SirKuamFerentseDialogue.kt | 58 ++ .../quest/recruitmentdrive/SirLeyeBehavior.kt | 49 ++ .../SirRenItchwoodDialogue.kt | 199 +++++++ .../recruitmentdrive/SirSpishyusDialogue.kt | 221 ++++++++ .../SirTiffyCashienDialogueFile.kt | 139 +++++ .../recruitmentdrive/SirTinleyDialogue.kt | 100 ++++ .../quest/witchshouse/WitchsHouse.java | 1 + .../CreatureOfFenkenstrainListeners.kt | 4 - Server/src/main/core/api/ContentAPI.kt | 20 + .../src/main/core/game/activity/Cutscene.kt | 68 +++ .../core/game/dialogue/DialogueBuilder.kt | 8 + .../game/dialogue/DialogueInterpreter.java | 2 + 28 files changed, 2715 insertions(+), 181 deletions(-) delete mode 100644 Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.java create mode 100644 Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/AlchemicalNotes.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/LadyTableDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MissCheeversDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MsHynnTerprettDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirKuamFerentseDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirLeyeBehavior.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirRenItchwoodDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirSpishyusDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt create mode 100644 Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTinleyDialogue.kt diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json index 6b94f4807..cf3b5345c 100644 --- a/Server/data/configs/ground_spawns.json +++ b/Server/data/configs/ground_spawns.json @@ -627,6 +627,10 @@ "item_id": "5523", "loc_data": "{1,2935,3282,1,90}-" }, + { + "item_id": "5586", + "loc_data": "{1,2473,4941,0,90}-" + }, { "item_id": "6291", "loc_data": "{1,2681,3111,0,30}-{1,2673,3112,0,30}-{1,2674,3094,0,30}-{1,2671,3089,0,30}-" diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 7bfe8b36d..a365397e3 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -50376,10 +50376,18 @@ "id": "5584" }, { - "examine": "It's a metal spade without a handle.", + "examine": "I hope the mould was accurate enough...", + "durability": null, + "name": "Bronze Key", + "weight": "0.01", + "archery_ticket_price": "0", + "id": "5585" + }, + { + "examine": "It's a metal spade with a wooden handle.", "durability": null, "name": "Metal spade", - "weight": "2.5", + "weight": "1.814", "archery_ticket_price": "0", "id": "5586" }, @@ -50387,7 +50395,7 @@ "examine": "It's a metal spade without a handle.", "durability": null, "name": "Metal spade", - "weight": "2.5", + "weight": "1.814", "archery_ticket_price": "0", "id": "5587" }, @@ -50399,101 +50407,101 @@ "id": "5588" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "A tin layered with some stuff from a vial.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5592" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "It's full of a white lumpy mixture that seems to be hardening.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5593" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is an impression of a key embedded in it.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5594" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is an impression of a key, filled with tin ore.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5595" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is an impression of a key, filled with copper ore.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5596" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is an impression of a key, filled with tin and copper ore.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5597" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is a bronze key surrounded by plaster in this tin.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5598" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "20", + "examine": "There is a strange concoction filling this tin.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.101", "archery_ticket_price": "0", "id": "5599" }, { - "shop_price": "6", - "examine": "This needs refining.", - "grand_exchange_price": "42", + "shop_price": "10", + "examine": "I could probably pour something into this.", + "grand_exchange_price": "0", "durability": null, "name": "Tin", - "tradeable": "true", - "weight": "2.25", + "tradeable": "false", + "weight": "0.1", "archery_ticket_price": "0", "id": "5600" }, @@ -50523,8 +50531,8 @@ "grand_exchange_price": "41", "durability": null, "name": "Shears", - "tradeable": "true", - "weight": "0.1", + "tradeable": "false", + "weight": "0.113", "archery_ticket_price": "0", "id": "5603" }, diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 9250ea47f..616d737c0 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -23449,6 +23449,54 @@ "range_level": "1", "attack_level": "1" }, + { + "examine": "An observer for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Sir Spishyus", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2282", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "An observer for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Lady Table", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2283", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "An observer for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Sir Kuam Ferentse", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2284", + "range_level": "1", + "attack_level": "1" + }, { "examine": "A warrior blessed by Saradomin.", "melee_animation": "400", @@ -23456,13 +23504,45 @@ "defence_animation": "425", "death_animation": "836", "name": "Sir Leye", - "defence_level": "1", + "defence_level": "15", "safespot": null, "lifepoints": "21", - "strength_level": "1", + "strength_level": "18", "id": "2285", "aggressive": "true", "range_level": "1", + "attack_level": "18" + }, + { + "examine": "An observer for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Sir Tinley", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2286", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "An observer for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Sir Ren Itchood", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2287", + "range_level": "1", "attack_level": "1" }, { @@ -23497,6 +23577,22 @@ "range_level": "1", "attack_level": "1" }, + { + "examine": "Head of recruitment for the Temple Knights.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Sir Tiffy Cashien", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "2290", + "range_level": "1", + "attack_level": "1" + }, { "examine": "A carpet merchant.", "melee_animation": "0", @@ -71281,11 +71377,6 @@ "name": "Sir Vyvin", "id": "605" }, - { - "examine": "Head of recruitment for the Temple Knights.", - "name": "Sir Tiffy Cashien", - "id": "2290" - }, { "examine": "An armourer.", "name": "Wayne", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 0074b7fab..9442e9457 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -5171,6 +5171,34 @@ "npc_id": "2281", "loc_data": "{3187,3241,0,1,0}-{3177,3243,0,1,0}-{3246,3245,0,1,4}-" }, + { + "npc_id": "2282", + "loc_data": "{2488,4973,0,0,6}-" + }, + { + "npc_id": "2283", + "loc_data": "{2458,4980,0,0,6}-" + }, + { + "npc_id": "2284", + "loc_data": "{2457,4966,0,0,6}-" + }, + { + "npc_id": "2286", + "loc_data": "{2476,4958,0,0,3}-" + }, + { + "npc_id": "2287", + "loc_data": "{2443,4956,0,0,4}-" + }, + { + "npc_id": "2288", + "loc_data": "{2469,4941,0,0,6}-" + }, + { + "npc_id": "2289", + "loc_data": "{2451,4939,0,0,6}-" + }, { "npc_id": "2290", "loc_data": "{2997,3373,0,0,0}-" diff --git a/Server/src/main/content/minigame/castlewars/CastleWarsListeners.kt b/Server/src/main/content/minigame/castlewars/CastleWarsListeners.kt index eed986625..24fdb55cc 100644 --- a/Server/src/main/content/minigame/castlewars/CastleWarsListeners.kt +++ b/Server/src/main/content/minigame/castlewars/CastleWarsListeners.kt @@ -18,7 +18,6 @@ import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import org.rs09.consts.Sounds import rs09.game.content.activity.castlewars.areas.CastleWarsWaitingArea -import java.util.* @Suppress("unused") class CastleWarsListeners : InteractionListener { diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt index 971e7f392..37ce90253 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt @@ -61,7 +61,7 @@ class TrollStronghold : Quest("Troll Stronghold",128, 127, 1, 317, 0, 1, 50) { if (stage >= 5) { line(player, "I have defeated the !!Troll Champion??", line++, true) } else if (stage >= 3) { - line(player, "I have to defeat the !!Troll Champion??", line++) + line(player, "I have accepted the !!Troll Champion's?? challenge.", line++) } if (stage in 5..7) { line++ diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.java b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.java deleted file mode 100644 index 0332c725b..000000000 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.java +++ /dev/null @@ -1,89 +0,0 @@ -package content.region.asgarnia.falador.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the dialogue used for sir tiffy. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class SirTiffyCashienDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code SirTiffyCashienDialogue} {@code Object}. - */ - public SirTiffyCashienDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code SirTiffyCashienDialogue} {@code Object}. - * @param player the player. - */ - public SirTiffyCashienDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new SirTiffyCashienDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What ho, sirrag.", "Spiffing day for a walk in the park, what?"); - stage = 1; - break; - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Spiffing?"); - stage = 2; - break; - case 2: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Absolutely, top-hole!", "Well, can't stay and chat all day, dontchaknow!", "Ta-ta for now!"); - stage = 10; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Erm...goodbye."); - stage = 4; - break; - case 4: - end(); - break; - case 10: - npc("Would you like to look at my wares?"); - stage++; - break; - case 11: - player("Yes, please."); - stage++; - break; - case 12: - npc.openShop(player); - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 2290 }; - } -} diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt new file mode 100644 index 000000000..40420b785 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt @@ -0,0 +1,106 @@ +package content.region.asgarnia.falador.dialogue + +import content.region.asgarnia.falador.quest.recruitmentdrive.RecruitmentDrive +import content.region.asgarnia.falador.quest.recruitmentdrive.SirTiffyCashienDialogueFile +import core.ServerConstants +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.NPCs + +@Initializable +class SirTiffyCashienDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + + // Completed Recruitment Drive & Start Wanted!! Quest + if (isQuestComplete(player!!, RecruitmentDrive.questName)) { + openDialogue(player, SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile(), npc) + return true + } + + // Recruitment Drive Quest + if (isQuestInProgress(player!!, RecruitmentDrive.questName, 1, 99)) { + openDialogue(player, SirTiffyCashienDialogueFile(), npc) + return true + } + + // Fallback to default. + when (stage) { + START_DIALOGUE -> player("Hello.").also { stage++ } + 1 -> npc(FacialExpression.FRIENDLY, "What ho, ${if (player.isMale) "sirrah" else "milady"}.", "Spiffing day for a walk in the park, what?").also { stage++ } + 2 -> player(FacialExpression.THINKING, "Spiffing?").also { stage++ } + 3 -> npc(FacialExpression.FRIENDLY, "Absolutely, top-hole!", "Well, can't stay and chat all day, dontchaknow!", "Ta-ta for now!").also { stage++ } + 4 -> player(FacialExpression.THINKING, "Erm...goodbye.").also { stage = END_DIALOGUE } + } + + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return SirTiffyCashienDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.SIR_TIFFY_CASHIEN_2290) + } +} + +// Move this to Wanted!! Quest. +class SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .npc(FacialExpression.HAPPY, "What ho, @g[sirrah,milady].", "Jolly good show on the old training grounds thingy,", "what?") + .options().let { optionBuilder -> + optionBuilder.option_playerl("Do you have any jobs for me yet?") + .npcl("Sorry dear @g[boy,gal] but we are still in the process of organising.") + .npcl("I'm sure that we will have something for you soon, so please feel free to check back later.") + // Started of Wanted! quest + .end() + optionBuilder.option("Can you explain the Gaze of Saradomin to me?") + .playerl("I don't really understand this 'Gaze of Saradomin' thing... Do you think you could explain what it does for me?") + .npcl("Certainly @g[sirrah,milady]! As you know, we Temple Knights are personally favoured by Saradomin himself.") + .npcl("And when I say personally favoured, I don't mean that sometime off in the future he's going to buy us all a drink!") + .npcl("He watches over each of us, and when we die he catches us as we fall, and ensures we arrive back at Falador castle safe and sound.") + .npcl("We usually lose some equipment when he does so, but it's a small price to pay to be hale and hearty again, what?") + .npcl("Some lucky fellows have a similar system going already, but when they die they spawn in that squalid little swamp village Lumbridge.") + .playerl("Yeah, what kind of person would want to spawn there... Certainly not me, and I never have! Honest!") + .npcl("Well, you should be glad that we offer you a step up then! Falador is clearly a far superior town to spend your time in!") + .npcl("Was there something else you wanted to ask good old Tiffy, @g[sirrah,milady]?") + .end() + optionBuilder.option("Can I buy some armour?") + .playerl("Can I buy some armour?") + // Recruitment Drive -> Initiate level, Slug Menace -> Proselyte level + .npcl("Of course dear @g[boy,gal]. I can sell you up to Initiate level items only I'm afraid.") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + optionBuilder.option_playerl("Can I switch respawns please?") + .npcl("I'm sorry dear @g[boy,gal], I'm afraid I can't switch your respawn point at the moment.") + .end() +// I have no idea how to do this properly. +// optionBuilder.option("Can I switch respawns please?") +// .branch { player -> if(player.properties.spawnLocation == Location(2997, 3375, 0)) { 1 } else { 0 } } +// .let { branch -> +// branch.onValue(1) +// .npcl("Ah, so you'd like to respawn in Falador, the good old homestead! Are you sure?") +// .endWith { _, player -> +// player.properties.spawnLocation = Location(2997, 3375, 0) +// } +// branch.onValue(0) +// .npcl("What? You're saying you want to respawn in Lumbridge? Are you sure?") +// .endWith { _, player -> +// player.properties.spawnLocation = ServerConstants.HOME_LOCATION +// } +// } + optionBuilder.option("Goodbye.") + .playerl("Well, see you around Tiffy.") + .npcl(FacialExpression.HAPPY,"Ta-ta for now, old bean!") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java index 33f2a41c5..ae5904dde 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java @@ -1,5 +1,6 @@ package content.region.asgarnia.falador.quest.blackknightsfortress; +import content.region.asgarnia.falador.quest.recruitmentdrive.SirAmikVarzeDialogueFile; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; @@ -8,6 +9,8 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; +import static core.api.ContentAPIKt.openDialogue; + /** * Represents the sir amik varze dialogue. * @author Vexia @@ -72,35 +75,7 @@ public class SirAmikVarzeDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (quest.getStage(player)) { case 100: - switch (stage) { - case 0: - interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "Hello, friend!"); - stage = 1; - break; - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_ASKING, "Do you have any other quests for me to do?"); - stage = 2; - break; - case 2: - interpreter.sendDialogues(npc, FacialExpression.HALF_THINKING, "Quests, eh?", "Well, I don't have anything on the go at the moment,", "but there is an organisation that is always looking for", "capable adventurers to assist them."); - stage = 3; - break; - case 3: - interpreter.sendDialogues(npc, FacialExpression.HAPPY, "Your excellent work sorting out those Black Knights", "means I will happily write you a letter of", "recommendation."); - stage = 4; - break; - case 4: - interpreter.sendDialogues(npc, FacialExpression.HALF_ASKING, "Would you like me to put your name forwards to", "them?"); - stage = 5; - break; - case 5: - interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "No thanks."); - stage = 6; - break; - case 6: - end(); - break; - } + openDialogue(player, new SirAmikVarzeDialogueFile(), npc); break; case 30: switch (stage) { diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/AlchemicalNotes.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/AlchemicalNotes.kt new file mode 100644 index 000000000..56eaa77d1 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/AlchemicalNotes.kt @@ -0,0 +1,248 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import content.global.handlers.iface.BookInterface +import content.global.handlers.iface.BookLine +import content.global.handlers.iface.Page +import content.global.handlers.iface.PageSet +import core.api.setAttribute +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items + +// https://www.youtube.com/watch?v=o-bAoxIYT-A 7:27 +@Initializable +class AlchemicalNotes : InteractionListener { + companion object { + private val TITLE = "Alchemical Reactions Study" + private val CONTENTS = arrayOf( + PageSet( + Page( + BookLine("Acetic acid and Cupric", 55), + BookLine("Sulphate:", 56), + BookLine("Endothermic.", 57), + BookLine("The Cupric is in ", 58), + BookLine("insufficient quantities to", 59), + BookLine("cause any noticeable", 60), + BookLine("reaction.", 61), + ), + Page( + BookLine("Acetic acid and Gypsum:", 66), + BookLine("Endothermic.", 67), + BookLine("Made a particularly bad", 68), + BookLine("smell, but little else that", 69), + BookLine("was productive.", 70), + ) + ), + PageSet( + Page( + BookLine("Acetic acid and Sodium", 55), + BookLine("Chloride:", 56), + BookLine("Endothermic.", 57), + BookLine("Very tasty when", 58), + BookLine("combined with fried", 59), + BookLine("potatoes at room", 60), + BookLine("temperature.", 61), + ), + Page( + BookLine("Acetic acid and", 66), + BookLine("Dihydrogen Monoxide:", 67), + BookLine("Endothermic.", 68), + BookLine("The Dihydrogen", 69), + BookLine("Monoxide served only to", 70), + BookLine("dilute the Acetic acid at", 71), + BookLine("room temperature.", 72), + ) + ), + PageSet( + Page( + BookLine("Acetic acid and Cupric", 55), + BookLine("Ore Powder:", 56), + BookLine("Endothermic.", 57), + BookLine("The powdered form of", 58), + BookLine("Cupric Ore allowed a", 59), + BookLine("lower than usual melting", 60), + BookLine("temperature, but the end", 61), + BookLine("product was non-usable.", 62), + ), + Page( + BookLine("Acetic acid and Tin Ore", 66), + BookLine("powder:", 67), + BookLine("Endothermic.", 68), + BookLine("Similar results to those", 69), + BookLine("made using Cupric Ore.", 70), + ) + ), + PageSet( + Page( + BookLine("Cupric Sulphate and", 55), + BookLine("Dihyrdogen Monoxide:", 56), + BookLine("Exothermic.", 57), + BookLine("A blue compound was", 58), + BookLine("produced, along with heat.", 59), + ), + Page( + BookLine("Cupric Sulphate and", 66), + BookLine("Gypsum:", 67), + BookLine("Endothermic.", 68), + BookLine("At room temperature, no", 69), + BookLine("useful product was", 70), + BookLine("created.", 71), + ) + ), + PageSet( + Page( + BookLine("Cupric Sulphate and", 55), + BookLine("Sodium Chloride:", 56), + BookLine("Endothermic.", 57), + BookLine("A pungent odour was", 58), + BookLine("released when combined.", 59), + ), + Page( + BookLine("Cupric Sulphate and", 66), + BookLine("Cupric Ore powder:", 67), + BookLine("Endothermic.", 68), + BookLine("The Cupric did not react", 69), + BookLine("with each other at room", 70), + BookLine("temperature.", 71), + ) + ), + PageSet( + Page( + BookLine("Cupric Sulphate and Tin", 55), + BookLine("Ore powder:", 56), + BookLine("Endothermic.", 57), + BookLine("Similar results to those", 58), + BookLine("shown with Cupric Ore,", 59), + BookLine("despite the increased", 60), + BookLine("solubility involved with", 61), + BookLine("the powdered form.", 62), + ), + Page( + BookLine("Gypsum and Dihydrogen", 66), + BookLine("Monoxide:", 67), + BookLine("Exothermic.", 68), + BookLine("A white liquid compound", 69), + BookLine("was formed, that quickly", 70), + BookLine("cooled at room", 71), + BookLine("temperature to a white", 72), + BookLine("heat resistant solid very", 73), + BookLine("similar to plaster.", 74), + BookLine("Heat was also produced,", 75), + BookLine("although not in the same", 76), + ) + ), + PageSet( + Page( + BookLine("quantity as Cupric", 55), + BookLine("Sulphate with Dihydrogen", 56), + BookLine("Monoxide", 57), + ), + Page( + BookLine("Gypsum and Sodium", 66), + BookLine("Chloride:", 67), + BookLine("Endothermic.", 68), + BookLine("The two did not seem to", 69), + BookLine("noticably mix together at", 70), + BookLine("room temperature.", 71), + ) + ), + PageSet( + Page( + BookLine("Gypsum and Culpric Ore:", 55), + BookLine("Endothermic.", 56), + BookLine("The gypsum seems quite", 57), + BookLine("resistant to most", 58), + BookLine("compounds at normal", 59), + BookLine("room temperature.", 60), + ), + Page( + BookLine("Gypsum and Tin Ore:", 66), + BookLine("Endothermic.", 67), + BookLine("Again, very similar results", 68), + BookLine("as those shown with", 69), + BookLine("Cupric Ore.", 70), + ) + ), + + PageSet( + Page( + BookLine("Sodium Chloride and", 55), + BookLine("Dihydrogen Monoxide:", 56), + BookLine("Endothermic.", 57), + BookLine("At room temperature, the", 58), + BookLine("Sodium Chloride dissolves", 59), + BookLine("quite easily. Dissolution is", 60), + BookLine("faster at higher", 61), + BookLine("temperatures.", 62), + ), + Page( + BookLine("Sodium Chloride and", 66), + BookLine("Cupric Ore:", 67), + BookLine("Endothermic.", 68), + BookLine("No visible combination at", 69), + BookLine("room temperature.", 70), + ) + ), + PageSet( + Page( + BookLine("Sodium Chloride and Tin", 55), + BookLine("Ore:", 56), + BookLine("Endothermic.", 57), + BookLine("Another very similar ", 58), + BookLine("result as with Cupric Ore.", 59), + ), + Page( + BookLine("Cupric Ore Powder and", 66), + BookLine("Tin Ore Powder:", 67), + BookLine("Endothermic.", 68), + BookLine("When both ores are in", 69), + BookLine("particulate form, a much", 70), + BookLine("lower than usual bonding", 71), + BookLine("temperature can be", 72), + BookLine("obtained.", 73), + BookLine("When combined at a", 74), + BookLine("moderate heat, (my", 75), + BookLine("laboratory heating", 76), + ) + ), + PageSet( + Page( + BookLine("apparatus) I was able to", 55), + BookLine("form liquid Bronze quite", 56), + BookLine("easily, which cooled to", 57), + BookLine("form a standard Bronze", 58), + BookLine("Bar at a temperature far", 60), + BookLine("lower than that required", 61), + BookLine("to produce in mass at a", 62), + BookLine("furnace.", 63), + ), + Page( + BookLine("Nitrous Monoxide:", 66), + BookLine("Was not able to perform", 67), + BookLine("an experimentation using", 68), + BookLine("this substance, as the", 69), + BookLine("gaseous form would", 70), + BookLine("always escape when the", 71), + BookLine("vial was opened.", 72), + ) + ) + ) + } + + private fun display(player:Player, pageNum: Int, buttonID: Int) : Boolean { + BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS) + return true + } + + + override fun defineListeners() { + on(Items.ALCHEMICAL_NOTES_5588, IntType.ITEM, "read") { player, _ -> + setAttribute(player, "bookInterfaceCallback", ::display) + setAttribute(player, "bookInterfaceCurrentPage", 0) + display(player, 0, 0) + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/LadyTableDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/LadyTableDialogue.kt new file mode 100644 index 000000000..b1386266f --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/LadyTableDialogue.kt @@ -0,0 +1,114 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.system.task.Pulse +import org.rs09.consts.Components +import org.rs09.consts.NPCs + +class LadyTableDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, LadyTableDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return LadyTableDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.LADY_TABLE_2283) + } +} + +class LadyTableDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile(), InteractionListener { + companion object { + const val statueVarbit = 658 + const val attributeStatueStateNumber = "quest:recruitmentdrive-statuestatenumber" + val statueArray = intArrayOf(0, 7308, 7307, 7306, 7305, 7304, 7303, 7312, 7313, 7314, 7311, 7310, 7309) + } + + override fun defineListeners() { + + on(statueArray, IntType.SCENERY, "touch") { player, node -> + if( node.id == statueArray[getAttribute(player, attributeStatueStateNumber, 0)]) { + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, false, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + return@on true + } + } else { + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + openDialogue(player, LadyTableDialogueFile(2), NPC(NPCs.LADY_TABLE_2283)) + return@on true + } + } + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) { + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, false, "Please step through the portal to meet your next", "challenge.") + } + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) { + openDialogue(player, LadyTableDialogueFile(2), NPC(NPCs.LADY_TABLE_2283)) + } + return@on true + } + + } + override fun create(b: DialogueBuilder) { + b.onPredicate { player -> dialogueNum == 1 } + .endWith { _, player -> + submitWorldPulse(object : Pulse() { + var counter = 0 + override fun pulse(): Boolean { + when (counter++) { + 0 -> { + lock(player, 15) + setAttribute(player, attributeStatueStateNumber, (1..12).random()) + setVarbit(player, statueVarbit, getAttribute(player, attributeStatueStateNumber, 0)) + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"Welcome, @name.", "This room will test your observation skills.") + } + 5 -> { + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true, "Study the statues closely.", "There is one missing statue in this room.") + } + 10 -> { + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true, "We will also mix the order up a little, to make things", "interesting for you!") + } + 15 -> { + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"You have 10 seconds to memorise the statues... starting", "NOW!") + } + 20 -> { + closeDialogue(player) + } + 31 -> { // From 15 -> 16 * 600ms = 10 seconds + openOverlay(player,Components.FADE_TO_BLACK_120) + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"We will now dim the lights and bring the missing statue", "back in.") + } + 34 -> { // From 15 -> 16 * 600ms = 10 seconds + setVarbit(player, statueVarbit, 0) + openOverlay(player,Components.FADE_FROM_BLACK_170) + sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"Please touch the statue you think has been added.") + return true + } + } + return false + } + }) + } + + b.onPredicate { player -> dialogueNum == 2 || (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) } + .betweenStage { _, player, _, _ -> + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + .npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.") + .endWith { _, player -> + removeAttribute(player, attributeStatueStateNumber) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + RecruitmentDriveListeners.FailTestCutscene(player).start() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MissCheeversDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MissCheeversDialogue.kt new file mode 100644 index 000000000..21fed50ba --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MissCheeversDialogue.kt @@ -0,0 +1,512 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +@Initializable +class MissCheeversDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MissCheeversDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return MissCheeversDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.MISS_CHEEVERS_2288) + } +} + +class MissCheeversDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> dialogueNum == 0 } + .playerl(FacialExpression.FRIENDLY,"Can you give me any help?") + .npcl(FacialExpression.FRIENDLY,"No, I am sorry, but that is forbidden by our rules.") + .npcl(FacialExpression.FRIENDLY,"If you are having a particularly tough time of it, I suggest you leave and come back later when you are in a more receptive frame of mind.") + .npcl(FacialExpression.FRIENDLY,"Sometimes a break from concentration will yield fresh insight. Our aim is to test you, but not to the point of frustration!") + .playerl(FacialExpression.FRIENDLY,"Okay, thanks!") + .end() + + + b.onPredicate { _ -> dialogueNum == 1 } + .betweenStage { _, player, _, _ -> + setVarbit(player, MissCheeversRoomListeners.doorVarbit, 0) + removeAttribute(player, MissCheeversRoomListeners.attributebook) + removeAttribute(player, MissCheeversRoomListeners.attributemagnet) + removeAttribute(player, MissCheeversRoomListeners.attributeKnife) + removeAttribute(player, MissCheeversRoomListeners.attributeShears) + removeAttribute(player, MissCheeversRoomListeners.attributeTin) + removeAttribute(player, MissCheeversRoomListeners.attributeChisel) + removeAttribute(player, MissCheeversRoomListeners.attributeWire) + + removeAttribute(player, MissCheeversRoomListeners.attribute3VialsOfLiquid) + + MissCheeversRoomListeners.Companion.Vials.vialMap.map { + removeAttribute(player, it.value.attribute) + } + + MissCheeversRoomListeners.Companion.DoorVials.doorVialsRequiredMap.map { + removeAttribute(player, it.value.attribute) + } + } + .npcl(FacialExpression.FRIENDLY,"Greetings, @name. Welcome to my challenge.") + .npcl(FacialExpression.FRIENDLY,"All you need to do is leave from the opposite door to where you came in by.") + .npcl(FacialExpression.FRIENDLY,"I will warn you that this is more complicated than it may at first appear.") + .npcl(FacialExpression.FRIENDLY,"I should also warn you that there are limited supplies of the items in this room, so think carefully before using them, you may find yourself stuck and have to leave to start again!") + .npcl(FacialExpression.FRIENDLY,"Best of luck!") + .end() + } +} + +class MissCheeversRoomListeners : InteractionListener { + companion object { + + const val doorVarbit = 686 + + const val attributebook = "quest:recruitmentdrive-book" + const val attributemagnet = "quest:recruitmentdrive-magnet" + const val attributeKnife = "quest:recruitmentdrive-knife" + const val attributeShears = "quest:recruitmentdrive-shears" + const val attributeTin = "quest:recruitmentdrive-tin" + const val attributeChisel = "quest:recruitmentdrive-chisel" + const val attributeWire = "quest:recruitmentdrive-wire" + + const val attribute3VialsOfLiquid = "quest:recruitmentdrive-3vialsofliquid" + + /** Enums to map canoes to related properties. */ + enum class Vials(val itemId: Int, val attribute: String) { + CUPRIC_SULPHATE_5577(Items.CUPRIC_SULPHATE_5577, "quest:recruitmentdrive-cupricsulphate"), + ACETIC_ACID_5578(Items.ACETIC_ACID_5578, "quest:recruitmentdrive-aceticacid"), + GYPSUM_5579(Items.GYPSUM_5579, "quest:recruitmentdrive-gypsum"), + SODIUM_CHLORIDE_5580(Items.SODIUM_CHLORIDE_5580, "quest:recruitmentdrive-sodiumchloride"), + NITROUS_OXIDE_5581(Items.NITROUS_OXIDE_5581, "quest:recruitmentdrive-nitrousoxide"), + VIAL_OF_LIQUID_5582(Items.VIAL_OF_LIQUID_5582, "quest:recruitmentdrive-vialofliquid"), + TIN_ORE_POWDER_5583(Items.TIN_ORE_POWDER_5583, "quest:recruitmentdrive-tinorepowder"), + CUPRIC_ORE_POWDER_5584(Items.CUPRIC_ORE_POWDER_5584, "quest:recruitmentdrive-cupricorepowder"); + + companion object { + @JvmField + val vialMap = Vials.values().associateBy { it.itemId } + } + } + + + /** Enums to map canoes to related properties. */ + enum class DoorVials(val itemId: Int, val attribute: String) { + CUPRIC_SULPHATE_5577(Items.CUPRIC_SULPHATE_5577, "quest:recruitmentdrive-doorcupricsulphate"), + ACETIC_ACID_5578(Items.ACETIC_ACID_5578, ""), + SODIUM_CHLORIDE_5580(Items.SODIUM_CHLORIDE_5580, ""), + VIAL_OF_LIQUID_5582(Items.VIAL_OF_LIQUID_5582, "quest:recruitmentdrive-doorvialofliquid"); + + companion object { + @JvmField + val doorVialsArray = DoorVials.values().map { it.itemId }.toIntArray() + val doorVialsMap = DoorVials.values().associateBy { it.itemId } + val doorVialsRequiredMap = DoorVials.values().associateBy { it.itemId }.filter { it.value.attribute != "" } + } + } + + + fun searchingHelper(player: Player, attributeCheck: String, item: Int, searchingDescription: String, objectDescription: String) { + queueScript(player, 0, QueueStrength.WEAK) { stage: Int -> + when (stage) { + 0 -> { + sendMessage(player, searchingDescription) + return@queueScript delayScript(player, 2) + } + 1 -> { + if (attributeCheck != "" && !getAttribute(player, attributeCheck, false)) { + setAttribute(player, attributeCheck, true) + addItem(player, item) + sendMessage(player, objectDescription) + } else { + sendMessage(player, "You don't find anything interesting.") + } + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + } + + override fun defineListeners() { + + /** Obtainable Items */ + + on(Scenery.OLD_BOOKSHELF_7327, IntType.SCENERY, "search") { player, _ -> + searchingHelper(player, attributemagnet, Items.MAGNET_5604, "You search the bookshelves...", "Hidden amongst the books you find a magnet.") + return@on true + } + + on(Scenery.OLD_BOOKSHELF_7328, IntType.SCENERY, "search") { player, _ -> + searchingHelper(player, attributebook, Items.ALCHEMICAL_NOTES_5588, "You search the bookshelves...", "You find a book that looks like it might be helpful.") + return@on true + } + + on(Scenery.OLD_BOOKSHELF_7329, IntType.SCENERY, "search") { player, _ -> + searchingHelper(player, attributeKnife, Items.KNIFE_5605, "You search the bookshelves...", "Hidden amongst the books you find a knife.") + return@on true + } + + on(Scenery.OLD_BOOKSHELF_7330, IntType.SCENERY, "search") { player, _ -> + searchingHelper(player, "", 0, "You search the bookshelves...", "") + return@on true + } + + on(Scenery.SHELVES_7333, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.ACETIC_ACID_5578]!!.attribute, false)) { vialList.add(Items.ACETIC_ACID_5578) } + if (!getAttribute(player, Vials.vialMap[Items.VIAL_OF_LIQUID_5582]!!.attribute, false)) { vialList.add(Items.VIAL_OF_LIQUID_5582) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7334, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.CUPRIC_SULPHATE_5577]!!.attribute, false)) { vialList.add(Items.CUPRIC_SULPHATE_5577) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7335, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.GYPSUM_5579]!!.attribute, false)) { vialList.add(Items.GYPSUM_5579) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7336, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.SODIUM_CHLORIDE_5580]!!.attribute, false)) { vialList.add(Items.SODIUM_CHLORIDE_5580) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7337, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.NITROUS_OXIDE_5581]!!.attribute, false)) { vialList.add(Items.NITROUS_OXIDE_5581) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7338, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.TIN_ORE_POWDER_5583]!!.attribute, false)) { vialList.add(Items.TIN_ORE_POWDER_5583) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7339, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + if (!getAttribute(player, Vials.vialMap[Items.CUPRIC_ORE_POWDER_5584]!!.attribute, false)) { vialList.add(Items.CUPRIC_ORE_POWDER_5584) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray())) + return@on true + } + + on(Scenery.SHELVES_7340, IntType.SCENERY, "search") { player, _ -> + val vialList = ArrayList() + val total = getAttribute(player, attribute3VialsOfLiquid, 3) + for (i in 1..total) { vialList.add(Items.VIAL_OF_LIQUID_5582) } + openDialogue(player, VialShelfDialogueFile(vialList.toIntArray(), attribute3VialsOfLiquid)) + return@on true + } + + on(Scenery.CRATE_7347, IntType.SCENERY, "search") { player, node -> + if (node.location == Location(2476, 4943)) { + searchingHelper(player, attributeTin, Items.TIN_5600, "You search the crate...", "Inside the crate you find a tin.") + } else { + searchingHelper(player, "", 0, "You search the crate...", "") + } + return@on true + } + + on(Scenery.CRATE_7348, IntType.SCENERY, "search") { player, node -> + if (node.location == Location(2476, 4937)) { + searchingHelper(player, attributeChisel, Items.CHISEL_5601, "You search the crate...", "Inside the crate you find a chisel.") + } else { + searchingHelper(player, "", 0, "You search the crate...", "") + } + return@on true + } + + on(Scenery.CRATE_7349, IntType.SCENERY, "search") { player, node -> + if (node.location == Location(2475, 4943)) { + searchingHelper(player, attributeWire, Items.BRONZE_WIRE_5602, "You search the crate...", "Inside the crate you find some wire.") + } else { + searchingHelper(player, "", 0, "You search the crate...", "") + } + return@on true + } + + on(Scenery.CLOSED_CHEST_7350, IntType.SCENERY, "open") { player, node -> + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.OPEN_CHEST_7351, 100) + return@on true + } + + on(Scenery.OPEN_CHEST_7351, IntType.SCENERY, "search") { player, _ -> + searchingHelper(player, attributeShears, Items.SHEARS_5603, "You search the chest...", "Inside the chest you find some shears.") + return@on true + } + + on(Scenery.OPEN_CHEST_7351, IntType.SCENERY, "close") { player, node -> + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CLOSED_CHEST_7350, -1) + return@on true + } + + /** Combining Items the correct way */ + + onUseWith(ITEM, Items.TIN_5600, Items.GYPSUM_5579) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You empty the vial into the tin.") + addItemOrDrop(player, Items.TIN_5592) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5592, Items.VIAL_OF_LIQUID_5582) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You empty the vial into the tin.") + sendMessage(player, "You notice the tin gets quite warm as you do this.") + sendMessage(player, "A lumpy white mixture is made, that seems to be hardening.") + addItemOrDrop(player, Items.TIN_5593) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(SCENERY, Items.TIN_5593, Scenery.KEY_7346) { player, used, _ -> + if(removeItem(player, used.id)) { + sendMessage(player, "You make an impression of the key as the white mixture hardens.") + addItemOrDrop(player, Items.TIN_5594) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5594, Items.TIN_ORE_POWDER_5583) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You pour the vial into the impression of the key.") + addItemOrDrop(player, Items.TIN_5595) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5595, Items.CUPRIC_ORE_POWDER_5584) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You pour the vial into the impression of the key.") + addItemOrDrop(player, Items.TIN_5597) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5594, Items.CUPRIC_ORE_POWDER_5584) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You pour the vial into the impression of the key.") + addItemOrDrop(player, Items.TIN_5596) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5596, Items.TIN_ORE_POWDER_5583) { player, used, with -> + if(removeItem(player, used.id) && removeItem(player, with.id)) { + sendMessage(player, "You pour the vial into the impression of the key.") + addItemOrDrop(player, Items.TIN_5597) + addItemOrDrop(player, Items.VIAL_229) + } + return@onUseWith true + } + + onUseWith(SCENERY, Items.TIN_5597, Scenery.BUNSEN_BURNER_7332) { player, used, _ -> + if(removeItem(player, used.id)) { + sendMessage(player, "You heat the two powdered ores together in the tin.") + sendMessage(player, "You make a duplicate of the key in bronze.") + addItemOrDrop(player, Items.TIN_5598) + } + return@onUseWith true + } + + onUseWith(ITEM, Items.TIN_5598, Items.BRONZE_WIRE_5602, Items.CHISEL_5601, Items.KNIFE_5605) { player, used, with -> + if(removeItem(player, used.id)) { + sendMessage(player, "You prise the duplicate key out of the tin.") + addItemOrDrop(player, Items.TIN_5594) + addItemOrDrop(player, Items.BRONZE_KEY_5585) + } + return@onUseWith true + } + + onUseWith(SCENERY, Items.METAL_SPADE_5586, Scenery.BUNSEN_BURNER_7332) { player, used, _ -> + if(removeItem(player, used.id)) { + sendMessage(player, "You burn the wooden handle away from the spade...") + sendMessage(player, "...and are left with a metal spade with no handle.") + addItemOrDrop(player, Items.ASHES_592) + addItemOrDrop(player, Items.METAL_SPADE_5587) + } + return@onUseWith true + } + + + on(Scenery.STONE_DOOR_7343, SCENERY, "study") { player, node -> + sendDialogueLines(player, "There is a stone slab here obstructing the door.", "There is a small hole in the slab that looks like it might be for a handle.") + sendMessage(player, "It's nearly a perfect fit!") + return@on true + } + + onUseWith(SCENERY, Items.METAL_SPADE_5587, Scenery.STONE_DOOR_7343) { player, used, _ -> + if(removeItem(player, used.id)) { + sendMessage(player, "You slide the spade into the hole in the stone...") + sendMessage(player, "It's nearly a perfect fit!") + setVarbit(player, doorVarbit, 1) + } + return@onUseWith true + } + + onUseWith(SCENERY, DoorVials.doorVialsArray, Scenery.STONE_DOOR_7344) { player, used, _ -> + if(removeItem(player, used.id)) { + setAttribute(player, DoorVials.doorVialsMap[used.id]!!.attribute, true) + sendMessage(player, "You pour the vial onto the flat part of the spade.") + } + if (DoorVials.doorVialsRequiredMap.all { getAttribute(player, it.value.attribute, false) }) { + sendMessage(player, "Something caused a reaction when mixed!") + sendMessage(player, "The spade gets hotter, and expands slightly.") + setVarbit(player, doorVarbit, 2) + } + return@onUseWith true + } + + on(Scenery.STONE_DOOR_7344, SCENERY, "pull-spade") { player, node -> + if (DoorVials.doorVialsRequiredMap.all { getAttribute(player, it.value.attribute, false) }) { + sendMessage(player, "You pull on the spade...") + sendMessage(player, "It works as a handle, and you swing the stone door open.") + setVarbit(player, doorVarbit, 3) + } else { + sendMessage(player, "You pull on the spade...") + sendMessage(player, "It comes loose, and slides out of the hole in the stone.") + addItemOrDrop(player, Items.METAL_SPADE_5587) + setVarbit(player, doorVarbit, 0) + } + return@on true + } + + on(Scenery.OPEN_DOOR_7345, SCENERY, "walk-through") { player, node -> + if(player.location.x <= 2477) { + player.walkingQueue.addPath(2477, 4940) + player.walkingQueue.addPath(2478, 4940) + } else { + player.walkingQueue.addPath(2477, 4940) + } + return@on true + } + + + } + +} + +private class VialShelfDialogueFile(private val flaskIdsArray: IntArray, private val specialAttribute: String? = null) : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true }.branch { _ -> flaskIdsArray.size }.let { branch -> + + branch.onValue(3) + // This is the only shelf with 3 vials of water. + .line("There are three vials on this shelf.") + .options("Take the vials?").let { optionBuilder -> + optionBuilder.option("Take one vial.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 1) + print(getAttribute(player, specialAttribute, 3)) + } + } + optionBuilder.option("Take two vials.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + addItemOrDrop(player, flaskIdsArray[1]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 2) + } + } + optionBuilder.option("Take all three vials.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + addItemOrDrop(player, flaskIdsArray[1]) + addItemOrDrop(player, flaskIdsArray[2]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 3) + } + } + optionBuilder.option("Don't take a vial.") + .end() + } + branch.onValue(2) + .line("There are two vials on this shelf.") + .options("Take the vials?").let { optionBuilder -> + optionBuilder.option("Take the first vial.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 1) + } else { + setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true) + } + } + optionBuilder.option("Take the second vial.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[1]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 1) + } else { + setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[1]]!!.attribute, true) + } + } + optionBuilder.option("Take both vials.") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + addItemOrDrop(player, flaskIdsArray[1]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 2) + } else { + setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true) + setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[1]]!!.attribute, true) + } + } + } + + branch.onValue(1) + .line("There is a vial on this shelf.") + .options("Take the vial?").let { optionBuilder -> + optionBuilder.option("YES") + .endWith { _, player -> + addItemOrDrop(player, flaskIdsArray[0]) + if (specialAttribute != null) { + setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 1) - 1) + } else { + setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true) + } + } + optionBuilder.option("NO") + .end() + } + + branch.onValue(0) + .line("There is nothing of interest on these shelves.") + } + } +} diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MsHynnTerprettDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MsHynnTerprettDialogue.kt new file mode 100644 index 000000000..91be2f7a7 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/MsHynnTerprettDialogue.kt @@ -0,0 +1,154 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class MsHynnTerprettDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MsHynnTerprettDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return MsHynnTerprettDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.MS_HYNN_TERPRETT_2289) + } +} + +class MsHynnTerprettDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + companion object { + const val attributeRandomRiddle = "quest:recruitmentdrive-randomriddle" + const val attributeRecentlyCorrect = "quest:recruitmentdrive-recentlycorrect" + } + + override fun create(b: DialogueBuilder) { + + b.onPredicate { player -> true }.branch { player -> + if (getAttribute(player, attributeRecentlyCorrect, false)) { + return@branch 3 + } else if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) { + return@branch 2 + } else if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) { + return@branch 1 + } else { + return@branch 0 + } + }.let { branch -> + /** Failed Branch */ + val failedStage = b.placeholder() + failedStage.builder() + .npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.") + .endWith { _, player -> + removeAttribute(player, attributeRandomRiddle) + removeAttribute(player, attributeRecentlyCorrect) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + RecruitmentDriveListeners.FailTestCutscene(player).start() + } + /** Passed Branch */ + val passedStage = b.placeholder() + passedStage.builder() + .betweenStage { _, player, _, _ -> + removeAttribute(player, attributeRandomRiddle) + removeAttribute(player, attributeRecentlyCorrect) + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + } + } + .npc("Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + .end() + + branch.onValue(3) // Passed stage + .goto(passedStage) + branch.onValue(2) // Failed stage + .goto(failedStage) + branch.onValue(1) // Already passed stage + .npc("You certainly have the wits to be a Temple Knight.", "Pass on through the portal to find your next challenge.") + .end() + branch.onValue(0) + .betweenStage { _, player, _, _ -> + if (getAttribute(player, attributeRandomRiddle, -1) !in 0..4) { + setAttribute(player, attributeRandomRiddle, (0..4).random()) + } + } + .npc("Greetings, @name.", "I am here to test your wits with a simple riddle.") + .branch { player -> getAttribute(player, attributeRandomRiddle, 0) } + .let { branch -> + branch.onValue(0) + .npc(FacialExpression.THINKING, "Here is my riddle:", "I estimate there to be one million inhabitants in the world", "of @servername, creatures and people both.") + .npc(FacialExpression.THINKING, "What number would you get if you multiply", "the number of fingers on everything's left hand, to the", "nearest million?") + .manualStage { _, player, _, _ -> + sendInputDialogue(player, false, "Enter the amount:") { value: Any -> + if(value == "0") { + setAttribute(player, attributeRecentlyCorrect, true) + } else { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + openDialogue(player, MsHynnTerprettDialogueFile(), NPC(NPCs.MS_HYNN_TERPRETT_2289)) + return@sendInputDialogue + } + } + .end() + + branch.onValue(1) + .npc(FacialExpression.THINKING, "Here is my riddle:", "Which of the following statements is true?") + .options().let { optionBuilder -> + optionBuilder.option("The number of false statements here is one.").goto(failedStage) + optionBuilder.option("The number of false statements here is two.").goto(failedStage) + optionBuilder.option("The number of false statements here is three.").goto(passedStage) + optionBuilder.option("The number of false statements here is four.").goto(failedStage) + } + + branch.onValue(2) + .npc(FacialExpression.THINKING, "Here is my riddle:", "I have both a husband and daughter.") + .npc(FacialExpression.THINKING, "My husband is four times older than my daughter. ", "In twenty years time, he will be twice as old as my", "daughter.") + .npc(FacialExpression.THINKING, "How old is my daughter now?") + .manualStage { _, player, _, _ -> + sendInputDialogue(player, true, "Enter the amount:") { value: Any -> + if(value == 10) { + setAttribute(player, attributeRecentlyCorrect, true) + } else { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + openDialogue(player, MsHynnTerprettDialogueFile(), NPC(NPCs.MS_HYNN_TERPRETT_2289)) + return@sendInputDialogue + } + } + .end() + + branch.onValue(3) + .npc(FacialExpression.THINKING, "Here is my riddle:", "Imagine that you have been captured by an enemy.", "You are to be killed, but in a moment of mercy, the", "enemy has allowed you to pick your own demise.") + .npc(FacialExpression.THINKING, "Your first choice is to be drowned in a lake of acid.") + .npc(FacialExpression.THINKING, "Your second choice is to be burned on a fire.") + .npc(FacialExpression.THINKING, "Your third choice is to be thrown to a pack of wolves", "that have not been fed in over a month.") + .npc(FacialExpression.THINKING, "Your final choice of fate is to be thrown from the walls", "of a castle, many hundreds of feet high.") + .npc(FacialExpression.THINKING, "Which fate would you be wise to choose?") + .options().let { optionBuilder -> + optionBuilder.option("The lake of acid.").goto(failedStage) + optionBuilder.option("The large fire.").goto(failedStage) + optionBuilder.option("The wolves.").goto(passedStage) + optionBuilder.option("The castle walls.").goto(failedStage) + } + + branch.onValue(4) + .npc(FacialExpression.THINKING, "Here is my riddle:", "I dropped four identical stones, into four identical", "buckets, each containing an identical amount of water.") + .npc(FacialExpression.THINKING, "The first bucket's water was at 32 degrees Fahrenheit,", "the second was at 33 degrees, the third at 34 and the", "fourth was at 35 degrees.") + .npc(FacialExpression.THINKING, "Which bucket's stone dropped to the bottom of the bucket", "last?") + .options().let { optionBuilder -> + optionBuilder.option("Bucket A (32 degrees)").goto(passedStage) + optionBuilder.option("Bucket B (33 degrees)").goto(failedStage) + optionBuilder.option("Bucket C (34 degrees)").goto(failedStage) + optionBuilder.option("Bucket D (35 degrees)").goto(failedStage) + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt new file mode 100644 index 000000000..6a7b174cd --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt @@ -0,0 +1,133 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items + +/** + * Recruitment Drive Quest + * + * https://www.youtube.com/watch?v=0yvFREeXNn0 - Quest start log only. + * https://www.youtube.com/watch?v=lNlSiUvPL1o - Very good + * https://www.youtube.com/watch?v=OGWpX1WqpKM 10:12 - Final congrats page. + * https://www.youtube.com/watch?v=nu4OAswRcGg - Speaking to Tiffy after the quest (IMPORTANT!) + * https://www.youtube.com/watch?v=srFMJa4nuX0 1:47 blur ass quest log again + * https://www.youtube.com/watch?v=L7NdDTWa-1Q HAZEEL's CULT + * 1 - Speak to Sir Amik Varze. + * 2 - Sent to secret training ground. + * 3 - Finish all stages. + * 100 - Finish by talking to Tiffy. + */ +@Initializable +class RecruitmentDrive : Quest("Recruitment Drive", 103, 102, 1, 496, 0, 1, 2) { + companion object { + const val questName = "Recruitment Drive" + const val attributeOriginalGender = "/save:quest:recruitmentdrive-originalgender" + + // Stage state: (0: reset), (1: passed), (-1: failed) + const val attributeStagePassFailState = "/save:quest:recruitmentdrive-stagestate" + const val attributeCurrentStage = "/save:quest:recruitmentdrive-currentstage" + const val attributeStage1 = "/save:quest:recruitmentdrive-stage1" + const val attributeStage2 = "/save:quest:recruitmentdrive-stage2" + const val attributeStage3 = "/save:quest:recruitmentdrive-stage3" + const val attributeStage4 = "/save:quest:recruitmentdrive-stage4" + const val attributeStage5 = "/save:quest:recruitmentdrive-stage5" + val attributeStageArray = arrayOf(attributeStage1, attributeStage2, attributeStage3, attributeStage4, attributeStage5) + } + + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player, questName) > 0 + + if(!started){ + line(player, "I can start this quest by speaking to !!Sir Amik Varze??,", line++) + line(player, "upstairs in !!Falador Castle,??", line++) + if (isQuestComplete(player, "Druidic Ritual")) { + line(player, "with the Druidic Ritual Quest completed,", line++, true) + } else { + line(player, "with the !!Druidic Ritual Quest?? completed,", line++) + } + if (isQuestComplete(player, "Black Knights' Fortress")) { + line(player, "and since I have completed the Black Knights' Fortress", line++, true) + line(player, "Quest.", line++, true) + } else { + line(player, "and after I have completed the !!Black Knights' Fortress??", line++) + line(player, "Quest.", line++) + } + } else { + line(player, "Sir Amik Varze told me that he had put my name forward as", line++, true) + line(player, "a potential member of some mysterious organisation.", line++, true) + + if (stage >= 2) { + } else if (stage >= 1) { + line(player, "I should head to !!Falador Park?? to meet my !!Contact?? so that I", line++, false) + line(player, "can begin my !!testing for the job??", line++, false) + } + + if (stage >= 3) { + line(player, "I went to Falador Park, and met a strange old man named", line++, true) + line(player, "Tiffy.", line++, true) + line(player, "He sent me to a secret training ground, where my wits", line++, true) + line(player, "were thoroughly tested.", line++, true) + line(player, "Luckily, I was too smart to fall for any of their little tricks,", line++, true) + line(player, "and passed the test with flying colours.", line++, true) + } else if (stage >= 2) { + line(player, "I went to !!Falador Park??, and met a strange old man named", line++, false) + line(player, "!!Tiffy??.", line++, false) + line(player, "He sent me to a !!secret training ground??, where my wits", line++, false) + line(player, "were thoroughly tested.", line++, false) + } + + if (stage >= 4) { + line(player, "I am now an official member of the Temple Knights,", line++, true) + line(player, "although I have to wait for the paperwork to go through", line++, true) + line(player, "before I can commence working for them.", line++, true) + } else if (stage >= 3) { + line(player, "I should talk to !!Tiffy?? to become a Temple Knight.", line++, false) + } + if (stage >= 100) { + line++ + line(player,"QUEST COMPLETE!", line) + } + } + } + + override fun reset(player: Player) { + removeAttribute(player, attributeOriginalGender) + removeAttribute(player, attributeStagePassFailState) + removeAttribute(player, attributeCurrentStage) + removeAttribute(player, attributeStage1) + removeAttribute(player, attributeStage2) + removeAttribute(player, attributeStage3) + removeAttribute(player, attributeStage4) + removeAttribute(player, attributeStage5) + } + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have passed the Recruitment Drive!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.INITIATE_SALLET_5574, 230, 277, 5) + + drawReward(player, "1 Quest Point", ln++) + drawReward(player, "1000 Prayer, Herblore and", ln++) + drawReward(player, "Agility XP", ln++) + drawReward(player, "Gaze of Saradomin", ln++) + drawReward(player, "Temple Knight's Initiate Helm", ln) + + rewardXP(player, Skills.PRAYER, 1000.0) + rewardXP(player, Skills.HERBLORE, 1000.0) + rewardXP(player, Skills.AGILITY, 1000.0) + addItem(player, Items.INITIATE_SALLET_5574) + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt new file mode 100644 index 000000000..f46d9c80d --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt @@ -0,0 +1,316 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import core.ServerConstants +import core.api.* +import core.game.activity.Cutscene +import core.game.dialogue.FacialExpression +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction +import core.net.packet.PacketRepository +import core.net.packet.context.MinimapStateContext +import core.net.packet.out.MinimapState +import org.rs09.consts.* + +class RecruitmentDriveListeners : InteractionListener { + companion object { + + enum class Stages(val npc: Int, val startLocation: Location, val startWalkLocation: Location, val quitPortal: Int, val successDoor: Int) { + SIR_SPISHYUS(NPCs.SIR_SPISHYUS_2282, Location(2490, 4972), Location(2489, 4972), Scenery.PORTAL_7272, Scenery.DOOR_7274), + LADY_TABLE(NPCs.LADY_TABLE_2283, Location(2460, 4979), Location(2459, 4979), Scenery.PORTAL_7288, Scenery.DOOR_7302), + SIR_KUAM_FERENTSE(NPCs.SIR_KUAM_FERENTSE_2284, Location(2455, 4964), Location(2456, 4964), Scenery.PORTAL_7315, Scenery.DOOR_7317), + SIR_TINLEY(NPCs.SIR_TINLEY_2286, Location(2471, 4956), Location(2472, 4956), Scenery.PORTAL_7318, Scenery.DOOR_7320), + SIR_REN_ITCHOOD(NPCs.SIR_REN_ITCHOOD_2287, Location(2439, 4956), Location(2440, 4956), Scenery.PORTAL_7321, Scenery.DOOR_7323), + MISS_CHEEVERS(NPCs.MISS_CHEEVERS_2288, Location(2467, 4940), Location(2468, 4940), Scenery.PORTAL_7324, Scenery.DOOR_7326), + MS_HYNN_TERPRETT(NPCs.MS_HYNN_TERPRETT_2289, Location(2451, 4935), Location(2451, 4936), Scenery.PORTAL_7352, Scenery.DOOR_7354); + + companion object { + @JvmField + val indexMap = Stages.values().associateBy { it.ordinal } + val indexArray = Stages.indexMap.keys.map { it } + val quitPortalArray = Stages.indexMap.values.map { it.quitPortal }.toIntArray() + val successDoorArray = Stages.indexMap.values.map { it.successDoor }.toIntArray() + } + } + + fun shuffleStages(player: Player) { + // Obtain an array to shuffle. Must be at least [5] long. + val stagesArrayToShuffle = intArrayOf(0,1,2,3,4,5,6) // Stages.indexArray.toIntArray() + stagesArrayToShuffle.shuffle() + setAttribute(player, RecruitmentDrive.attributeStage1, stagesArrayToShuffle[0]) + setAttribute(player, RecruitmentDrive.attributeStage2, stagesArrayToShuffle[1]) + setAttribute(player, RecruitmentDrive.attributeStage3, stagesArrayToShuffle[2]) + setAttribute(player, RecruitmentDrive.attributeStage4, stagesArrayToShuffle[3]) + setAttribute(player, RecruitmentDrive.attributeStage5, stagesArrayToShuffle[4]) + setAttribute(player, RecruitmentDrive.attributeCurrentStage, 0) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + } + + fun callStartingDialogues (player: Player, npc: Int) { + when (npc) { + NPCs.SIR_SPISHYUS_2282 -> openDialogue(player, SirSpishyusDialogueFile(1), NPC(npc)) + NPCs.LADY_TABLE_2283 -> openDialogue(player, LadyTableDialogueFile(1), NPC(npc)) + NPCs.SIR_KUAM_FERENTSE_2284 -> openDialogue(player, SirKuamFerentseDialogueFile(1), NPC(npc)) + NPCs.SIR_TINLEY_2286 -> openDialogue(player, SirTinleyDialogueFile(1), NPC(npc)) + NPCs.SIR_REN_ITCHOOD_2287 -> openDialogue(player, SirRenItchwoodDialogueFile(1), NPC(npc)) + NPCs.MISS_CHEEVERS_2288 -> openDialogue(player, MissCheeversDialogueFile(1), NPC(npc)) + NPCs.MS_HYNN_TERPRETT_2289 -> openDialogue(player, MsHynnTerprettDialogueFile(1), NPC(npc)) + } + } + } + + override fun defineListeners() { + + on(Stages.quitPortalArray, IntType.SCENERY, "use") { player, node -> + FailTestCutscene(player).start() + return@on true + } + + on(Stages.successDoorArray, IntType.SCENERY, "open") { player, node -> + // This is specially for Miss Cheevers + if (inInventory(player, Items.BRONZE_KEY_5585)) { + sendMessage(player, "You use the duplicate key you made to unlock the door.") + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + } + // Success Door + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) { + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + setAttribute(player, RecruitmentDrive.attributeCurrentStage, getAttribute(player, RecruitmentDrive.attributeCurrentStage, 0) + 1) + DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery) + val currentLevel = getAttribute(player, RecruitmentDrive.attributeCurrentStage, 0) + if (currentLevel >= 5) { + CompleteTestCutscene(player).start() + return@on true + } + val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[currentLevel], 0) + val currentStageEnum = Stages.indexMap[currentStage]!! + closeDialogue(player) + + // This is specifically for Sir Spishyus to reset the fox, chicken, grain + SirSpishyusRoomListeners.resetStage(player) + + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + player.inventory.clear() + player.equipment.clear() + openOverlay(player, Components.FADE_TO_BLACK_120) + return@queueScript delayScript(player, 6) + } + 1 -> { + teleport(player, currentStageEnum.startLocation) + return@queueScript delayScript(player, 2) + } + 2 -> { + openOverlay(player, Components.FADE_FROM_BLACK_170) + return@queueScript delayScript(player, 2) + } + 3 -> { + forceWalk(player, currentStageEnum.startWalkLocation, "dumb") + return@queueScript delayScript(player, 2) + } + 4 -> { + callStartingDialogues(player, currentStageEnum.npc) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } else { + if(node.id == Scenery.DOOR_7323) { + // This is specifically for SirRenItchwood + openInterface(player, Components.RD_COMBOLOCK_285) + } else { + sendMessage(player, "You have not completed this room's puzzle yet.") + } + } + return@on true + } + } + + /** Starting Recruitment Drive test cutscene */ + class StartTestCutscene(player: Player) : Cutscene(player) { + override fun setup() { + loadRegion(9805) + val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[0], 0) + setExit(Stages.indexMap[currentStage]!!.startLocation) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2)) + timedUpdate(6) + } + 1 -> { + dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "Here we go!", "Mind your head!") + timedUpdate(3) + } + 2 -> { + dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "Oops. Ignore the smell!", "Nearly there!") + timedUpdate(3) + } + 3 -> { + dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "And...", "Here we are!", "Best of luck!") + timedUpdate(3) + } + 4 -> { + player.inventory.clear() + player.equipment.clear() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0)) + dialogueClose() + endWithoutFade { + val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[0], 0) + val firstStage = Stages.indexMap[currentStage]!! + + // This is specifically for Sir Spishyus to reset the fox, chicken, grain + SirSpishyusRoomListeners.resetStage(player) + + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + fadeFromBlack() + return@queueScript delayScript(player, 2) + } + 1 -> { + forceWalk(player, firstStage.startWalkLocation, "dumb") + return@queueScript delayScript(player, 2) + } + 2 -> { + callStartingDialogues(player, firstStage.npc) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + + } + } + } + } + } + + /** Failed Recruitment Drive test cutscene */ + class FailTestCutscene(player: Player) : Cutscene(player) { + override fun setup() { + loadRegion(9805) + setExit(Location(2997, 3374)) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + closeDialogue(player) + fadeToBlack() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2)) + timedUpdate(6) + } + 1 -> { + var clearBoss = getAttribute(player, SirKuamFerentseDialogueFile.attributeGeneratedSirLeye, NPC(0)) + if (clearBoss.id != 0) { + clearBoss.clear() + } + player.inventory.clear() + player.equipment.clear() + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + fadeFromBlack() + return@queueScript delayScript(player, 2) + } + 1 -> { + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0)) + openDialogue(player, SirTiffyCashienFailedDialogueFile(), NPC(NPCs.SIR_TIFFY_CASHIEN_2290)) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + endWithoutFade { + face(player, Location(2997, 3373)) + fadeFromBlack() + } + } + } + } + } + + /** Complete Recruitment Drive test cutscene */ + class CompleteTestCutscene(player: Player) : Cutscene(player) { + override fun setup() { + loadRegion(9805) + setExit(Location(2996, 3375)) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + if (getQuestStage(player, RecruitmentDrive.questName) == 2) { + setQuestStage(player, RecruitmentDrive.questName, 3) + } + closeDialogue(player) + fadeToBlack() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2)) + timedUpdate(6) + } + 1 -> { + player.inventory.clear() + player.equipment.clear() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0)) + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + fadeFromBlack() + return@queueScript delayScript(player, 2) + } + 1 -> { + openDialogue(player, SirTiffyCashienDialogueFile(), NPC(NPCs.SIR_TIFFY_CASHIEN_2290)) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + endWithoutFade { + face(player, Location(2997, 3373)) + fadeFromBlack() + } + } + } + } + } + + class LogoutRecruitmentDrive : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf(getRegionBorders(9805)) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS) + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + // This is specifically for Sir Spishyus to reset the fox, chicken, grain + SirSpishyusRoomListeners.resetStage(entity) + // Clear inventory whenever you leave the recruitment drive area + entity.inventory.clear() + entity.equipment.clear() + // Teleport you out if you log out. You should do this in one sitting. + if (logout) { + PacketRepository.send(MinimapState::class.java, MinimapStateContext(entity, 0)) + teleport(entity, Location(2996, 3375)) + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt new file mode 100644 index 000000000..754b3de4b --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt @@ -0,0 +1,74 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.* + +class SirAmikVarzeDialogueFile : DialogueBuilderFile() { + + override fun create(b: DialogueBuilder) { + b.onQuestStages(RecruitmentDrive.questName, 0) + .npcl(FacialExpression.FRIENDLY,"Hello, friend!") + .playerl(FacialExpression.THINKING, "Do you have any other quests for me to do?") + .branch { player -> if(isQuestComplete(player, "Black Knights' Fortress") && isQuestComplete(player, "Druidic Ritual")) { 1 } else { 0 } } + .let{ branch -> + // Failure branch + branch.onValue(0) + .npcl(FacialExpression.THINKING, "A quest? Alas I do not have any quests I can offer you at this time.") + .end() + return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch. + }.onValue(1) // Success branch + .npc("Quests, eh?", "Well, I don't have anything on the go at the moment,", "but there is an organisation that is always looking for", "capable adventurers to assist them.") + .npc(FacialExpression.FRIENDLY,"Your excellent work sorting out those Black Knights", "means I will happily write you a letter of", "recommendation.") + .npc("Would you like me to put your name forwards to", "them?") + .options().let { optionBuilder -> + optionBuilder.option ("Yes please") + .playerl("Sure thing Sir Amik, sign me up!") + .npc(FacialExpression.SUSPICIOUS,"Erm, well, this is a little embarrassing, I already HAVE", "put you forward as a potential member.") + .npc("They are the Temple Knights, and you are to", "meet Sir Tiffy Cashien in Falador park for testing", "immediately.") + .playerl("Okey dokey, I'll go do that then.") + .endWith { _, player -> + if(getQuestStage(player, RecruitmentDrive.questName) == 0) { + setAttribute(player, RecruitmentDrive.attributeOriginalGender, player.isMale) + setQuestStage(player, RecruitmentDrive.questName, 1) + } + } + optionBuilder.option_playerl("No thanks") + .end() + optionBuilder.option("Tell me about this organization...") + .npc(FacialExpression.SUSPICIOUS,"I cannot tell you much...", "They are called the Temple Knights, and are an", "organisation that was founded by Saradomin personally", "many centuries ago.") + .npc("There are many rumours and fables about their works and", "actions, but official records of their presence are non-", "existent.") + .npc("It is a secret organisation of extraordinary power and", "resourcefulness...") + .npc("Let me put it this way:", "Should you decide to take them up on their generous", "offer to join, you will find yourself in an advantageous", "position that many in this world would envy, and that few") + .npc("are called to occupy.") + .playerl("Well, that wasn't quite as helpful as I thought it would be...but thanks anyway, I guess.") + .end() + } + + b.onQuestStages(RecruitmentDrive.questName, 1,2,3,4) + .npcl(FacialExpression.FRIENDLY,"Hello, friend!") + .playerl(FacialExpression.THINKING, "Can I just skip the test to become a Temple Knight?") + .npcl("No, I'm afraid not. I suggest you go meet Sir Tiffy in Falador Park, he will be expecting you.") + .end() + + // This should be after the Wanted Quest, but is the placeholder until that quest is implemented. + b.onQuestStages(RecruitmentDrive.questName, 100) + .npcl(FacialExpression.FRIENDLY,"Hello, friend!") + .npcl(FacialExpression.FRIENDLY,"Well @name, now that you are a White Knight, I expect you should be out there hunting Black Knights for us!") + .options().let { optionBuilder -> + optionBuilder.option_playerl("Can you explain the White Knight honour system again?") + .npcl("Sadly we are not as rich as we once were, and there are many White Knights who foolishly lose their combat equipment.") + .npcl("We do not think it fair to make a profit from our brethren, so we will sell you equipment at cost, and rebuy it at the same cost, but we will only sell equipment to those we consider responsible enough to") + .npcl("wield it correctly.") + .npcl("By killing Black Knights, you will increase your reputation with us, by killing White Knights we will obviously think less of you.") + .npcl("You can check your White Knight reputation level by looking at your quest journal for the Wanted! Quest, or Sir Vyvin will let you know what level you are at when you go to purchase equipment.") + .npcl("Sir Vyvin can be found in Falador Castle, and he will sell you any equipment appropriate to your reputation level.") + .npcl("Have fun, and go kill some Black Knights for me!") + .playerl("Okay Amik, thanks for explaining!") + .end() + + optionBuilder.option("Okay, bye!") + .playerl("Okay, 'bye then Amik!") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirKuamFerentseDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirKuamFerentseDialogue.kt new file mode 100644 index 000000000..055845ca2 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirKuamFerentseDialogue.kt @@ -0,0 +1,58 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class SirKuamFerentseDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, SirKuamFerentseDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return SirKuamFerentseDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.SIR_KUAM_FERENTSE_2284) + } +} + +class SirKuamFerentseDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + companion object { + const val attributeGeneratedSirLeye = "quest:recruitmentdrive-generatedsirleye" + } + + override fun create(b: DialogueBuilder) { + b.onPredicate { player -> getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 } + .npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + .end() + + // You can't fail unless you quit the room. + b.onPredicate { _ -> true } + .npc("Ah, @name, you're finally here.", "Your task for this room is to defeat Sir Leye.", "He has been blessed by Saradomin to be undefeatable", "by any man, so it should be quite the challenge for you.") + .npc("If you are having problems, remember", "A true warrior uses his wits as much as his brawn.", "Fight smarter, not harder.") + .endWith { _, player -> + var boss = getAttribute(player, attributeGeneratedSirLeye, NPC(0)) + if (boss.id != 0) { + boss.clear() + } + boss = NPC(NPCs.SIR_LEYE_2285, player.location) + setAttribute(player, attributeGeneratedSirLeye, boss) + boss.isRespawn = false + boss.isAggressive = false + boss.isWalks = true + boss.location = Location(2460, 4963) + boss.init() + registerHintIcon(player, boss) + sendChat(boss, "No man may defeat me!") + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirLeyeBehavior.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirLeyeBehavior.kt new file mode 100644 index 000000000..3f91752f7 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirLeyeBehavior.kt @@ -0,0 +1,49 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import org.rs09.consts.NPCs + +class SirLeyeBehavior : NPCBehavior(NPCs.SIR_LEYE_2285) { + var clearTime = 0 + + override fun tick(self: NPC): Boolean { + // You have 400 ticks to kill Sir Leye + if (clearTime++ > 400) { + clearTime = 0 + poofClear(self) + } + return true + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + val lifepoints = self.skills.lifepoints + if (attacker is Player) { + // If you are male, Sir Leye will recover to full health. + if (attacker.isMale) { + if (state.estimatedHit + Integer.max(state.secondaryHit, 0) > lifepoints - 1) { + self.skills.lifepoints = self.getSkills().getStaticLevel(Skills.HITPOINTS) + } + } + } + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + clearHintIcon(killer) + setAttribute(killer, RecruitmentDrive.attributeStagePassFailState, 1) + removeAttribute(killer, SirKuamFerentseDialogueFile.attributeGeneratedSirLeye) + } + } + + // No xp from attacking this dude. + override fun getXpMultiplier(self: NPC, attacker: Entity): Double { + return 0.0 + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirRenItchwoodDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirRenItchwoodDialogue.kt new file mode 100644 index 000000000..d5ddd45a0 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirRenItchwoodDialogue.kt @@ -0,0 +1,199 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.InterfaceListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Components +import org.rs09.consts.NPCs + +@Initializable +class SirRenItchwoodDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, SirRenItchwoodDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return SirRenItchwoodDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.SIR_REN_ITCHOOD_2287) + } +} + +class SirRenItchwoodDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + companion object { + const val attributeClueNumber = "quest:recruitmentdrive-cluenumber" + } + + override fun create(b: DialogueBuilder) { + b.onPredicate { player -> dialogueNum in 0..1 && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1 } + .betweenStage { _, player, _, _ -> + if (getAttribute(player, attributeClueNumber, -1) !in 0..5) { + setAttribute(player, attributeClueNumber, (0..5).random()) + } + } + .npc("Greetings friend, and welcome here,", "you'll find my puzzle not so clear.", "Hidden amongst my words, it's true,", "the password for the door as a clue.") + .options().let { optionBuilder -> + optionBuilder.option_playerl ("Can I have the clue for the door?") + .branch { player -> getAttribute(player, attributeClueNumber, 0) } + .let{ branch -> + // Note: all the "I" in here are written in small case "i" (sic) + branch.onValue(0) + .npc("Better than me, you'll not find", "In rhyming and in puzzles.", "This clue so clear will tax your mind", "Entirely as it confuzzles!") + .end() + branch.onValue(1) + .npc("Feel the aching of your mind", "In puzzlement, confused.", "See the clue hidden behind", "His words, as you perused.") + .end() + branch.onValue(2) + .npc("Look closely at the words i speak;", "And study closely every part.", "See for yourself the word you seek", "Trapped for you if you're smart.") + .end() + branch.onValue(3) + .npc("More than words, i have not for you", "Except the things i say today.", "Aware are you, this is a clue?", "Take note of what i say!") + .end() + branch.onValue(4) + .npc("Rare it is that you will see", "A puzzle such as this!", "In many ways it tickles me", "Now, watching you hit and miss!") + .end() + branch.onValue(5) + .npc("This riddle of mine may confuse,", "I am quite sure of that.", "Mayhap you should closely peruse", "Every word i have spat?") + .end() + } + return@let optionBuilder.option("Can I have a different clue?") + .player("I don't get that riddle...", "Can I have a different one?") + .branch { player -> getAttribute(player, attributeClueNumber, 0) } + .let{ branch -> + branch.onValue(0) + .npc("Before you hurry through that door", "Inspect the words i spoke.", "There is a simple hidden flaw", "Ere you think my rhyme a joke.") + .end() + branch.onValue(1) + .npc("First my clue you did not see,", "I really wish you had.", "Such puzzling wordplay devilry", "Has left you kind of mad!") + .end() + branch.onValue(2) + .npc("Last time my puzzle did not help", "Apparently, so you've bidden.", "Study my speech carefully, whelp", "To find the answer, hidden.") + .end() + branch.onValue(3) + .npc("Many types have passed through here", "Even such as you amongst their sort.", "And in the end, the puzzles clear;", "The hidden word you saught.") + .end() + branch.onValue(4) + .npc("Repetition, once again", "Against good sense it goes.", "In my words, the answers plain", "Now that you see rhyme flows.") + .end() + branch.onValue(5) + .npc("Twice it is now, i have stated", "In a rhyme, what is the pass.", "Maybe my words obfuscated", "Entirely beyond your class.") + .end() + } + /* + // I'm too goddamned lazy to implement the final clue dialogue + return@let optionBuilder.option("Can I have the final clue?") + .branch { player -> getAttribute(player, attributeClueNumber, 0) } + .let{ branch -> + branch.onValue(0) + .npc("Betrayed by words the answer is", "In that what i say is the key", "There is no more help after this", "Especially no more from me.") + .end() + branch.onValue(1) + .npc("For the last time i will state", "In simple words, the clue.", "Such tricky words make you irate", "Having no idea what to do...") + .end() + branch.onValue(2) + .npc("Lo! my final speech is now", "Attended to by you.", "Study my words, and find out how", "To understand my clue!") + .end() + branch.onValue(3) + .npc("Many types have passed through here", "Even such as you amongst their sort.", "And in the end, the puzzles clear;", "The hidden word you saught.") + .end() + branch.onValue(4) + .npc("Repetition, once again", "Against good sense it goes.", "In my words, the answers plain", "Now that you see rhyme flows.") + .end() + branch.onValue(5) + .npc("Twice it is now, i have stated", "In a rhyme, what is the pass.", "Maybe my words obfuscated", "Entirely beyond your class.") + .end() + } + */ + + } + b.onPredicate { player -> dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 } + .betweenStage { _, player, _, _ -> + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + .npc(FacialExpression.SAD, "It's sad to say,", "this test beat you.", "I'll send you to Tiffy,", "what to do?") + .endWith { _, player -> + removeAttribute(player, attributeClueNumber) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + RecruitmentDriveListeners.FailTestCutscene(player).start() + } + + } +} + +class DoorLockPuzzleInterfaceListener : InterfaceListener { + + companion object { + const val temp = Components.RD_COMBOLOCK_285 + const val attributeLock1 = "quest:recruitmentdrive-lock1" + const val attributeLock2 = "quest:recruitmentdrive-lock2" + const val attributeLock3 = "quest:recruitmentdrive-lock3" + const val attributeLock4 = "quest:recruitmentdrive-lock4" + val lockArray = arrayOf(attributeLock1, attributeLock2, attributeLock3, attributeLock4) + val answers = arrayOf("BITE", "FISH", "LAST", "MEAT", "RAIN", "TIME") + } + + override fun defineInterfaceListeners() { + + onOpen(Components.RD_COMBOLOCK_285) { player, _ -> + setAttribute(player, attributeLock1, 65) + setAttribute(player, attributeLock2, 65) + setAttribute(player, attributeLock3, 65) + setAttribute(player, attributeLock4, 65) + return@onOpen true + } + + onClose(Components.RD_COMBOLOCK_285) { player, _ -> + removeAttribute(player, attributeLock1) + removeAttribute(player, attributeLock2) + removeAttribute(player, attributeLock3) + removeAttribute(player, attributeLock4) + return@onClose true + } + + on(Components.RD_COMBOLOCK_285) { player, component, opcode, buttonID, slot, itemID -> + // Child IDs for respective locks: + // 6 7 8 9 + // 10 < Lock1 > 11 12 < Lock2 > 13 14 < Lock3 > 15 16 < Lock4 > 17 + if (buttonID in 10..17) { + val position = (buttonID - 10) / 2 + val backForth = (buttonID - 10) % 2 + var newValue = getAttribute(player, lockArray[position], 65) + (if (backForth == 0) { -1 } else { 1 }) + if (newValue < 65) { newValue = 90 } // If char number is under A(65), loop back to Z(90) + if (newValue > 90) { newValue = 65 } // If char number is over Z(90), loop back to A(65) + setAttribute(player, lockArray[position], newValue) + setInterfaceText(player, newValue.toChar().toString(), Components.RD_COMBOLOCK_285, position + 6) + } + // Enter Button + if (buttonID == 18) { + val lock1 = getAttribute(player, attributeLock1, 65).toChar() + val lock2 = getAttribute(player, attributeLock2, 65).toChar() + val lock3 = getAttribute(player, attributeLock3, 65).toChar() + val lock4 = getAttribute(player, attributeLock4, 65).toChar() + val answer = arrayOf(lock1, lock2, lock3, lock4).joinToString("") + closeInterface(player) + if (answers[getAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber, 0)] == answer){ + removeAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber) + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + } + sendNPCDialogue(player, NPCs.SIR_REN_ITCHOOD_2287, "Your wit is sharp, your brains quite clear; You solved my puzzle with no fear. At puzzles I rank you quite the best, now enter the portal for your next test.") + } else { + removeAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber) + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + openDialogue(player, SirRenItchwoodDialogueFile(2), NPC(NPCs.SIR_REN_ITCHOOD_2287)) + } + } + } + return@on true + } + } +} diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirSpishyusDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirSpishyusDialogue.kt new file mode 100644 index 000000000..8f6df7708 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirSpishyusDialogue.kt @@ -0,0 +1,221 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.container.impl.EquipmentContainer +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.world.map.zone.ZoneBorders +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +@Initializable +class SirSpishyusDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, SirSpishyusDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return SirSpishyusDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.SIR_SPISHYUS_2282) + } +} + +class SirSpishyusDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { player -> getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 } + .npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + .end() + + b.onPredicate { player -> dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 } + .betweenStage { _, player, _, _ -> + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + .npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.") + .endWith { _, player -> + removeAttribute(player, SirTinleyDialogueFile.attributeDoNotMove) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + RecruitmentDriveListeners.FailTestCutscene(player).start() + } + b.onPredicate { _ -> true } + .npcl(FacialExpression.FRIENDLY, "Ah, welcome @name.") + .playerl(FacialExpression.FRIENDLY, "Hello there." + " What am I supposed to be doing in this room?") + .npcl(FacialExpression.FRIENDLY, "Well, your task is to take this fox, this chicken and this bag of grain across that bridge there to the other side of the room.") + .npcl(FacialExpression.FRIENDLY, "When you have done that, your task is complete.") + .playerl(FacialExpression.FRIENDLY, "Is that it?") + .npcl(FacialExpression.FRIENDLY, "Well, it is not quite as simple as that may sound.") + .npcl(FacialExpression.FRIENDLY, "Firstly, you may only carry one of the objects across the room at a time, for the bridge is old and fragile.") + .npcl(FacialExpression.FRIENDLY, "Secondly, the fox wants to eat the chicken, and the chicken wants to eat the grain. Should you ever leave the fox unattended with the chicken, or the grain unattended with the chicken, then") + .npcl(FacialExpression.FRIENDLY, "one of them will be eaten, and you will be unable to complete the test.") + .playerl(FacialExpression.FRIENDLY, "Okay, I'll see what I can do.") + .end() + } +} +class SirSpishyusRoomListeners : InteractionListener { + companion object { + const val foxFromVarbit = 680 + const val foxToVarbit = 681 + const val chickenFromVarbit = 682 + const val chickenToVarbit = 683 + const val grainFromVarbit = 684 + const val grainToVarbit = 685 + + val fromZoneBorder = ZoneBorders(2479, 4967, 2490, 4977) + val toZoneBorder = ZoneBorders(2471, 4967, 2478, 4977) + + fun countEquipmentItems(player: Player): Int { + var count = 0 + if(inEquipment(player, Items.GRAIN_5607)) { count++ } + if(inEquipment(player, Items.FOX_5608)) { count++ } + if(inEquipment(player, Items.CHICKEN_5609)) { count++ } + return count + } + + fun checkFinished(player: Player) { + if (getVarbit(player, foxToVarbit) == 1 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 1) { + sendMessage(player, "Congratulations! You have solved this room's puzzle!") + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + } + } + + fun checkFail(player: Player): Boolean { + return ((getVarbit(player, foxFromVarbit) == 0 && getVarbit(player, chickenFromVarbit) == 0 && getVarbit(player, grainFromVarbit) == 1) || + (getVarbit(player, foxFromVarbit) == 1 && getVarbit(player, chickenFromVarbit) == 0 && getVarbit(player, grainFromVarbit) == 0) || + (getVarbit(player, foxToVarbit) == 1 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 0) || + (getVarbit(player, foxToVarbit) == 0 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 1)) + } + + fun resetStage(player: Player) { + setVarbit(player, foxFromVarbit, 0) + setVarbit(player, chickenFromVarbit, 0) + setVarbit(player, grainFromVarbit, 0) + setVarbit(player, foxToVarbit, 0) + setVarbit(player, chickenToVarbit, 0) + setVarbit(player, grainToVarbit, 0) + removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT) + removeItem(player, Items.FOX_5608, Container.EQUIPMENT) + removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT) + } + } + + override fun defineListeners() { + on(Scenery.PRECARIOUS_BRIDGE_7286, SCENERY, "cross") { player, node -> + if (countEquipmentItems(player) > 1) { + sendDialogue(player, "I really don't think I should be carrying more than 5Kg across that rickety bridge...") + } else if (checkFail(player)) { + openDialogue(player, SirTinleyDialogueFile(2), NPC(NPCs.SIR_SPISHYUS_2282)) // Fail + } else { + lock(player, 5) + sendMessage(player, "You carefully walk across the rickety bridge...") + player.walkingQueue.reset() + player.walkingQueue.addPath(2476, 4972) + } + return@on true + } + + on(Scenery.PRECARIOUS_BRIDGE_7287, SCENERY, "cross") { player, node -> + if (countEquipmentItems(player) > 1) { + sendDialogue(player, "I really don't think I should be carrying more than 5Kg across that rickety bridge...") + } else if (checkFail(player)) { + openDialogue(player, SirTinleyDialogueFile(2), NPC(NPCs.SIR_SPISHYUS_2282)) // Fail + } else { + lock(player, 5) + sendMessage(player, "You carefully walk across the rickety bridge...") + player.walkingQueue.reset() + player.walkingQueue.addPath(2484, 4972) + } + return@on true + } + + on(Scenery.GRAIN_7284, SCENERY, "pick-up") { player, _ -> + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + if (fromZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.CAPE.ordinal, Item(Items.GRAIN_5607), null, Container.EQUIPMENT) + setVarbit(player, grainFromVarbit, 1) + } + if (toZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.CAPE.ordinal, Item(Items.GRAIN_5607), null, Container.EQUIPMENT) + setVarbit(player, grainToVarbit, 0) + } + } + return@on true + } + onUnequip(Items.GRAIN_5607) { player, _ -> + if (fromZoneBorder.insideBorder(player)) { + removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT) + setVarbit(player, grainFromVarbit, 0) + } + if (toZoneBorder.insideBorder(player)) { + removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT) + setVarbit(player, grainToVarbit, 1) + checkFinished(player) + } + return@onUnequip true + } + + + on(Scenery.FOX_7277, SCENERY, "pick-up") { player, _ -> + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + if (fromZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.WEAPON.ordinal, Item(Items.FOX_5608), null, Container.EQUIPMENT) + setVarbit(player, foxFromVarbit, 1) + } + if (toZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.WEAPON.ordinal, Item(Items.FOX_5608), null, Container.EQUIPMENT) + setVarbit(player, foxToVarbit, 0) + } + } + return@on true + } + onUnequip(Items.FOX_5608) { player, _ -> + if (fromZoneBorder.insideBorder(player)) { + removeItem(player, Items.FOX_5608, Container.EQUIPMENT) + setVarbit(player, foxFromVarbit, 0) + } + if (toZoneBorder.insideBorder(player)) { + removeItem(player, Items.FOX_5608, Container.EQUIPMENT) + setVarbit(player, foxToVarbit, 1) + checkFinished(player) + } + return@onUnequip true + } + + + on(Scenery.CHICKEN_7281, SCENERY, "pick-up") { player, _ -> + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) { + if (fromZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.SHIELD.ordinal, Item(Items.CHICKEN_5609), null, Container.EQUIPMENT) + setVarbit(player, chickenFromVarbit, 1) + } + if (toZoneBorder.insideBorder(player)) { + replaceSlot(player, EquipmentSlot.SHIELD.ordinal, Item(Items.CHICKEN_5609), null, Container.EQUIPMENT) + setVarbit(player, chickenToVarbit, 0) + } + } + return@on true + } + onUnequip(Items.CHICKEN_5609) { player, _ -> + if (fromZoneBorder.insideBorder(player)) { + removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT) + setVarbit(player, chickenFromVarbit, 0) + } + if (toZoneBorder.insideBorder(player)) { + removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT) + setVarbit(player, chickenToVarbit, 1) + checkFinished(player) + } + return@onUnequip true + } + + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt new file mode 100644 index 000000000..0d057494b --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt @@ -0,0 +1,139 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression +import org.rs09.consts.Items + +class SirTiffyCashienDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(RecruitmentDrive.questName, 1) + .player(FacialExpression.FRIENDLY, "Sir Amik Varze sent me to meet you here for some", "sort of testing...") + .npc(FacialExpression.FRIENDLY, "Ah, @name!", "Amik told me all about you, dontchaknow!", "Spliffing job you you did with the old Black Knights there,", "absolutely first class.") + .playerl(FacialExpression.GUILTY, "...Thanks I think.") + // .npcl(FacialExpression.FRIENDLY, "Well, not in those exact words, but you get my point, what?") + .npc(FacialExpression.FRIENDLY, "Well, a top-notch filly like yourself is just the right sort", "we've been looking for for our organisation.") + .npcl(FacialExpression.FRIENDLY, "So, are you ready to begin testing?") + .let { path -> + val originalPath = b.placeholder() + path.goto(originalPath) + return@let originalPath.builder().options().let { optionBuilder -> + val continuePath = b.placeholder() + optionBuilder.option("Testing..?") + .playerl(FacialExpression.FRIENDLY, "Testing? What exactly do you mean by testing?") + .npcl(FacialExpression.FRIENDLY, "Jolly bad show! Varze was supposed to have informed you about all this before sending you here!") + .npcl(FacialExpression.FRIENDLY, "Well, not your fault I suppose, what? Anywho, our organisation is looking for a certain specific type of person to join.") + .playerl(FacialExpression.FRIENDLY, "So... You want me to go kill some monster or something for you?") + .npcl(FacialExpression.FRIENDLY, "Not at all, old bean. There's plenty of warriors around should we require dumb muscle.") + .npcl(FacialExpression.FRIENDLY, "That's really not the kind of thing our organisation is after, what?") + .playerl(FacialExpression.FRIENDLY, "So you want me to go and fetch you some kind of common item, and then take it for delivery somewhere on the other side of the country?") + .playerl(FacialExpression.FRIENDLY, "Because I really hate doing that!") + .npcl(FacialExpression.FRIENDLY, "Haw, haw, haw! What a dull thing to ask of someone, what?") + .npcl(FacialExpression.FRIENDLY, "I know what you mean, though. I did my fair share of running errands when I was a young adventurer, myself!") + .playerl(FacialExpression.FRIENDLY, "So what exactly will this test consist of?") + .npcl(FacialExpression.FRIENDLY, "Can't let just any old riff-raff in, what? The mindless thugs and bully boys are best left in the White Knights or the city guard. We look for the top-shelf brains to join us.") + .playerl(FacialExpression.FRIENDLY, "So you want to test my brains? Will it hurt?") + .npcl(FacialExpression.FRIENDLY, "Haw, haw, haw! That's a good one!") + .npcl(FacialExpression.FRIENDLY, "Not in the slightest.. Well, maybe a bit, but we all have to make sacrifices occasionally, what?") + .playerl(FacialExpression.FRIENDLY, "What do you want me to do then?") + .npcl(FacialExpression.FRIENDLY, "It's a test of wits, what? I'll take you to our secret training grounds, and you will have to pass through a series of five separate intelligence test to prove you're our sort of adventurer.") + .npcl(FacialExpression.FRIENDLY, "Standard puzzle room rules will apply.") + .playerl(FacialExpression.THINKING, "Erm... What are standard puzzle room rules exactly?") + .npcl(FacialExpression.HAPPY, "Never done this sort of thing before, what?") + .npc("The simple rules are:", "No items or equipment to be brought with you.", "Each room is a self-contained puzzle.", "You may quit at any time.") + .npcl(FacialExpression.HAPPY, "Of course, if you quit a room, then all your progress up to that point will be cleared, and you'll have to start again from scratch.") + .npc(FacialExpression.HAPPY, "Our organisation manages to filter all the top-notch", "adventurers this way.", "So, are you ready to go?") + .goto(originalPath) + optionBuilder.option("Organisation?") + .playerl(FacialExpression.THINKING, "This organisation you keep mentioning.. Perhaps you could tell me a little about it?") + .npcl(FacialExpression.FRIENDLY, "Oh, that Amik! Jolly bad form. Did he not tell you anything that he was supposed to?") + .playerl(FacialExpression.FRIENDLY, "No. He didn't really tell me anything except to come here and meet you.") + .npcl(FacialExpression.FRIENDLY, "Well, now, old sport, let me give you the heads up and the low down, what?") + .npcl(FacialExpression.FRIENDLY, "I represent the Temple Knights. We are the premier order of Knights in Asgarnia, if not the world. Saradomin himself personally founded our order centuries ago, and we answer only to him.") + .npcl(FacialExpression.FRIENDLY, "Only the very best of the best are permitted to join, and the powers we command are formidable indeed.") + .npcl(FacialExpression.FRIENDLY, "You might say that we are the front line of defence for the entire kingdom!") + .playerl(FacialExpression.THINKING, "So what's the difference between you and the White Knights?") + .npcl(FacialExpression.FRIENDLY, "Well, in simple terms, we're better! Any fool with a sword can manage to get into the White Knights, which is mostly the reason they are so very, very incompetent, what?") + .npcl(FacialExpression.FRIENDLY, "The Temple Knights, on the other hand, have to be smarter, stronger and better than all others. We are the elite. No man controls us, for our orders come directly from Saradomin himself!") + .npcl(FacialExpression.FRIENDLY, "According to Sir Vey Lance, our head of operations, that is. He claims that everything he tells us to do is done with Saradomin's implicit permission.") + .npcl(FacialExpression.FRIENDLY, "It's not every job where you have more authority than the king, though, is it?") + .playerl(FacialExpression.THINKING, "Wait... You can order the King around?") + .npcl(FacialExpression.FRIENDLY, "Well, not me personally. I'm only in the recruitment side of things, dontchaknow, but the higher ranking members of the organisation have almost absolute power over the kingdom.") + .npcl(FacialExpression.FRIENDLY, "Plus a few others, so I hear...") + .npcl(FacialExpression.FRIENDLY, "Anyway, this is why we keep our organisation shrouded in secrecy, and why we demand such rigorous testing for all potential recruits. Speaking of which, are you ready to begin your testing?") + .goto(originalPath) + optionBuilder.option("Yes, let's go!") + .player(FacialExpression.FRIENDLY, "Yeah. this sounds right up my street.", "Let's go!") + .branch { player -> if(player.inventory.isEmpty && player.equipment.isEmpty && !player.familiarManager.hasFamiliar()) { 1 } else { 0 } } + .let { branch -> + branch.onValue(0) + .npcl(FacialExpression.NEUTRAL, "Well, bad luck, old @g[guy,gal]. You'll need to have a completely empty inventory and you can't be wearing any equipment before we can accurately test you.") + .npcl(FacialExpression.HAPPY, "Don't want people cheating by smuggling stuff in, what? That includes things carried by familiars, too! Come and see me again after you've been to the old bank to drop your stuff off, what?") + .end() + return@let branch + } + .onValue(1) + .npc(FacialExpression.HAPPY, "Jolly good show!", "Now the training grounds location is a secret, so...") + .goto(continuePath) + optionBuilder.option("No, I've changed my mind.") + .player("No, I've changed my mind.") + .end() + + return@let continuePath.builder() + } + + }.endWith { _, player -> + if (getQuestStage(player, RecruitmentDrive.questName) == 1) { + setQuestStage(player, RecruitmentDrive.questName, 2) + } + RecruitmentDriveListeners.shuffleStages(player) + RecruitmentDriveListeners.StartTestCutscene(player).start() + } + b.onQuestStages(RecruitmentDrive.questName, 2) + .npc(FacialExpression.FRIENDLY, "Ah, what ho!", "Back for another go at the old testing, what?") + .options().let { optionBuilder -> + val continuePath = b.placeholder() + optionBuilder.option("Yes, let's go!") + .player(FacialExpression.FRIENDLY, "Yeah. this sounds right up my street.", "Let's go!") + .branch { player -> if(player.inventory.isEmpty && player.equipment.isEmpty && !player.familiarManager.hasFamiliar()) { 1 } else { 0 } } + .let { branch -> + branch.onValue(0) + .npcl(FacialExpression.NEUTRAL, "Well, bad luck, old @g[guy,gal]. You'll need to have a completely empty inventory and you can't be wearing any equipment before we can accurately test you.") + .npcl(FacialExpression.HAPPY, "Don't want people cheating by smuggling stuff in, what? That includes things carried by familiars, too! Come and see me again after you've been to the old bank to drop your stuff off, what?") + .end() + return@let branch + } + .onValue(1) + .npc(FacialExpression.FRIENDLY, "Jolly good show!", "Now the training grounds location is a secret, so...") + .endWith { _, player -> + RecruitmentDriveListeners.shuffleStages(player) + RecruitmentDriveListeners.StartTestCutscene(player).start() + } + optionBuilder.option("No, I've changed my mind.") + .player("No, I've changed my mind.") + .end() + return@let continuePath.builder() + } + b.onQuestStages(RecruitmentDrive.questName, 3) + .npc(FacialExpression.HAPPY, "Oh, jolly well done!", "Your performance will need to be evaluated by Sir Vey", "personally, but I don't think it's going too far ahead of", "myself to welcome you to the team!") + .endWith { _, player -> + // Get a voucher and $3000 to change gender if you did do it during the quest. + if (getAttribute(player, RecruitmentDrive.attributeOriginalGender, true) != player.isMale) { + addItemOrDrop(player, Items.MAKEOVER_VOUCHER_5606) + addItemOrDrop(player, Items.COINS_995, 3000) + } + removeAttribute(player, RecruitmentDrive.attributeOriginalGender) + finishQuest(player, RecruitmentDrive.questName) + } + } +} + +class SirTiffyCashienFailedDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .npc(FacialExpression.SAD, "Oh, jolly bad luck, what?", "Not quite the brainbox you thought you were, eh?") + .npc(FacialExpression.HAPPY, "Well, never mind!", "You have an open invitation to join our organization, so", "when you're feeling a little smarter, come back and talk", "to me again.") + + } +} diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTinleyDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTinleyDialogue.kt new file mode 100644 index 000000000..d00cae73a --- /dev/null +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTinleyDialogue.kt @@ -0,0 +1,100 @@ +package content.region.asgarnia.falador.quest.recruitmentdrive + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.impl.Projectile +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.system.task.Pulse +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.update.flag.context.Graphics +import core.plugin.Initializable +import org.rs09.consts.NPCs +import org.rs09.consts.Sounds + +@Initializable +class SirTinleyDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, SirTinleyDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return SirTinleyDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.SIR_TINLEY_2286) + } +} + +class SirTinleyDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile(), MapArea { + companion object { + const val attributeDoNotMove = "quest:recruitmentdrive-donotmove" + } + + override fun create(b: DialogueBuilder) { + b.onPredicate {player -> dialogueNum == 0 && !getAttribute(player, attributeDoNotMove, false) && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0 } + .npc("Ah, welcome @name.", "I have but one clue for you to pass this room's puzzle:", "'Patience'.") + .endWith { _, player -> + setAttribute(player, attributeDoNotMove, true) + queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> + when (stage) { + 0 -> { + return@queueScript delayScript(player, 15) + } + 1 -> { + if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1) { + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1) + setAttribute(player, attributeDoNotMove, false) + npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + } + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + b.onPredicate {player -> dialogueNum == 0 && !getAttribute(player, attributeDoNotMove, false) && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 } + .npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.") + .end() + + // If you talk to him before time is up, you fail. + b.onPredicate { player -> dialogueNum == 0 && getAttribute(player, attributeDoNotMove, false) || dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 } + .betweenStage { _, player, _, _ -> + setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1) + } + .npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.") + .endWith { _, player -> + removeAttribute(player, attributeDoNotMove) + removeAttribute(player, RecruitmentDrive.attributeStagePassFailState) + RecruitmentDriveListeners.FailTestCutscene(player).start() + } + + b.onPredicate { _ -> dialogueNum == 1 } + .npc("Ah, @name, you have arrived.", "Speak to me to begin your task.") + .endWith { _, player -> + setAttribute(player, attributeDoNotMove, false) + } + } + + + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders(2474, 4959, 2478, 4957)) + } + + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + if(getAttribute(entity, attributeDoNotMove, false)) { + setAttribute(entity, attributeDoNotMove, false) + setAttribute(entity, RecruitmentDrive.attributeStagePassFailState, -1) + openDialogue(entity, SirTinleyDialogueFile(2), NPC(NPCs.SIR_TINLEY_2286)) + } + } + } +} diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java index 7d142974d..d4bd61017 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java @@ -8,6 +8,7 @@ import core.plugin.Initializable; /** * Created for 2009Scape * User: Ethan Kyle Millard + * https://www.youtube.com/watch?v=-RuHho3NbWg * Date: March 15, 2020 * Time: 9:21 AM */ diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt index a79c8940e..81cf396b5 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt @@ -1,15 +1,11 @@ package content.region.morytania.quest.creatureoffenkenstrain -import content.global.travel.canoe.CanoeListener import core.api.* import core.game.dialogue.FacialExpression import core.game.global.action.DoorActionHandler import core.game.global.action.PickupHandler import core.game.interaction.InteractionListener -import core.game.node.Node -import core.game.node.entity.player.Player import core.game.node.item.GroundItem -import core.game.node.item.Item import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.update.flag.context.Animation diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index bfe883b94..0a7c70317 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -919,6 +919,14 @@ fun openDialogue(player: Player, dialogue: Any, vararg args: Any) { } } +/** + * Closes any opened dialogue. + */ +fun closeDialogue(player: Player) { + player.dialogueInterpreter.close() + player.interfaceManager.closeChatbox() +} + /** * Gets an NPC with the given ID from the repository. * @param id the ID of the NPC to locate @@ -1647,6 +1655,18 @@ fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: core.game.dialo player.dialogueInterpreter.sendDialogues(npc, expr, *splitLines(msg)) } +/** + * Sends a dialogue that uses the player's chathead. + * @param player the player to send the dialogue to + * @param npc the ID of the NPC to use for the chathead + * @param expr the FacialExpression to use. An enum exists for these called FacialExpression. + * @param msg the message to send. + */ +fun sendNPCDialogueLines(player: Player, npc: Int, expr: core.game.dialogue.FacialExpression, hideContinue: Boolean, vararg msgs: String) { + val dialogueComponent = player.dialogueInterpreter.sendDialogues(npc, expr, *msgs) + player.packetDispatch.sendInterfaceConfig(dialogueComponent.id, msgs.size + 4, hideContinue) +} + /** * Sends an animation to a specific interface child * @param player the player to send the packet to diff --git a/Server/src/main/core/game/activity/Cutscene.kt b/Server/src/main/core/game/activity/Cutscene.kt index 0caa0e393..a8b2c6759 100644 --- a/Server/src/main/core/game/activity/Cutscene.kt +++ b/Server/src/main/core/game/activity/Cutscene.kt @@ -121,6 +121,29 @@ abstract class Cutscene(val player: Player) { player.dialogueInterpreter.addAction { _,_ -> onContinue.invoke() } } + /** + * Sends a dialogue to the player using the given NPC ID, which updates the cutscene stage by default when continued. + * @param npcId the ID of the NPC to send a dialogue for + * @param expression the FacialExpression the NPC should use + * @param message the message to send + * @param onContinue (optional) a method that runs when the dialogue is "continued." Increments the cutscene stage by default. + */ + fun dialogueLinesUpdate(npcId: Int, expression: core.game.dialogue.FacialExpression, vararg message: String, onContinue: () -> Unit = {incrementStage()}) + { + logCutscene("Sending NPC dialogue lines update.") + sendNPCDialogueLines(player, npcId, expression, true, *message) + player.dialogueInterpreter.addAction { _,_ -> onContinue.invoke() } + } + + /** + * Forces the dialogue to close. + */ + fun dialogueClose() + { + logCutscene("Sending dialogue close.") + closeDialogue(player) + } + /** * Sends a non-NPC dialogue to the player, which updates the cutscene stage by default when continued * @param message the message to send @@ -248,6 +271,51 @@ abstract class Cutscene(val player: Player) { AntiMacro.pause(player) } + + /** + * Ends this cutscene, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method. + * @param endActions (optional) a method that executes when the cutscene fully completes + */ + fun endWithoutFade(endActions: (() -> Unit)? = null) + { + ended = true + GameWorld.Pulser.submit(object : Pulse(){ + var tick: Int = 0 + override fun pulse(): Boolean { + when(tick++) + { + 0 -> player.properties.teleportLocation = exitLocation + 1 -> { + return true + } + } + return false + } + + override fun stop() { + super.stop() + player ?: return + player.removeAttribute(ATTRIBUTE_CUTSCENE) + player.removeAttribute(ATTRIBUTE_CUTSCENE_STAGE) + player.properties.isSafeZone = false + player.properties.safeRespawn = ServerConstants.HOME_LOCATION + player.interfaceManager.restoreTabs() + player.unlock() + clearNPCs() + player.unhook(CUTSCENE_DEATH_HOOK) + player.logoutListeners.remove("cutscene") + AntiMacro.unpause(player) + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0)) + try { + endActions?.invoke() + } catch (e: Exception) { + log(this::class.java, Log.ERR, "There's some bad nasty code in ${this::class.java.simpleName} end actions!") + e.printStackTrace() + } + } + }) + } + /** * Ends this cutscene, fading the screen to black, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method. * @param fade (optional) should the cutscene fade to black? diff --git a/Server/src/main/core/game/dialogue/DialogueBuilder.kt b/Server/src/main/core/game/dialogue/DialogueBuilder.kt index 454ea29a5..9d3107406 100644 --- a/Server/src/main/core/game/dialogue/DialogueBuilder.kt +++ b/Server/src/main/core/game/dialogue/DialogueBuilder.kt @@ -295,6 +295,14 @@ class DialogueBuilder(var target: DialogueBuilderFile, var clauseIndex: Int = -1 } } + /** + * The first if-statement to a dialogue. At minimum, you must have "b.onPredicate { _ -> true }" + * PLEASE BE CAREFUL ABOUT HAVING COMPLEX PREDICATE. + * If at any point during a dialogue that the predicate is not satisfied, + * it will block further dialogue progression and any dialogue will suddenly disappear. + * e.g. onPredicate(x==2) but during dialogue you set x=3, dialogue after it will disappear. + * Think of this as a repeated filter at every dialogue step. + */ fun onPredicate(predicate: (player: Player) -> Boolean): DialogueBuilder { target.data.add(DialogueClause(predicate, ArrayList())) clauseIndex = target.data.size - 1 diff --git a/Server/src/main/core/game/dialogue/DialogueInterpreter.java b/Server/src/main/core/game/dialogue/DialogueInterpreter.java index 06a93a303..ae6c16977 100644 --- a/Server/src/main/core/game/dialogue/DialogueInterpreter.java +++ b/Server/src/main/core/game/dialogue/DialogueInterpreter.java @@ -10,6 +10,7 @@ import core.game.node.entity.Entity; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import core.game.world.GameWorld; import core.net.packet.PacketRepository; import core.net.packet.context.ChildPositionContext; import core.net.packet.context.ContainerContext; @@ -501,6 +502,7 @@ public final class DialogueInterpreter { static Pattern GENDERED_SUBSTITUTION = Pattern.compile("@g\\[([^,]*),([^\\]]*)\\]"); public static String doSubstitutions(Player player, String msg) { msg = msg.replace("@name", player.getUsername()); + msg = msg.replace("@servername", GameWorld.getSettings().getName()); StringBuilder sb = new StringBuilder(); Matcher m = GENDERED_SUBSTITUTION.matcher(msg); int index = player.isMale() ? 1 : 2; From 518b5d91dd26f8a9f9acec862d36ac97dd32e282 Mon Sep 17 00:00:00 2001 From: "A F (Hawk)" <22297189-austinfrancktex@users.noreply.gitlab.com> Date: Thu, 22 Aug 2024 08:19:08 +0000 Subject: [PATCH 005/306] Fixed woad leaf typo in Wyson dialogue --- .../asgarnia/falador/dialogue/WysonTheGardenerDialogue.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/WysonTheGardenerDialogue.kt b/Server/src/main/content/region/asgarnia/falador/dialogue/WysonTheGardenerDialogue.kt index 4d42d5d9f..1d2592ad8 100644 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/WysonTheGardenerDialogue.kt +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/WysonTheGardenerDialogue.kt @@ -121,7 +121,7 @@ class WysonTheGardenerDialogue : core.game.dialogue.DialoguePlugin { } 133 -> end() 140 -> { - npc("Thanks for being generous", "here's an extra woad leave.") + npc("Thanks for being generous", "here's an extra woad leaf.") stage = 141 } 141 -> if (player.inventory.contains(995, 20)) { From 97464ef1d24a59574c239ae3f1d356af245e1710 Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Fri, 23 Aug 2024 01:29:44 +0000 Subject: [PATCH 006/306] Corrected All Fired Up item requirements --- Server/data/configs/item_configs.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index a365397e3..852a6fc39 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -119738,6 +119738,7 @@ "equipment_slot": "0" }, { + "requirements": "{11,62}", "shop_price": "100", "examine": "It burns, burns, burns...", "durability": null, @@ -119753,6 +119754,7 @@ "point_price": "50" }, { + "requirements": "{11,79}", "destroy_message": "To get another pair of Flame Gloves, you need to keep ten beacons alight simultaneously and then talk to King Roald.", "shop_price": "200", "examine": "The hottest gloves in town.", @@ -119767,6 +119769,7 @@ "equipment_slot": "9" }, { + "requirements": "{11,92}", "shop_price": "300", "examine": "Danger: risk of fire.", "durability": null, From c271d4e74bae60dd31b35a43fca8c3e6c0cec9b5 Mon Sep 17 00:00:00 2001 From: Oliver Fawcett Date: Sun, 25 Aug 2024 03:50:33 +0000 Subject: [PATCH 007/306] Fixed typo in Straven dialogue --- .../misthalin/varrock/quest/shieldofarrav/StravenDialogue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java index 6b26f29c9..5bb9fc352 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java @@ -321,7 +321,7 @@ public class StravenDialogue extends DialoguePlugin { stage = 47; break; case 47: - npc("Although having said that, a rival gang of ours, er,", "theirs, called the Black Arm Gang is supposedly metting", "a contact from Port Sarim today in the Blue Moon", "Inn."); + npc("Although having said that, a rival gang of ours, er,", "theirs, called the Black Arm Gang is supposedly meeting", "a contact from Port Sarim today in the Blue Moon", "Inn."); stage = 48; break; case 48: From 4156f28b93d16e105359674fc92763ee59b30d29 Mon Sep 17 00:00:00 2001 From: GregF Date: Wed, 11 Sep 2024 07:07:55 +0000 Subject: [PATCH 008/306] Corrected many potion effects --- .../content/data/consumables/Consumables.java | 22 +++++++++---------- .../consumables/effects/RestoreEffect.java | 16 +++++++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Server/src/main/content/data/consumables/Consumables.java b/Server/src/main/content/data/consumables/Consumables.java index 75808438e..7b217c81a 100644 --- a/Server/src/main/content/data/consumables/Consumables.java +++ b/Server/src/main/content/data/consumables/Consumables.java @@ -319,11 +319,11 @@ public enum Consumables { STRENGTH(new Potion(new int[] {113, 115, 117, 119}, new SkillEffect(Skills.STRENGTH, 3, 0.1))), ATTACK(new Potion(new int[] {2428, 121, 123, 125}, new SkillEffect(Skills.ATTACK, 3, 0.1))), DEFENCE(new Potion(new int[] {2432, 133, 135, 137}, new SkillEffect(Skills.DEFENCE, 3, 0.1))), - RANGING(new Potion(new int[] {2444, 169, 171, 173}, new SkillEffect(Skills.RANGE, 3, 0.1))), - MAGIC(new Potion(new int[] {3040, 3042, 3044, 3046}, new SkillEffect(Skills.MAGIC, 3, 0.1))), - SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 3, 0.2))), - SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 3, 0.2))), - SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 3, 0.2))), + RANGING(new Potion(new int[] {2444, 169, 171, 173}, new SkillEffect(Skills.RANGE, 4, 0.1))), + MAGIC(new Potion(new int[] {3040, 3042, 3044, 3046}, new SkillEffect(Skills.MAGIC, 4, 0))), + SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 5, 0.15))), + SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 5, 0.15))), + SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 5, 0.15))), ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new AddTimerEffect("poison:immunity", secondsToTicks(90)))), ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new AddTimerEffect("poison:immunity", minutesToTicks(9)))), ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new AddTimerEffect("poison:immunity", minutesToTicks(12)))), @@ -332,18 +332,18 @@ public enum Consumables { AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))), HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))), RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))), - SARA_BREW(new Potion(new int[] {6685, 6687, 6689, 6691}, new MultiEffect(new PercentHeal(2, .15), new SkillEffect(Skills.ATTACK, 0, -0.10), new SkillEffect(Skills.STRENGTH, 0, -0.10), new SkillEffect(Skills.MAGIC, 0, -0.10), new SkillEffect(Skills.RANGE, 0, -0.10), new SkillEffect(Skills.DEFENCE, 2, 0.2)))), + SARA_BREW(new Potion(new int[] {6685, 6687, 6689, 6691}, new MultiEffect(new PercentHeal(0, .15), new SkillEffect(Skills.ATTACK, 0, -0.10), new SkillEffect(Skills.STRENGTH, 0, -0.10), new SkillEffect(Skills.MAGIC, 0, -0.10), new SkillEffect(Skills.RANGE, 0, -0.10), new SkillEffect(Skills.DEFENCE, 0, 0.25)))), SUMMONING(new Potion(new int[] {12140, 12142, 12144, 12146}, new MultiEffect(new RestoreSummoningSpecial(), new SummoningEffect(7, 0.25)))), COMBAT(new Potion(new int[] {9739, 9741, 9743, 9745}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, .1), new SkillEffect(Skills.ATTACK, 3, .1)))), - ENERGY(new Potion(new int[] {3008, 3010, 3012, 3014}, new MultiEffect(new EnergyEffect(10), new HealingEffect(3)))), + ENERGY(new Potion(new int[] {3008, 3010, 3012, 3014}, new EnergyEffect(10))), FISHING(new Potion(new int[] {2438, 151, 153, 155}, new SkillEffect(Skills.FISHING, 3, 0))), PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))), - SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new MultiEffect(new RestoreEffect(8, 0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25)))), - ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), + SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new RestoreEffect(8, 0.25, true))), + ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))), GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))), MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))), - SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8,0.25), new RemoveTimerEffect("poison"), new RemoveTimerEffect("disease")))), + SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25, true), new AddTimerEffect("poison:immunity", secondsToTicks(90)), new RemoveTimerEffect("disease")))), SUPER_ENERGY(new Potion(new int[] {3016, 3018, 3020, 3022}, new EnergyEffect(20))), BLAMISH_OIL(new FakeConsumable(1582, new String[] {"You know... I'd really rather not."})), @@ -356,7 +356,7 @@ public enum Consumables { STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))), RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))), SUPER_RESTO_MIX(new BarbarianMix(new int [] {11493, 11495}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25), new HealingEffect(6)))), - ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(6)))), + ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(3)))), DEF_MIX(new BarbarianMix(new int[] {11457, 11459}, new MultiEffect(new SkillEffect(Skills.DEFENCE, 3, 0.1), new HealingEffect(6)))), AGIL_MIX(new BarbarianMix(new int[] {11461, 11463}, new MultiEffect(new SkillEffect(Skills.AGILITY, 3, 0), new HealingEffect(6)))), COMBAT_MIX(new BarbarianMix(new int[] {11445, 11447}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(6)))), diff --git a/Server/src/main/content/data/consumables/effects/RestoreEffect.java b/Server/src/main/content/data/consumables/effects/RestoreEffect.java index 3b57acabf..79dc76ccb 100644 --- a/Server/src/main/content/data/consumables/effects/RestoreEffect.java +++ b/Server/src/main/content/data/consumables/effects/RestoreEffect.java @@ -6,15 +6,29 @@ import core.game.node.entity.skill.Skills; public class RestoreEffect extends ConsumableEffect { double base,bonus; + boolean all_skills; // Except for hitpoints public RestoreEffect(double base, double bonus){ this.base = base; this.bonus = bonus; + this.all_skills = false; + } + + public RestoreEffect(double base, double bonus, boolean all_skills){ + this.base = base; + this.bonus = bonus; + this.all_skills = all_skills; } final int[] SKILLS = new int[] { Skills.DEFENCE, Skills.ATTACK, Skills.STRENGTH, Skills.MAGIC, Skills.RANGE }; + final int[] ALL_SKILLS = new int[]{ + Skills.ATTACK,Skills.DEFENCE, Skills.STRENGTH,Skills.RANGE,Skills.PRAYER,Skills.MAGIC, Skills.COOKING, + Skills.WOODCUTTING,Skills.FLETCHING,Skills.FISHING,Skills.FIREMAKING,Skills.CRAFTING,Skills.SMITHING, + Skills.MINING,Skills.HERBLORE,Skills.AGILITY,Skills.THIEVING,Skills.SLAYER,Skills.FARMING, + Skills.RUNECRAFTING,Skills.HUNTER,Skills.CONSTRUCTION,Skills.SUMMONING }; @Override public void activate(Player p) { Skills sk = p.getSkills(); - for(int skill : SKILLS){ + int[] skills = this.all_skills ? ALL_SKILLS : SKILLS; + for(int skill : skills){ int statL = sk.getStaticLevel(skill); int curL = sk.getLevel(skill); if(curL < statL){ From 5c027e2649b8f42e9dbe07f4731a08e46823c2dd Mon Sep 17 00:00:00 2001 From: GregF Date: Wed, 11 Sep 2024 07:09:46 +0000 Subject: [PATCH 009/306] Corrected fletching arrow xp --- .../content/global/skill/fletching/Fletching.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Server/src/main/content/global/skill/fletching/Fletching.java b/Server/src/main/content/global/skill/fletching/Fletching.java index 4dea01354..de5a99e65 100644 --- a/Server/src/main/content/global/skill/fletching/Fletching.java +++ b/Server/src/main/content/global/skill/fletching/Fletching.java @@ -190,13 +190,13 @@ public class Fletching { } public enum ArrowHeads { - BRONZE_ARROW(39, 882, 1, 2.6), - IRON_ARROW(40, 884, 15, 3.8), - STEEL_ARROW(41, 886, 30, 6.3), - MITHRIL_ARROW(42, 888, 45, 8.8), - ADAMANT_ARROW(43, 890, 60, 11.3), - RUNE_ARROW(44, 892, 75, 13.8), - DRAGON_ARROW(11237, 11212, 90, 16.3), + BRONZE_ARROW(39, 882, 1, 1.3), + IRON_ARROW(40, 884, 15, 2.5), + STEEL_ARROW(41, 886, 30, 5), + MITHRIL_ARROW(42, 888, 45, 7.5), + ADAMANT_ARROW(43, 890, 60, 10), + RUNE_ARROW(44, 892, 75, 12.5), + DRAGON_ARROW(11237, 11212, 90, 15), BROAD_ARROW(13278, 4160, 52, 15); public int unfinished,finished,level; From cc47f4b488f2818b642c01cc1ad23b6c403cc600 Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Wed, 11 Sep 2024 07:11:13 +0000 Subject: [PATCH 010/306] Fixed cockatrice, godtrice and spirit cobra egg implementation --- .../content/global/skill/summoning/familiar/SpiritCobraNPC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritCobraNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritCobraNPC.java index 83f1d21ae..18d4946b2 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritCobraNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritCobraNPC.java @@ -56,7 +56,7 @@ public class SpiritCobraNPC extends Familiar { * @author Vexia */ public enum Egg { - COCKATRICE(new Item(1944), new Item(12109)), SARATRICE(new Item(10533), new Item(12113)), ZAMATRICE(new Item(10532), new Item(12115)), GUTHATRICE(new Item(10531), new Item(12111)), CORACATRICE(new Item(11964), new Item(12119)), PENGATRICE(new Item(12483), new Item(12117)), VULATRICE(new Item(11695), new Item(12121)); + COCKATRICE(new Item(1944), new Item(12109)), SARATRICE(new Item(5077), new Item(12113)), ZAMATRICE(new Item(5076), new Item(12115)), GUTHATRICE(new Item(5078), new Item(12111)), CORACATRICE(new Item(11964), new Item(12119)), PENGATRICE(new Item(12483), new Item(12117)), VULATRICE(new Item(11965), new Item(12121)); /** * The egg item. From f94221918f7d97c1bda32c25f4d627810e88d7e0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 09:32:57 +0000 Subject: [PATCH 011/306] Fixed the unlocking of region-wide music tracks --- .../node/entity/player/link/music/MusicPlayer.java | 7 ++----- .../main/core/game/system/config/MusicConfigLoader.kt | 2 +- Server/src/main/core/game/world/map/Region.java | 11 +++++------ .../main/core/game/world/map/zone/ZoneMonitor.java | 6 +++--- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java b/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java index 1123fdfd1..163cdadc5 100644 --- a/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java +++ b/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java @@ -10,9 +10,7 @@ import core.net.packet.context.StringContext; import core.net.packet.out.MusicPacket; import core.net.packet.out.StringPacket; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; +import java.util.*; import static core.api.ContentAPIKt.*; @@ -199,10 +197,9 @@ public final class MusicPlayer { public void unlock(int id, boolean play) { MusicEntry entry = MusicEntry.forId(id); if (entry == null) { - return; } - if (!unlocked.containsKey(entry.getIndex())) { + if (!entry.getName().equals(" ") && !unlocked.containsKey(entry.getIndex())) { unlocked.put(entry.getIndex(), entry); player.getPacketDispatch().sendMessage("You have unlocked a new music track: " + entry.getName() + "."); refreshList(); diff --git a/Server/src/main/core/game/system/config/MusicConfigLoader.kt b/Server/src/main/core/game/system/config/MusicConfigLoader.kt index d73fc597d..3f5cc60cf 100644 --- a/Server/src/main/core/game/system/config/MusicConfigLoader.kt +++ b/Server/src/main/core/game/system/config/MusicConfigLoader.kt @@ -40,7 +40,7 @@ class MusicConfigLoader { val e = config as JSONObject val region = Integer.parseInt(e["region"].toString()) val id = Integer.parseInt(e["id"].toString()) - RegionManager.forId(region).music = MusicEntry.forId(id) + RegionManager.forId(region).music = id count++ } log(this::class.java, Log.FINE, "Parsed $count region music configs.") diff --git a/Server/src/main/core/game/world/map/Region.java b/Server/src/main/core/game/world/map/Region.java index 93303b658..ff87d8e6b 100644 --- a/Server/src/main/core/game/world/map/Region.java +++ b/Server/src/main/core/game/world/map/Region.java @@ -3,7 +3,6 @@ package core.game.world.map; import core.cache.Cache; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.music.MusicEntry; import core.game.node.entity.player.link.music.MusicZone; import core.game.system.communication.CommunicationInfo; import core.game.system.task.Pulse; @@ -62,9 +61,9 @@ public class Region { private final List regionZones = new ArrayList<>(20); /** - * The region-wide music track for this region. + * The region-wide music track ID for this region. */ - private MusicEntry music = null; + private int music = -1; /** * Any tile-specific music zones lying in this region. @@ -481,15 +480,15 @@ public class Region { /** * Sets the region-wide music track. */ - public void setMusic(MusicEntry music) { + public void setMusic(int music) { this.music = music; } /** * Gets the region-wide music track - * @return The music entry + * @return The music entry ID */ - public MusicEntry getMusic() { + public int getMusic() { return this.music; } diff --git a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java index a992ed0ef..65b4a0322 100644 --- a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java +++ b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java @@ -410,13 +410,13 @@ public final class ZoneMonitor { return; } } - MusicEntry music = r.getMusic(); - if (music == null) { + int music = r.getMusic(); + if (music == -1) { if (!player.getMusicPlayer().isPlaying()) { player.getMusicPlayer().playDefault(); } } else { - player.getMusicPlayer().play(music); + player.getMusicPlayer().unlock(music, true); } } From 8db9060a40d42878e211d0217d69005aa1be66d2 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 6 Oct 2024 09:59:02 +0000 Subject: [PATCH 012/306] Implemented the ogres in combat training camp --- Server/data/configs/npc_configs.json | 10 +++--- Server/data/configs/npc_spawns.json | 46 +++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 616d737c0..01db7199f 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -26861,7 +26861,7 @@ "attack_level": "1" }, { - "examine": "An angry Ogre in a funny hat.", + "examine": "Big, ugly, and smelly.", "melee_animation": "359", "range_animation": "359", "attack_speed": "6", @@ -26869,14 +26869,14 @@ "magic_animation": "359", "death_animation": "361", "name": "Ogre", - "defence_level": "30", + "defence_level": "54", "safespot": null, - "lifepoints": "48", - "strength_level": "30", + "lifepoints": "60", + "strength_level": "54", "id": "2801", "aggressive": "true", "range_level": "1", - "attack_level": "30" + "attack_level": "54" }, { "examine": "They just call him 'Coach'.", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 9442e9457..5eb7c1910 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -977,11 +977,15 @@ }, { "npc_id": "344", - "loc_data": "{3016,3187,1,1,0}-{3015,3183,1,1,0}-{3014,3181,1,1,0}-{3011,3185,1,1,0}-" + "loc_data": "{2510,3378,0,1,0}-{2511,3383,0,1,0}-{2515,3356,0,1,0}-{2519,3356,0,1,0}-{2521,3383,0,1,0}-{2524,3362,0,1,0}-{2525,3383,0,1,0}-" }, { "npc_id": "345", - "loc_data": "{3018,3185,2,1,0}-" + "loc_data": "{2519,3366,0,1,0}-{2525,3369,0,1,0}-{2531,3368,0,1,0}-" + }, + { + "npc_id": "346", + "loc_data": "{2508,3370,0,1,0}-{2512,3374,0,1,0}-{2518,3371,0,1,0}-{2525,3380,0,1,0}-" }, { "npc_id": "347", @@ -1571,6 +1575,10 @@ "npc_id": "560", "loc_data": "{2767,3122,0,1,6}-" }, + { + "npc_id": "561", + "loc_data": "{2514,3385,0,1,0}-" + }, { "npc_id": "562", "loc_data": "{2799,3438,0,1,1}-" @@ -5861,19 +5869,31 @@ }, { "npc_id": "2699", - "loc_data": "{3037,2982,0,0,6}-{3036,2979,0,0,6}-" + "loc_data": "{3016,3184,1,1,0}-" }, { "npc_id": "2700", - "loc_data": "{3037,2982,0,0,6}-" + "loc_data": "{3016,3182,1,1,0}-" + }, + { + "npc_id": "2701", + "loc_data": "{3011,3181,1,1,0}-" + }, + { + "npc_id": "2702", + "loc_data": "{3019,3180,1,1,0}-" + }, + { + "npc_id": "2703", + "loc_data": "{3012,3185,1,1,0}-" }, { "npc_id": "2704", - "loc_data": "{3034,2979,0,0,1}-{3033,2980,1,0,4}-{3032,2979,0,0,1}-{3034,2985,0,0,1}-{3035,2982,0,0,1}-{3019,3185,0,0,0}-" + "loc_data": "{3019,3185,0,0,0}-" }, { "npc_id": "2705", - "loc_data": "{3034,2985,1,0,1}-" + "loc_data": "{3018,3185,2,1,0}-" }, { "npc_id": "2706", @@ -5967,6 +5987,14 @@ "npc_id": "2800", "loc_data": "{2981,3190,0,0,0}-" }, + { + "npc_id": "2801", + "loc_data": "{2523,3373,0,1,0}-{2523,3376,0,1,0}-{2526,3373,0,1,0}-{2526,3376,0,1,0}-{2529,3373,0,1,0}-{2529,3376,0,1,0}-{2531,3376,0,1,0}-{2532,3373,0,1,0}-" + }, + { + "npc_id": "2802", + "loc_data": "{2406,3498,0,1,0}-" + }, { "npc_id": "2803", "loc_data": "{3391,3066,0,1,6}-{3397,3054,0,1,6}-{3398,3060,0,1,0}-{3412,3059,0,1,3}-" @@ -6075,6 +6103,10 @@ "npc_id": "2910", "loc_data": "{3082,9885,0,1,4}-" }, + { + "npc_id": "2932", + "loc_data": "{2437,3347,0,1,0}-" + }, { "npc_id": "2935", "loc_data": "{3671,3484,0,1,4}-" @@ -7293,7 +7325,7 @@ }, { "npc_id": "4375", - "loc_data": "{3012,3192,1,0,2}-" + "loc_data": "{3013,3192,1,0,6}-" }, { "npc_id": "4376", From 6b0f942598e28462be960bf3278a3da784cd51b6 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Sun, 6 Oct 2024 10:21:58 +0000 Subject: [PATCH 013/306] Fairy ring refactor Reimplemented the travel log, fixes the issue where all the travel log interface text collapses in on itself Travel log now displays the relevant code Log sorting implemented Fairy ring now remembers the last entered code and automatically re-enters it when opened Fairy ring no longer skips letters Direction clicks in quick succession now turn the wheel multiple times --- .../handlers/iface/FairyRingInterface.kt | 150 +++++++++--------- .../misc/zanaris/handlers/FairyRingPlugin.kt | 22 +-- Server/src/main/core/api/ContentAPI.kt | 11 +- .../net/packet/context/ContainerContext.java | 15 +- .../core/net/packet/out/ContainerPacket.java | 35 ++-- 5 files changed, 129 insertions(+), 104 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt index 70a005ec4..f73ec61c4 100644 --- a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt +++ b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt @@ -2,109 +2,128 @@ package content.global.handlers.iface import core.api.* import core.game.event.FairyRingDialEvent -import core.game.component.Component +import core.game.interaction.InterfaceListener import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager import core.game.system.task.Pulse +import core.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.RegionManager import core.tools.RandomFunction -import core.game.interaction.InterfaceListener -import core.game.world.GameWorld -val RING_1 = arrayOf('a','d','c','b') -val RING_2 = arrayOf('i','l','k','j') -val RING_3 = arrayOf('p','s','r','q') /** * Handles the fairy ring interface * @author Ceikry */ class FairyRingInterface : InterfaceListener { - - val RINGS = 734 - val TRAVEL_LOG = 735 + companion object { + const val RINGS_IFACE = 734 + const val LOG_IFACE_ID = 735 + const val VARP_F_RING = 816 + const val VB_LOG_SORT_ORDER = 4618 + const val VB_RING_1 = 2341 + const val VB_RING_2 = 2342 + const val VB_RING_3 = 2343 + val RING_1 = arrayOf('a','d','c','b') + val RING_2 = arrayOf('i','l','k','j') + val RING_3 = arrayOf('p','s','r','q') + } override fun defineInterfaceListeners() { - onOpen(RINGS){player, _ -> - player.interfaceManager.openSingleTab(Component(TRAVEL_LOG)) - player.setAttribute("fr:ring1", 0) - player.setAttribute("fr:ring2", 0) - player.setAttribute("fr:ring3", 0) - FairyRing.drawLog(player) + onOpen(RINGS_IFACE){ player, _ -> + openSingleTab(player, LOG_IFACE_ID) + saveVarp(player, VARP_F_RING) return@onOpen true } - onClose(RINGS){player, _ -> - closeTabInterface(player) - player.removeAttribute("fr:ring1") - player.removeAttribute("fr:ring2") - player.removeAttribute("fr:ring3") - setVarp(player, 816, 0) + onOpen(LOG_IFACE_ID){ player, _ -> + drawLog(player) + return@onOpen true + } + + onClose(RINGS_IFACE){ player, _ -> closeTabInterface(player) return@onClose true } - on(RINGS){player, _, _, buttonID, _, _ -> - if(player.getAttribute("fr:time",0L) > System.currentTimeMillis()) return@on true - var delayIncrementer = 1750L + on(RINGS_IFACE){ player, _, _, buttonID, _, _ -> when(buttonID){ - 23 -> delayIncrementer += increment(player,1) - 25 -> delayIncrementer += increment(player,2) - 27 -> delayIncrementer += increment(player,3) + 23 -> increment(player,1) + 25 -> increment(player,2) + 27 -> increment(player,3) 24 -> decrement(player,1) 26 -> decrement(player,2) 28 -> decrement(player,3) 21 -> confirm(player) } - player.setAttribute("fr:time",System.currentTimeMillis() + delayIncrementer) return@on true } - on(TRAVEL_LOG,12){player, _, _, _, _, _ -> + on(LOG_IFACE_ID,12){ player, _, _, _, _, _ -> toggleSortOrder(player) return@on true } } - private fun toggleSortOrder(player: Player): Long{ - val ring1index = player.getAttribute("fr:ring1",0) - var toSet = player.getAttribute("fr:sortorder",true) - toSet = !toSet - player.setAttribute("fr:sortorder",toSet) - if(toSet) { - setVarp(player, 816, ring1index) - player.setAttribute("fr:ring2",0) - player.setAttribute("fr:ring3",0) + /** + * Draws the travel log interface + * Currently, the visited logs is a bool array in globalData. Someone should migrate this to prefs or something at some point. + * On transmit of Varp 816, which all used varbits are part of here, the CS2 is invoked to populate the codes in the log and sort them correctly. + * @param player The player to draw the interface for + */ + private fun drawLog (player: Player) + { + for (i in FairyRing.values().indices) { + if (!player.savedData.globalData.hasTravelLog(i)) { + continue + } + val ring = FairyRing.values()[i] + if (ring.childId == -1) { + continue + } + setInterfaceText(player, "
${ring.tip}", LOG_IFACE_ID, ring.childId) } - return -1750L } - fun increment(player: Player,ring: Int): Long{ - val curIndex = player.getAttribute("fr:ring$ring",0) - var nextIndex = 0 - if(curIndex == 3) nextIndex = 0 - else if(curIndex == 1) nextIndex = 3 - else if(curIndex == 2) nextIndex = 2 - else nextIndex = curIndex + 1 - player.setAttribute("fr:ring$ring",nextIndex) - return if (curIndex == 1) 1750L else 0L + private fun toggleSortOrder(player: Player) { + val curSort = getVarbit(player, VB_LOG_SORT_ORDER) == 0 + setVarbit(player, VB_LOG_SORT_ORDER, if (curSort) 1 else 0) + drawLog(player) + } + + fun increment(player: Player,ring: Int) { + val vbit = when(ring) { + 1 -> VB_RING_1 + 2 -> VB_RING_2 + 3 -> VB_RING_3 + else -> return + } + val curIndex = getVarbit(player, vbit) + val nextIndex: Int = if(curIndex == 3) 0 + else curIndex + 1 + setVarbit(player, vbit, nextIndex) } fun decrement(player: Player,ring: Int){ - val curIndex = player.getAttribute("fr:ring$ring",0) - var nextIndex = 0 - if(curIndex == 0) nextIndex = 3 - else nextIndex = curIndex - 1 - player.setAttribute("fr:ring$ring",nextIndex) + val vbit = when(ring) { + 1 -> VB_RING_1 + 2 -> VB_RING_2 + 3 -> VB_RING_3 + else -> return + } + val curIndex = getVarbit(player, vbit) + val nextIndex: Int = if(curIndex == 0) 3 + else curIndex - 1 + setVarbit(player, vbit, nextIndex) } private fun confirm(player: Player){ - val ring1index = player.getAttribute("fr:ring1",0) - val ring2index = player.getAttribute("fr:ring2",0) - val ring3index = player.getAttribute("fr:ring3",0) + val ring1index = getVarbit(player, VB_RING_1) + val ring2index = getVarbit(player, VB_RING_2) + val ring3index = getVarbit(player, VB_RING_3) val code = "${RING_1[ring1index]}${RING_2[ring2index]}${RING_3[ring3index]}" val ring: FairyRing? = try { FairyRing.valueOf(code.uppercase()) @@ -208,23 +227,4 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int open fun checkAccess(player: Player) : Boolean { return true } - - companion object { - /** - * Draws the travel log. - * @param player the player. - */ - fun drawLog(player: Player) { - for (i in FairyRing.values().indices) { - if (!player.savedData.globalData.hasTravelLog(i)) { - continue - } - val ring = FairyRing.values()[i] - if (ring.childId == -1) { - continue - } - setInterfaceText(player, "
${ring.tip}", 735, ring.childId) - } - } - } } diff --git a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt index f93d9ebfb..4d40506b5 100644 --- a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt +++ b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt @@ -1,13 +1,15 @@ package content.region.misc.zanaris.handlers -import core.api.* -import core.game.component.Component +import content.global.handlers.iface.FairyRingInterface +import core.api.anyInEquipment +import core.api.hasRequirement +import core.api.openInterface +import core.game.interaction.IntType +import core.game.interaction.InteractionListener import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.world.map.Location import org.rs09.consts.Items -import core.game.interaction.InteractionListener -import core.game.interaction.IntType /** * Handles interactions with fairy rings @@ -59,17 +61,7 @@ class FairyRingPlugin : InteractionListener { return true } - private fun reset(player: Player) { - player.removeAttribute("fairy-delay") - player.removeAttribute("fairy_location_combo") - for (i in 0..2) { - setVarp(player, 816 + i, 0) - } - } - private fun openFairyRing(player: Player) { - reset(player) - player.interfaceManager.openSingleTab(Component(735)) - player.interfaceManager.open(Component(734)) + openInterface(player, FairyRingInterface.RINGS_IFACE) } } diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 0a7c70317..c25bb67bc 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -1253,10 +1253,19 @@ fun getVarbit (player: Player, varbitId: Int) : Int { @JvmOverloads fun setVarp (player: Player, varpIndex: Int, value: Int, save: Boolean = false) { player.varpMap[varpIndex] = value - player.saveVarp[varpIndex] = save + if (player.saveVarp[varpIndex] != true && save) + player.saveVarp[varpIndex] = true //only set if we're choosing to save. Prevents accidental unsaving. if you REALLY want to unsave a varp, use unsaveVarp. player.packetDispatch.sendVarp(varpIndex, value) } +fun saveVarp (player: Player, varpIndex: Int) { + player.saveVarp[varpIndex] = true +} + +fun unsaveVarp (player: Player, varpIndex: Int) { + player.saveVarp.remove(varpIndex) +} + @JvmOverloads fun setVarbit (player: Player, def: VarbitDefinition, value: Int, save: Boolean = false) { val mask = def.mask diff --git a/Server/src/main/core/net/packet/context/ContainerContext.java b/Server/src/main/core/net/packet/context/ContainerContext.java index 7b4a3ea9c..411a812cd 100644 --- a/Server/src/main/core/net/packet/context/ContainerContext.java +++ b/Server/src/main/core/net/packet/context/ContainerContext.java @@ -34,7 +34,9 @@ public final class ContainerContext implements Context { /** * The items. */ - private final Item[] items; + private Item[] items; + + public int[] ids; /** * The length of the array to send. @@ -115,6 +117,17 @@ public final class ContainerContext implements Context { this.slots = null; } + public ContainerContext(Player player, int interfaceId, int childId, int containerId, int[] items) { + this.player = player; + this.interfaceId = interfaceId; + this.childId = childId; + this.containerId = containerId; + this.ids = items; + this.length = items.length; + this.split = false; + this.slots = null; + } + /** * Constructs a new {@code ContainerContext} {@code Object}. * @param player The player. diff --git a/Server/src/main/core/net/packet/out/ContainerPacket.java b/Server/src/main/core/net/packet/out/ContainerPacket.java index 9e3b8eda8..8c669186e 100644 --- a/Server/src/main/core/net/packet/out/ContainerPacket.java +++ b/Server/src/main/core/net/packet/out/ContainerPacket.java @@ -42,19 +42,30 @@ public final class ContainerPacket implements OutgoingPacket { } } } else { - buffer.putShort(context.getItems().length); - for (Item item : context.getItems()) - if (item != null) { - int amount = item.getAmount(); - if (amount < 0 || amount > 254) { - buffer.putS(255).putInt(amount); - } else { - buffer.putS(amount); - } - buffer.putShort(item.getId() + 1); - } else { - buffer.putS(0).putShort(0); + if (context.ids != null) + { + buffer.p2(context.getLength()); + for (int i = 0; i < context.getLength(); i++) + { + buffer.putS(1); + buffer.p2(context.ids[i] + 1); } + } + else { + buffer.putShort(context.getItems().length); + for (Item item : context.getItems()) + if (item != null) { + int amount = item.getAmount(); + if (amount < 0 || amount > 254) { + buffer.putS(255).putInt(amount); + } else { + buffer.putS(amount); + } + buffer.putShort(item.getId() + 1); + } else { + buffer.putS(0).putShort(0); + } + } } } buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer); From 9c202aa47a29fd3cfa7e6b19853c992f437b2391 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 10:47:36 +0000 Subject: [PATCH 014/306] Rewrote pet back end to use a more authentic system Pets can now stack Fixes a bug where a pet could get reset to 0 hunger and growth when dropped Player save version migration messages are no longer shown Pets now morph into adults in-place --- .../item/withnpc/CatOnArdougneCivilian.kt | 2 +- .../skill/summoning/SummoningTabListener.kt | 2 +- .../summoning/familiar/BabyChinchompaNPC.java | 103 ---------- .../familiar/DismissDialoguePlugin.java | 2 +- .../summoning/familiar/FamiliarManager.java | 191 +++++++++--------- .../skill/summoning/familiar/KalphiteNPC.java | 117 ----------- .../summoning/familiar/SnakelingNPC.java | 114 ----------- .../skill/summoning/familiar/VetionNPC.java | 33 --- .../summoning/pet/KittenInteractDialogue.java | 2 +- .../global/skill/summoning/pet/Pet.java | 55 +++-- .../skill/summoning/pet/PetDetails.java | 27 +-- .../global/skill/summoning/pet/Pets.java | 57 +----- Server/src/main/core/ServerConstants.kt | 2 +- Server/src/main/core/api/ContentAPI.kt | 36 ++++ .../game/node/entity/npc/Metamorphosis.java | 94 --------- .../player/info/login/PlayerSaveParser.kt | 2 +- .../entity/player/info/login/PlayerSaver.kt | 20 +- .../player/info/login/SaveVersionHooks.kt | 21 +- Server/src/main/core/game/node/item/Item.java | 8 - 19 files changed, 204 insertions(+), 684 deletions(-) delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/BabyChinchompaNPC.java delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/KalphiteNPC.java delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/SnakelingNPC.java delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/VetionNPC.java delete mode 100644 Server/src/main/core/game/node/entity/npc/Metamorphosis.java diff --git a/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt b/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt index 7046b50a2..eee377bf4 100644 --- a/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt +++ b/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt @@ -47,7 +47,7 @@ class CatOnArdougneCivilian: InteractionListener { override fun defineListeners() { onUseWith(IntType.NPC,cats,*civilians){ player, used, _ -> sendItemDialogue(player,Items.DEATH_RUNE_560,"You hand over the cat.
You are given 100 Death Runes.") - player.familiarManager.removeDetails(used.idHash) + player.familiarManager.removeDetails(used.id) removeItem(player,used,Container.INVENTORY) addItem(player,Items.DEATH_RUNE_560,100) return@onUseWith true diff --git a/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt b/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt index 2a8debf26..c47862b62 100644 --- a/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt +++ b/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt @@ -44,7 +44,7 @@ class SummoningTabListener : InterfaceListener { // Dismiss now if (player.getFamiliarManager().getFamiliar() is Pet) { val pet = player.familiarManager.familiar as Pet - player.familiarManager.removeDetails(pet.getItemIdHash()) + player.familiarManager.removeDetails(pet.getItemId()) } player.familiarManager.dismiss() } diff --git a/Server/src/main/content/global/skill/summoning/familiar/BabyChinchompaNPC.java b/Server/src/main/content/global/skill/summoning/familiar/BabyChinchompaNPC.java deleted file mode 100644 index 66c03042b..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/BabyChinchompaNPC.java +++ /dev/null @@ -1,103 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.Metamorphosis; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.tools.RandomFunction; - -/** - * Handles the baby chinchompa pet. - * @author Empathy - * - */ -@Initializable -public class BabyChinchompaNPC extends Metamorphosis { - - /** - * The chinchompa ids. - */ - private static final int[] CHINCHOMPA_IDS = new int[] { 8643, 8644, 8657, 8658 }; - - /** - * Constructs a new {@code BabyChinchompaNPC} object. - */ - public BabyChinchompaNPC() { - super(CHINCHOMPA_IDS); - } - - @Override - public DialoguePlugin getDialoguePlugin() { - return new BabyChinchompaDialogue(); - } - - @Override - public int getRandomNpcId() { - int i = RandomFunction.getRandom(getIds().length - 1); - if (getIds()[i] == 8658) { - int x = RandomFunction.getRandom(30); - if (x == 1) { - return getIds()[i]; - } else { - return getIds()[i-1]; - } - } - return getIds()[i]; - } - - /** - * Handles the BabyChinchompa Dialogue. - * @author Empathy - * - */ - public final class BabyChinchompaDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code BabyChinchompaDialogue} {@code Object}. - */ - public BabyChinchompaDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code BabyChinchompaDialogue} {@code Object}. - * - * @param player the player. - */ - public BabyChinchompaDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new BabyChinchompaDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, npc.getId() != 8658 ? "Squeak! Squeak!" : "Squeaka! Squeaka!"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 8643, 8644, 8657, 8658 }; - } - } -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/DismissDialoguePlugin.java b/Server/src/main/content/global/skill/summoning/familiar/DismissDialoguePlugin.java index ff053a5da..b369bf4d6 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/DismissDialoguePlugin.java +++ b/Server/src/main/content/global/skill/summoning/familiar/DismissDialoguePlugin.java @@ -55,7 +55,7 @@ public final class DismissDialoguePlugin extends DialoguePlugin { if (player.getFamiliarManager().getFamiliar() instanceof Pet) { interpreter.sendDialogues(player, null, "Run along; I'm setting you free."); Pet pet = (Pet) player.getFamiliarManager().getFamiliar(); - player.getFamiliarManager().removeDetails(pet.getItemIdHash()); + player.getFamiliarManager().removeDetails(pet.getItemId()); } else { end(); } diff --git a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java index f6a4b8f90..02bb0a403 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java +++ b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java @@ -4,7 +4,6 @@ import content.global.skill.summoning.pet.Pet; import content.global.skill.summoning.pet.Pets; import core.cache.def.impl.ItemDefinition; import core.game.component.Component; -import core.game.container.Container; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import core.game.node.entity.skill.Skills; @@ -20,7 +19,6 @@ import core.game.world.update.flag.context.Animation; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import static core.api.ContentAPIKt.*; @@ -38,9 +36,9 @@ public final class FamiliarManager { private static final Map FAMILIARS = new HashMap<>(); /** - * The pet details mapping, sorted by item id. + * The pet details mapping. */ - private final Map petDetails = new HashMap(); + private final Map> petDetails = new HashMap<>(); /** * The player. @@ -70,50 +68,69 @@ public final class FamiliarManager { this.player = player; } - public final void parse(JSONObject familiarData) { + public void parse(JSONObject familiarData) { + for (Pets pet : Pets.values()) { + for (int id : new int[]{pet.getBabyItemId(), pet.getGrownItemId(), pet.getOvergrownItemId()}) { + if (id != -1) { + petDetails.put(id, new ArrayList()); + } + } + } + int currentPet = -1; if (familiarData.containsKey("currentPet")) { currentPet = Integer.parseInt(familiarData.get("currentPet").toString()); } - JSONArray petDetails = (JSONArray) familiarData.get("petDetails"); - for (int i = 0; i < petDetails.size(); i++) { - JSONObject detail = (JSONObject) petDetails.get(i); - PetDetails details = new PetDetails(0); - details.updateHunger(Double.parseDouble(detail.get("hunger").toString())); - details.updateGrowth(Double.parseDouble(detail.get("growth").toString())); - int itemIdHash = Integer.parseInt(detail.get("petId").toString()); - // The below is for migrating legacy saves, which stored baby item IDs + growth stages - if (detail.containsKey("stage")) { - // The "itemIdHash" is actually the baby item ID. The "stage" gives the actual pet stage we want. - int babyItemId = itemIdHash; - int itemId = babyItemId; - int stage = Integer.parseInt(detail.get("stage").toString()); - if (stage > 0) { - Pets pets = Pets.forId(babyItemId); - itemId = pets.getNextStageItemId(itemId); - if (stage > 1) { + if (player.version < 2) { //migrate the v1 format + JSONArray petDetails = (JSONArray) familiarData.get("petDetails"); + for (Object petDetail : petDetails) { + JSONObject detail = (JSONObject) petDetail; + PetDetails details = new PetDetails(0); + details.updateHunger(Double.parseDouble(detail.get("hunger").toString())); + details.updateGrowth(Double.parseDouble(detail.get("growth").toString())); + int itemId; + int itemIdHash = Integer.parseInt(detail.get("petId").toString()); + // The below is for migrating the v0 format, which stored baby item IDs + growth stages + if (detail.containsKey("stage")) { + // The itemIdHash is actually the baby item ID. The "stage" gives the actual pet stage we want. + int babyItemId = itemIdHash; + itemId = babyItemId; + int stage = Integer.parseInt(detail.get("stage").toString()); + if (stage > 0) { + Pets pets = Pets.forId(babyItemId); itemId = pets.getNextStageItemId(itemId); + if (stage > 1) { + itemId = pets.getNextStageItemId(itemId); + } } + } else { + itemId = itemIdHash >> 16 & 0xFFFF; //in the legacy v1 format, was hash rather than item id } - Item item = new Item(itemId); - item.setCharge(1000); //this is the default value that will correspond to the player's item - itemIdHash = item.getIdHash(); - if (currentPet != -1 && currentPet == babyItemId) { - currentPet = itemIdHash; + this.petDetails.get(itemId).add(details); + } + if (currentPet > 65536) { + currentPet = currentPet >> 16 & 0xFFFF; //in the legacy v1 format, was hash rather than item id + } + } else { + JSONObject petDetails = (JSONObject) familiarData.get("petDetails"); + for (Object key : petDetails.keySet()) { + int itemId = Integer.parseInt(key.toString()); + this.petDetails.put(itemId, new ArrayList<>()); + JSONArray values = (JSONArray) petDetails.get(key.toString()); + for (Object petDetail : values) { + JSONObject detail = (JSONObject) petDetail; + PetDetails details = new PetDetails(0); + details.updateHunger(Double.parseDouble(detail.get("hunger").toString())); + details.updateGrowth(Double.parseDouble(detail.get("growth").toString())); + this.petDetails.get(itemId).add(details); } } - this.petDetails.put(itemIdHash, details); } - if (currentPet != -1) { - PetDetails details = this.petDetails.get(currentPet); - int itemId = currentPet >> 16 & 0xFFFF; - Pets pets = Pets.forId(itemId); - if (details == null) { - details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0); - this.petDetails.put(currentPet, details); - } - familiar = new Pet(player, details, itemId, pets.getNpcId(itemId)); + int last = this.petDetails.get(currentPet).size() - 1; + PetDetails details = this.petDetails.get(currentPet).get(last); + Pets pets = Pets.forId(currentPet); + familiar = new Pet(player, details, currentPet, pets.getNpcId(currentPet)); } else if (familiarData.containsKey("familiar")) { JSONObject currentFamiliar = (JSONObject) familiarData.get("familiar"); int familiarId = Integer.parseInt( currentFamiliar.get("originalId").toString()); @@ -147,7 +164,7 @@ public final class FamiliarManager { public void summon(Item item, boolean pet, boolean deleteItem) { boolean renew = false; if (hasFamiliar()) { - if(familiar.getPouchId() == item.getId()) { + if (familiar.getPouchId() == item.getId()) { renew = true; } else { player.getPacketDispatch().sendMessage("You already have a follower."); @@ -180,7 +197,7 @@ public final class FamiliarManager { player.getPacketDispatch().sendMessage("Invalid familiar " + npcId + " - report on 2009Scape GitLab"); return; } - if(!renew) { + if (!renew) { fam = fam.construct(player, npcId); if (fam.getSpawnLocation() == null) { player.getPacketDispatch().sendMessage("The spirit in this pouch is too big to summon here. You will need to move to a larger"); @@ -193,7 +210,7 @@ public final class FamiliarManager { } player.getSkills().updateLevel(Skills.SUMMONING, -pouch.getSummonCost(), 0); player.getSkills().addExperience(Skills.SUMMONING, pouch.getSummonExperience()); - if(!renew) { + if (!renew) { familiar = fam; spawnFamiliar(); } else { @@ -217,11 +234,10 @@ public final class FamiliarManager { * @param deleteItem the item. * @param location the location. */ - public void morphPet(final Item item, boolean deleteItem, Location location) { - if (hasFamiliar()) { - familiar.dismiss(); - } - summonPet(item, deleteItem, true, location); + public void morphPet(final Item item, boolean deleteItem, Location location, double hunger, double growth) { + int hasWarned = ((Pet) familiar).getHasWarned(); + familiar.dismiss(); + summonPet(item, deleteItem, true, location, hasWarned, hunger, growth); } /** @@ -230,7 +246,7 @@ public final class FamiliarManager { * @param deleteItem the item. */ private boolean summonPet(final Item item, boolean deleteItem) { - return summonPet(item, deleteItem, false, null); + return summonPet(item, deleteItem, false, null, 0, -1, -1); } /** @@ -238,9 +254,8 @@ public final class FamiliarManager { * @param item the item. * @param morph the pet. */ - private boolean summonPet(final Item item, boolean deleteItem, boolean morph, Location location) { + private boolean summonPet(final Item item, boolean deleteItem, boolean morph, Location location, int hasWarned, double hunger, double growth) { final int itemId = item.getId(); - int itemIdHash = item.getIdHash(); if (itemId > 8850 && itemId < 8900) { return false; } @@ -252,52 +267,24 @@ public final class FamiliarManager { player.getDialogueInterpreter().sendDialogue("You need a summoning level of " + pets.getSummoningLevel() + " to summon this."); return false; } - - // If this pet does not have an individual ID yet, we need to find it an available one. - // If it does, we need to verify that this ID is not already used for a different pet. This is needed to correct a historical bug that allowed multiple pets to be assigned the same individual ID (the historical code only checked the *current* stage item ID, failing to realize that we also need to account for *future* stage item IDs, in case the current pet grows up, resulting in a clash when it did). Saves affected by that bug will have multiple copies of the same item pointing to the same pet, which we have an opportunity to rectify now. - ArrayList taken = new ArrayList(); - Container[] searchSpace = {player.getInventory(), player.getBankPrimary(), player.getBankSecondary()}; - for (int checkId = pets.getBabyItemId(); checkId != -1; checkId = pets.getNextStageItemId(checkId)) { - Item check = new Item(checkId, 1); - for (Container container : searchSpace) { - for (Item i : container.getAll(check)) { - taken.add(i.getCharge()); - } - } - } - PetDetails details = petDetails.get(itemIdHash); - int individual = item.getCharge(); - if (details != null) { //we have this pet on file, but we need to check that it wasn't affected by the historical bug mentioned above - details.setIndividual(individual); - int count = 0; - for (int i : taken) { - if (i == individual) { - count++; - } - } - if (count > 1) { //this pet is sadly conjoined with another individual of its kind; untangle it by initializing it anew (which is what should have happened in the first place, save the minor detail of hunger propagation from the previous stage, which we no longer have any record of) - details = null; - } - } - if (details == null) { //init new pet - details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0); - for (individual = 0; taken.contains(individual) && individual < 0xFFFF; individual++) {} - details.setIndividual(individual); - // Make a copy of the item to extract what the item's idHash will be when including the individual ID as a "charge" value. - // The copy is necessary since the player's inventory still contains the default-charged item, which we will be removing only later. - Item newItem = item.copy(); - newItem.setCharge(individual); - petDetails.put(newItem.getIdHash(), details); + int last = this.petDetails.get(itemId).size() - 1; + if (last < 0) { //new pet + last = 0; + PetDetails details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0); + this.petDetails.get(itemId).add(details); } + PetDetails details = this.petDetails.get(itemId).get(last); int npcId = pets.getNpcId(itemId); if (npcId > 0) { familiar = new Pet(player, details, itemId, npcId); + ((Pet) familiar).setHasWarned(hasWarned); + if (hunger != -1) ((Pet) familiar).getDetails().setHunger(hunger); + if (growth != -1) ((Pet) familiar).getDetails().setGrowth(growth); if (deleteItem) { player.animate(new Animation(827)); - // We cannot use player().getInventory().remove(item), because that will remove the first pet item it sees, rather than the specific one (with the specific charge value) the player clicked. - // Instead, find the specific item the player dropped by slot, and remove that specific one. - int slot = player.getInventory().getSlotHash(item); - player.getInventory().remove(item, slot, true); + if (!player.getInventory().remove(item, true)) { + return false; + } } if (morph) { morphFamiliar(location); @@ -364,11 +351,7 @@ public final class FamiliarManager { return; } Pet pet = ((Pet) familiar); - PetDetails details = pet.getDetails(); - Item petItem = new Item(pet.getItemId()); - petItem.setCharge(details.getIndividual()); - if (player.getInventory().add(petItem)) { - petDetails.put(pet.getItemIdHash(),details); + if (player.getInventory().add(new Item(pet.getItemId()))) { player.animate(Animation.create(827)); player.getFamiliarManager().dismiss(); } @@ -423,11 +406,23 @@ public final class FamiliarManager { } /** - * Removes the details for this pet. - * @param itemIdHash The item id hash of the pet. + * Adds pet details for a new pet to that pet's stack. + * @param itemId The item id of the pet. + * @param details The new pet details. */ - public void removeDetails(int itemIdHash) { - petDetails.remove(itemIdHash); + public void addDetails(int itemId, PetDetails details) { + petDetails.get(itemId).add(details); + } + + /** + * Removes the details for this pet. + * @param itemId The item id of the pet. + */ + public void removeDetails(int itemId) { + int last = petDetails.get(itemId).size() - 1; + if (last >= 0) { + petDetails.get(itemId).remove(last); + } } /** @@ -521,7 +516,7 @@ public final class FamiliarManager { } - public Map getPetDetails() { + public Map> getPetDetails() { return petDetails; } } diff --git a/Server/src/main/content/global/skill/summoning/familiar/KalphiteNPC.java b/Server/src/main/content/global/skill/summoning/familiar/KalphiteNPC.java deleted file mode 100644 index 62b5020a0..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/KalphiteNPC.java +++ /dev/null @@ -1,117 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.plugin.Initializable; -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.Metamorphosis; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; - -/** - * Handles the kalphite princess pet. - * @author Empathy - * - */ -@Initializable -public class KalphiteNPC extends Metamorphosis { - - /** - * The kalphite ids. - */ - private static final int[] KALPHITE_IDS = new int[] { 8602, 8603 }; - - /** - * Constructs a new {@code KalphiteNPC} object. - */ - public KalphiteNPC() { - super(KALPHITE_IDS); - } - - - @Override - public DialoguePlugin getDialoguePlugin() { - return new KalphitePrincessDialogue(); - } - - /** - * Handles the KalphitePrincess dialogue. - * @author Empathy - * - */ - public final class KalphitePrincessDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code KalphitePrincessDialogue} {@code Object}. - */ - public KalphitePrincessDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code KalphitePrincessDialogue} {@code Object}. - * - * @param player the player. - */ - public KalphitePrincessDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new KalphitePrincessDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What is it with your kind and potato cactus?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Truthfully?"); - stage = 1; - break; - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yeah, please."); - stage = 2; - break; - case 2: - interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Soup. We make a fine soup with it."); - stage = 3; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Kalphites can cook?"); - stage = 4; - break; - case 4: - interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Nah, we just collect it and put it there because we", "know fools like yourself will come down looking for it", "then inevitably be killed by my mother."); - stage = 5; - break; - case 5: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Evidently not, that's how I got you!"); - stage = 6; - break; - case 6: - interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Touch�."); - stage = 7; - break; - case 7: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 8602, 8603 }; - } - } -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/SnakelingNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SnakelingNPC.java deleted file mode 100644 index cd6372f62..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/SnakelingNPC.java +++ /dev/null @@ -1,114 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.plugin.Initializable; -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.Metamorphosis; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; - -/** - * Handles the metamorphosis of the zulrah pet. - * @author Empathy - * - */ -@Initializable -public class SnakelingNPC extends Metamorphosis { - - /** - * The snakeling ids. - */ - public static final int[] SNAKELING_IDS = new int[] { 8626, 8627, 8628 }; - - /** - * - * Constructs a new {@code SnakelingNPC} object. - */ - public SnakelingNPC() { - super(SNAKELING_IDS); - } - - @Override - public DialoguePlugin getDialoguePlugin() { - return new PetSnakelingDialogue(); - } - - /** - * Handles the pet snakeling dialogue. - * @author Empathy - * - */ - public final class PetSnakelingDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code PetSnakelingDialogue} {@code Object}. - */ - public PetSnakelingDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code PetSnakelingDialogue} {@code Object}. - * - * @param player the player. - */ - public PetSnakelingDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new PetSnakelingDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - player("Hey little snake!"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc(FacialExpression.OLD_NORMAL, "Soon, Zulrah shall establish dominion over this plane."); - stage = 1; - break; - case 1: - player("Wanna play fetch?"); - stage = 2; - break; - case 2: - npc(FacialExpression.OLD_NORMAL, "Submit to the almighty Zulrah."); - stage = 3; - break; - case 3: - player("Walkies? Or slidies...?"); - stage = 4; - break; - case 4: - npc(FacialExpression.OLD_NORMAL, "Zulrah's wilderness as a God will soon be demonstrated."); - stage = 5; - break; - case 5: - player("I give up..."); - stage = 6; - break; - case 6: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return SNAKELING_IDS; - } - } - -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/VetionNPC.java b/Server/src/main/content/global/skill/summoning/familiar/VetionNPC.java deleted file mode 100644 index f939260f2..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/VetionNPC.java +++ /dev/null @@ -1,33 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.plugin.Initializable; -import core.game.dialogue.DialoguePlugin; -import core.game.node.entity.npc.Metamorphosis; - -/** - * Handles the metamorphosis of Vet'ion Jr. - * @author Empathy - * - */ -@Initializable -public class VetionNPC extends Metamorphosis { - - /** - * The Vet'ion Ids. - */ - public static final int[] VETION_IDS = new int[] { 8600, 8654 }; - - /** - * - * Constructs a new{@code VetionNPC} object. - */ - public VetionNPC() { - super(VETION_IDS); - } - - @Override - public DialoguePlugin getDialoguePlugin() { - return null; - } - -} diff --git a/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java b/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java index ebeb5b477..8925c4c42 100644 --- a/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java +++ b/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java @@ -117,8 +117,8 @@ public final class KittenInteractDialogue extends DialoguePlugin { player.sendChat("Shoo cat!"); Pet currentPet = (Pet) player.getFamiliarManager().getFamiliar(); player.getFamiliarManager().getFamiliar().sendChat("Miaow!"); - player.getFamiliarManager().removeDetails(currentPet.getItemIdHash()); player.getFamiliarManager().getFamiliar().dismiss(); + player.getFamiliarManager().removeDetails(currentPet.getItemId()); player.getPacketDispatch().sendMessage("The cat has run away."); } end(); diff --git a/Server/src/main/content/global/skill/summoning/pet/Pet.java b/Server/src/main/content/global/skill/summoning/pet/Pet.java index e4812dac1..439504c49 100644 --- a/Server/src/main/content/global/skill/summoning/pet/Pet.java +++ b/Server/src/main/content/global/skill/summoning/pet/Pet.java @@ -30,7 +30,7 @@ public final class Pet extends Familiar { /** * The growth rate of the pet. */ - private double growthRate; + private final double growthRate; /** * The pets type. @@ -86,8 +86,8 @@ public final class Pet extends Familiar { hasWarned = 2; } if (hunger >= 100.0 && growthRate != 0 && pet.getFood().length != 0) { - owner.getFamiliarManager().removeDetails(this.getItemIdHash()); owner.getFamiliarManager().dismiss(); + owner.getFamiliarManager().removeDetails(getItemId()); owner.getFamiliarManager().setFamiliar(null); setVarp(owner, 1175, 0); owner.sendMessage("Your pet has run away."); @@ -126,16 +126,10 @@ public final class Pet extends Familiar { // then this pet is already overgrown return; } - owner.getFamiliarManager().removeDetails(this.getItemIdHash()); - owner.getFamiliarManager().dismiss(); + owner.getFamiliarManager().removeDetails(getItemId()); + owner.getFamiliarManager().addDetails(newItemId, details); + owner.getFamiliarManager().morphPet(new Item(newItemId), false, location, details.getHunger(), 0); owner.getPacketDispatch().sendMessage("Your pet has grown larger."); - int npcId = pet.getNpcId(newItemId); - details.updateGrowth(-100.0); - Pet newPet = new Pet(owner, details, newItemId, npcId); - newPet.growthRate = growthRate; - newPet.hasWarned = hasWarned; - owner.getFamiliarManager().setFamiliar(newPet); - owner.getFamiliarManager().spawnFamiliar(); } @Override @@ -161,16 +155,6 @@ public final class Pet extends Familiar { return itemId; } - /** - * Gets the itemId with the individual hashed in. - * @return The itemIdHash. - */ - public int getItemIdHash() { - Item item = new Item(itemId); - item.setCharge(details.getIndividual()); - return item.getIdHash(); - } - /** * Gets the details. * @return The details. @@ -187,9 +171,36 @@ public final class Pet extends Familiar { return pet; } + /** + * Gets the hunger level. + */ + public double getHunger() { + return details.getHunger(); + } + + /** + * Gets the growth level. + */ + public double getGrowth() { + return details.getGrowth(); + } + + /** + * Gets the hunger warning level. + */ + public int getHasWarned() { + return hasWarned; + } + + /** + * Sets the hunger warning level. + */ + public void setHasWarned(int value) { + this.hasWarned = value; + } + @Override public int[] getIds() { return new int[] { 761, 762, 763, 764, 765, 766, 3505, 3598, 6969, 7259, 7260, 6964, 7249, 7251, 6960, 7241, 7243, 6962, 7245, 7247, 6966, 7253, 7255, 6958, 7237, 7239, 6915, 7277, 7278, 7279, 7280, 7018, 7019, 7020, 6908, 7313, 7316, 6947, 7293, 7295, 7297, 7299, 6911, 7261, 7263, 7265, 7267, 7269, 6919, 7301, 7303, 7305, 7307, 6949, 6952, 6955, 6913, 7271, 7273, 6945, 7319, 7321, 7323, 7325, 7327, 6922, 6942, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 6900, 6902, 6904, 6906, 768, 769, 770, 771, 772, 773, 3504, 6968, 7257, 7258, 6965, 7250, 7252, 6961, 7242, 7244, 6963, 7246, 7248, 6967, 7254, 7256, 6859, 7238, 7240, 6916, 7281, 7282, 7283, 7284, 7015, 7016, 7017, 6909, 7314, 7317, 6948, 7294, 7296, 7298, 7300, 6912, 7262, 7264, 7266, 7268, 7270, 6920, 7302, 7304, 7306, 7308, 6950, 6953, 6956, 6914, 7272, 7274, 6946, 7320, 7322, 7324, 7326, 7328, 6923, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 6901, 6903, 6905, 6907, 774, 775, 776, 777, 778, 779, 3503, 6951, 6954, 6957 }; } - } diff --git a/Server/src/main/content/global/skill/summoning/pet/PetDetails.java b/Server/src/main/content/global/skill/summoning/pet/PetDetails.java index b3e01c869..b3b0b8f05 100644 --- a/Server/src/main/content/global/skill/summoning/pet/PetDetails.java +++ b/Server/src/main/content/global/skill/summoning/pet/PetDetails.java @@ -19,11 +19,6 @@ public final class PetDetails { */ private double growth = 0.0; - /** - * The individual, an in principle arbitrary integer read off of the item's charge slot. - */ - private int individual; - /** * Constructs a new {@code PetDetails} {@code Object}. * @param growth The growth value. @@ -64,6 +59,13 @@ public final class PetDetails { return hunger; } + /** + * Sets the hunger. (You probably want to use updateHunger() instead.) + */ + public void setHunger(double value) { + this.hunger = value; + } + /** * Gets the growth. * @return The growth. @@ -73,18 +75,9 @@ public final class PetDetails { } /** - * Sets the individual. - * @param individual The individual to set. + * Sets the growth. (You probably want to use updateGrowth() instead.) */ - public void setIndividual(int individual) { - this.individual = individual; - } - - /** - * Gets the individual. - * @return The individual. - */ - public int getIndividual() { - return individual; + public void setGrowth(double value) { + this.growth = value; } } diff --git a/Server/src/main/content/global/skill/summoning/pet/Pets.java b/Server/src/main/content/global/skill/summoning/pet/Pets.java index 843075d28..75001becd 100644 --- a/Server/src/main/content/global/skill/summoning/pet/Pets.java +++ b/Server/src/main/content/global/skill/summoning/pet/Pets.java @@ -180,61 +180,6 @@ public enum Pets { */ BABY_DRAGON(12469, 12470, -1, 6900, 6901, -1, 0.0052, 99, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270), BABY_DRAGON_1(12471, 12472, -1, 6902, 6903, -1, 0.0052, 99, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270), BABY_DRAGON_2(12473, 12474, -1, 6904, 6905, -1, 0.0052, 99, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270), BABY_DRAGON_3(12475, 12476, -1, 6906, 6907, -1, 0.0052, 99, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270); - -// /** -// * Emperor's pets (that's right, MY pet"S"). -// */ -// GIANT_WOLPERTINGER(8888, -1, -1, 6990, -1, -1, 0.0, 99), DRAKAN(8889, -1, -1, 4794, -1, -1, 0.0, 99), DILL(8890, -1, -1, 7770, -1, -1, 0.0, 99), - -// /** -// * Vexias pet. -// */ -// IMP(9952, -1, -1, 1531, -1, -1, 0.0, 99), BIG_GUY(9951, -1, -1, 3101, -1, -1, 0.0, 99), LITTLE_GUY(8887, -1, -1, 5805, -1, -1, 0.0, 99), -// -// /** -// * Godwars boss pets. -// */ -// KRIL_JR(14648, -1, -1, 8591, -1, -1, 0.0, 1), KREE_JR(14645, -1, -1, 8592, -1, -1, 0.0, 1), ZILYANA_JR(14647, -1, -1, 8593, -1, -1, 0.0, 1), GRAARDOOR_JR(14646, -1, -1, 8594, -1, -1, 0.0, 1), -// -// /** -// * Classic boss pets. -// */ -// CHAOS_ELE_JR(14638, -1, -1, 8595, -1, -1, 0.0, 1), PRINCE_BLACK_DRAGON(14649, -1, -1, 8596, -1, -1, 0.0, 1), BABY_MOLE(14642, -1, -1, 8601, -1, -1, 0.0, 1), KQ_FORM_1(14643, -1, -1, 8602, -1, -1, 0.0, 1), KQ_FORM_2(14650, -1, -1, 8603, -1, -1, 0.0, 1), DARK_CORE(14653, -1, -1, 8630, -1, -1, 0.0, 1), -// -// /** -// * The boss pets for the Dagannoths -// */ -// DAGANNOTH_SUPREME(14639, -1, -1, 8605, -1, -1, 0.0, 1), DAGANNOTH_PRIME(14640, -1, -1, 8606, -1, -1, 0.0, 1), DAGANNOTH_REX(14641, -1, -1, 8607, -1, -1, 0.0, 1), -// /** -// * The new OSRS bosses. -// */ -// CALLISTO_CUB(14658, -1, -1, 8597, -1, -1, 0.0, 1), -// SCORPIA_JR(14661, -1, -1, 8598, -1, -1, 0.0, 1), -// VENENATIS_JR(14657, -1, -1, 8654, -1, -1, 0.0, 1), -// VETION_JR(14659, -1, -1, 8600, -1, -1, 0.0, 1), -// VETION_JR_2(14660, -1, -1, 8654, -1, -1, 0.0, 1), -// RELEASE_THE_KRAKEN(14651, -1, -1, 8608, -1, -1, 0.0, 1), -// SMOKE_DEVIL(14644, -1, -1, 8609, -1, -1, 0.0, 1), -// SNAKELING_YELLOW(14654, -1, -1, 8626, -1, -1, 0.0, 1), -// SNAKELING_ORANGE(14655, -1, -1, 8627, -1, -1, 0.0, 1), -// SNAKELING_PURPLE(14656, -1, -1, 8628, -1, -1, 0.0, 1), -// /** -// * The boss pet representing the likeness of the Penance Queen -// */ -// DRAMA_QUEEN(14652, -1, -1, 8604, -1, -1, 0.0, 1), -// /** -// * The skilling pets -// */ -// BEAVER(14821, -1, -1, 8635, -1, -1, 0.0, 1), -// ROCK_GOLEM(14822, -1, -1, 8637, -1, -1, 0.0, 1), -// BABY_RED_CHINCHOMPA(14823, -1, -1, 8643, -1, -1, 0.0, 1), -// BABY_GREY_CHINCHOMPA(14824, -1, -1, 8644, -1, -1, 0.0, 1), -// BABY_BLACK_CHINCHOMPA(14825, -1, -1, 8657, -1, -1, 0.0, 1), -// BABY_GOLD_CHINCHOMPA(14826, -1, -1, 8658, -1, -1, 0.0, 1), -// HERON(14827, -1, -1, 8647, -1, -1, 0.0, 1), -// TZREK_JAD(14828, -1, -1, 8650, -1, -1, 0.0, 1); - - /** * The baby pets mapping. */ @@ -481,4 +426,4 @@ public enum Pets { } return -1; } -} \ No newline at end of file +} diff --git a/Server/src/main/core/ServerConstants.kt b/Server/src/main/core/ServerConstants.kt index 6082e86c7..55a0eca1d 100644 --- a/Server/src/main/core/ServerConstants.kt +++ b/Server/src/main/core/ServerConstants.kt @@ -18,7 +18,7 @@ class ServerConstants { var NOAUTH_DEFAULT_ADMIN: Boolean = true @JvmField - var CURRENT_SAVEFILE_VERSION = 1 + var CURRENT_SAVEFILE_VERSION = 2 @JvmField var DAILY_ACCOUNT_LIMIT = 3 diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index c25bb67bc..84d41d69a 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -326,6 +326,7 @@ fun addItem(player: Player, id: Int, amount: Int = 1, container: Container = Con * @param player the player whose container to modify * @param slot the slot to use * @param item the item to replace the slot with + * @param currentItem the current item that is being replaced * @param container the Container to modify * @return the item that was previously in the slot, or null if none. */ @@ -358,6 +359,41 @@ fun replaceSlot(player: Player, slot: Int, item: Item, currentItem: Item? = null return null } +/** + * Replaces all items a player owns anywhere (equipment, inventory, bank, second bank) + * @param player the player whose inventory to remove the item from + * @param itemId the item ID to replace + * @param replaceId the replacement item ID + * @author Player Name + */ +fun replaceAllItems(player: Player, itemId: Int, replaceId: Int) { + val item = Item(itemId) + for (container in arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary)) { + val hasItems = container.getAll(item) + if (!item.definition.isStackable && (container == player.inventory || container == player.equipment)) { + for (target in hasItems) { + val newItem = Item(replaceId, target.amount) + container.replace(newItem, target.slot, true) + } + } else { + if (hasItems.size > 0) { + val target = hasItems[0] + var count = 0 + for (x in hasItems) { + count += x.amount + } + val newItem = Item(replaceId, count) + container.replace(newItem, target.slot, true) + } + if (hasItems.size > 1) { + for (i in 1 until hasItems.size) { + container.remove(hasItems[i], hasItems[i].slot, true) + } + } + } + } +} + /** * Add an item with a variable quantity or drop it if a player does not have enough space * @param player the player whose inventory to add to diff --git a/Server/src/main/core/game/node/entity/npc/Metamorphosis.java b/Server/src/main/core/game/node/entity/npc/Metamorphosis.java deleted file mode 100644 index 9b3175aed..000000000 --- a/Server/src/main/core/game/node/entity/npc/Metamorphosis.java +++ /dev/null @@ -1,94 +0,0 @@ -package core.game.node.entity.npc; - -import core.cache.def.impl.NPCDefinition; -import core.game.dialogue.DialoguePlugin; -import content.global.skill.summoning.familiar.Familiar; -import content.global.skill.summoning.pet.Pets; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.item.Item; -import core.plugin.Plugin; -import core.plugin.ClassScanner; -import core.tools.RandomFunction; - -/** - * A superclass plugin for any pets that have a metamorphosis option. - * @author Empathy - * - */ -public abstract class Metamorphosis extends OptionHandler { - - /** - * The ids of the possible npcs to metamorph into. - */ - protected int[] ids; - - - /** - * Constructs a new {@code Metamorphosis} {@code Object}. - * @param ids the id to transform. - */ - public Metamorphosis(int...ids) { - this.ids = ids; - } - - /** - * The dialogue plugin for the pet. - * @return the plugin. - */ - public abstract DialoguePlugin getDialoguePlugin(); - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (int id : getIds()) { - NPCDefinition.forId(id).getHandlers().put("option:metamorphosis", this); - } - if (getDialoguePlugin() != null) { - ClassScanner.definePlugin(getDialoguePlugin()); - } - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - Familiar familiar = (Familiar) node; - switch (option) { - case "metamorphosis": - if (player.getFamiliarManager().isOwner(familiar)) { - int newNpc = player.getFamiliarManager().getFamiliar().getId(); - while (newNpc == player.getFamiliarManager().getFamiliar().getId()) { - newNpc = getRandomNpcId(); - } - for (Pets p : Pets.values()) { - if (p.getBabyNpcId() == newNpc) { - player.getFamiliarManager().morphPet(new Item(p.getBabyItemId()), false, player.getFamiliarManager().getFamiliar().getLocation()); - break; - } - } - player.getPacketDispatch().sendMessage("You transform your " + player.getFamiliarManager().getFamiliar().getName() + "!"); - } else { - player.getPacketDispatch().sendMessage("This is not your familiar."); - } - break; - } - return true; - } - - /** - * Gets a random npc id. - * @return - */ - public int getRandomNpcId() { - int i = RandomFunction.getRandom(getIds().length - 1); - return getIds()[i]; - } - - /** - * Gets the npc ids. - * @return the id. - */ - public int[] getIds() { - return ids; - } -} diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index 1d712aeef..d9b0105f0 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -53,6 +53,7 @@ class PlayerSaveParser(val player: Player) { } fun parseData() { + parseVersion() parseCore() parseAttributes() parseSkills() @@ -77,7 +78,6 @@ class PlayerSaveParser(val player: Player) { parseStatistics() parseAchievements() parsePouches() - parseVersion() } fun runContentHooks() diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 511f730a2..4f1f176b4 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -36,6 +36,7 @@ class PlayerSaver (val player: Player){ } fun populate(): JSONObject { val saveFile = JSONObject() + saveVersion(saveFile) saveCoreData(saveFile) saveSkills(saveFile) saveSettings(saveFile) @@ -56,7 +57,6 @@ class PlayerSaver (val player: Player){ saveStatManager(saveFile) saveAttributes(saveFile) savePouches(saveFile) - saveVersion(saveFile) contentHooks.forEach { it.savePlayer(player, saveFile) } return saveFile } @@ -278,17 +278,21 @@ class PlayerSaver (val player: Player){ fun saveFamiliarManager(root: JSONObject){ val familiarManager = JSONObject() - val petDetails = JSONArray() + val petDetails = JSONObject() player.familiarManager.petDetails.map { - val detail = JSONObject() - detail.put("petId",it.key.toString()) - detail.put("hunger",it.value.hunger.toString()) - detail.put("growth",it.value.growth.toString()) - petDetails.add(detail) + val petId = it.key + val petData = JSONArray() + for (v in it.value) { + val pet = JSONObject() + pet.put("hunger",v.hunger.toString()) + pet.put("growth",v.growth.toString()) + petData.add(pet) + } + petDetails.put(petId.toString(), petData) } familiarManager.put("petDetails",petDetails) if(player.familiarManager.hasPet()){ - familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).getItemIdHash().toString()) + familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).getItemId().toString()) } else if (player.familiarManager.hasFamiliar()){ val familiar = JSONObject() familiar.put("originalId",player.familiarManager.familiar.originalId.toString()) diff --git a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt index 69de55908..4338de79f 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt @@ -1,25 +1,22 @@ package core.game.node.entity.player.info.login +import content.global.skill.summoning.pet.Pets import core.ServerConstants import core.api.* import core.game.node.entity.player.Player import core.game.node.item.Item import org.rs09.consts.Items - /** * Runs one-time save-version-related hooks. * @author Player Name */ class SaveVersionHooks : LoginListener { - override fun login(player: Player) { if (player.version < ServerConstants.CURRENT_SAVEFILE_VERSION) { - sendMessage(player, "Migrating save file version ${player.version} to current save file version ${ServerConstants.CURRENT_SAVEFILE_VERSION}.") - // Perform actual migrations - if (player.version < 1) { // GL #1811 + if (player.version < 1) { // GL !1811 // Give out crafting hoods if the player bought any crafting capes when the hoods were not obtainable var hasHoods = 0 var hasCapes = 0 @@ -60,10 +57,18 @@ class SaveVersionHooks : LoginListener { } } - // Finish up + if (player.version < 2) { //GL !1799 + // Most of the migration for this MR happens in FamiliarManager.java, but we fix up any pet items here + val pets = Pets.values() + for (pet in pets) { + for (id in arrayOf(pet.babyItemId, pet.grownItemId, pet.overgrownItemId)) { + replaceAllItems(player, id, id) + // The trick here is that replaceAllItems ignores the item charge value, and will hence cause it to be lost, making all pets authentically stack again + } + } + } + player.version = ServerConstants.CURRENT_SAVEFILE_VERSION - sendMessage(player, "Save file migration complete. Happy scaping!") } } - } diff --git a/Server/src/main/core/game/node/item/Item.java b/Server/src/main/core/game/node/item/Item.java index f84c7d648..086784cf6 100644 --- a/Server/src/main/core/game/node/item/Item.java +++ b/Server/src/main/core/game/node/item/Item.java @@ -196,14 +196,6 @@ public class Item extends Node{ return idHash; } - /** - * Sets the id hash. - * @param hash the hash to set - */ - public void setIdHash(int hash) { - this.idHash = hash; - } - /** * Checks if the item has a wrapper plugin. * @return {@code True} if so. From 0a89439c801e81d64a18836bb37a1179991be15c Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 10:58:18 +0000 Subject: [PATCH 015/306] Fixed saving of prayer points & hitpoints, dynamic level is now tracked separately to current hit/prayer points --- .../entity/player/info/login/PlayerSaver.kt | 12 ++--- .../core/game/node/entity/skill/Skills.java | 53 ++++++++----------- .../game/node/entity/skill/SkillsTests.kt | 43 +++++++++++++++ 3 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 Server/src/test/kotlin/core/game/node/entity/skill/SkillsTests.kt diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 4f1f176b4..7d5318921 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -566,12 +566,12 @@ class PlayerSaver (val player: Player){ val skill = JSONObject() skill.put("id",i.toString()) skill.put("static",player.skills.staticLevels[i].toString()) - if(i == Skills.HITPOINTS){ - skill.put("dynamic",player.skills.lifepoints.toString()) - } else if (i == Skills.PRAYER){ - skill.put("dynamic",ceil(player.skills.prayerPoints).toInt().toString()) - } else { - skill.put("dynamic",player.skills.dynamicLevels[i].toString()) + skill.put("dynamic",player.skills.dynamicLevels[i].toString()) + if (i == Skills.HITPOINTS) { + skill.put("lifepoints",player.skills.lifepoints.toString()) + } + if (i == Skills.PRAYER) { + skill.put("prayerPoints",player.skills.prayerPoints.toString()) } skill.put("experience",player.skills.getExperience(i).toString()) skills.add(skill) diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index f646c104b..9f550245a 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -1,6 +1,7 @@ package core.game.node.entity.skill; import content.global.skill.skillcapeperks.SkillcapePerks; +import core.ServerConstants; import core.game.event.DynamicSkillLevelChangeEvent; import core.game.event.XPGainEvent; import content.global.handlers.item.equipment.brawling_gloves.BrawlingGloves; @@ -369,36 +370,30 @@ public final class Skills { rechargePrayerPoints(); } - /** - * Parses the skill data from the buffer. - * @param buffer The byte buffer. - */ - public void parse(ByteBuffer buffer) { - for (int i = 0; i < 24; i++) { - experience[i] = ((double) buffer.getInt() / 10D); - dynamicLevels[i] = buffer.get() & 0xFF; - if (i == HITPOINTS) { - lifepoints = dynamicLevels[i]; - } else if (i == PRAYER) { - prayerPoints = dynamicLevels[i]; - } - staticLevels[i] = buffer.get() & 0xFF; - } - experienceGained = buffer.getInt(); - } - public void parse(JSONArray skillData){ for(int i = 0; i < skillData.size(); i++){ JSONObject skill = (JSONObject) skillData.get(i); int id = Integer.parseInt( skill.get("id").toString()); - dynamicLevels[id] = Integer.parseInt( skill.get("dynamic").toString()); - if (id == HITPOINTS) { - lifepoints = dynamicLevels[i]; - } else if (id == PRAYER) { - prayerPoints = dynamicLevels[i]; - } - staticLevels[id] = Integer.parseInt( skill.get("static").toString()); + dynamicLevels[id] = Integer.parseInt(skill.get("dynamic").toString()); + staticLevels[id] = Integer.parseInt(skill.get("static").toString()); experience[id] = Double.parseDouble(skill.get("experience").toString()); + int version = entity instanceof Player ? entity.asPlayer().version : ServerConstants.CURRENT_SAVEFILE_VERSION; + if (i == HITPOINTS) { + if (version < 3 && !skill.containsKey("lifepoints")) { //!1881 + lifepoints = dynamicLevels[id]; + dynamicLevels[id] = staticLevels[id]; + } else { + lifepoints = Integer.parseInt(skill.get("lifepoints").toString()); + } + } + if (i == PRAYER) { + if (version < 3 && !skill.containsKey("prayerPoints")) { //!1881 + prayerPoints = dynamicLevels[id]; + dynamicLevels[id] = staticLevels[id]; + } else { + prayerPoints = Double.parseDouble(skill.get("prayerPoints").toString()); + } + } } } @@ -432,13 +427,7 @@ public final class Skills { public void save(ByteBuffer buffer) { for (int i = 0; i < 24; i++) { buffer.putInt((int) (experience[i] * 10)); - if (i == HITPOINTS) { - buffer.put((byte) lifepoints); - } else if (i == PRAYER) { - buffer.put((byte) Math.ceil(prayerPoints)); - } else { - buffer.put((byte) dynamicLevels[i]); - } + buffer.put((byte) dynamicLevels[i]); buffer.put((byte) staticLevels[i]); } buffer.putInt((int) experienceGained); diff --git a/Server/src/test/kotlin/core/game/node/entity/skill/SkillsTests.kt b/Server/src/test/kotlin/core/game/node/entity/skill/SkillsTests.kt new file mode 100644 index 000000000..22c9dcffb --- /dev/null +++ b/Server/src/test/kotlin/core/game/node/entity/skill/SkillsTests.kt @@ -0,0 +1,43 @@ +package core.game.node.entity.skill + +import TestUtils.getMockPlayer +import core.game.node.entity.player.info.login.PlayerSaveParser +import core.game.node.entity.player.info.login.PlayerSaver +import org.json.simple.JSONArray +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +class SkillsTests { + init { + TestUtils.preTestSetup() + } + + @Test + fun saveDynamicLevelsTest() { + val player = getMockPlayer("") + + // Test migration of old save versions with incorrectly-saved dynamic levels + val jsonparser = JSONParser() + val json = jsonparser.parse("[{\"static\":\"55\",\"dynamic\":\"55\",\"id\":\"0\",\"experience\":\"177895.0\"},{\"static\":\"21\",\"dynamic\":\"21\",\"id\":\"1\",\"experience\":\"5120.0\"},{\"static\":\"23\",\"dynamic\":\"23\",\"id\":\"2\",\"experience\":\"6682.799999999999\"},{\"static\":\"26\",\"dynamic\":\"20\",\"id\":\"3\",\"experience\":\"9001.000000000002\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"4\",\"experience\":\"0.0\"},{\"static\":\"23\",\"dynamic\":\"20\",\"id\":\"5\",\"experience\":\"6772.5\"},{\"static\":\"37\",\"dynamic\":\"37\",\"id\":\"6\",\"experience\":\"28180.0\"},{\"static\":\"54\",\"dynamic\":\"54\",\"id\":\"7\",\"experience\":\"164425.0\"},{\"static\":\"40\",\"dynamic\":\"40\",\"id\":\"8\",\"experience\":\"40975.5\"},{\"static\":\"24\",\"dynamic\":\"24\",\"id\":\"9\",\"experience\":\"7260.0\"},{\"static\":\"40\",\"dynamic\":\"40\",\"id\":\"10\",\"experience\":\"40200.0\"},{\"static\":\"35\",\"dynamic\":\"35\",\"id\":\"11\",\"experience\":\"23750.0\"},{\"static\":\"60\",\"dynamic\":\"60\",\"id\":\"12\",\"experience\":\"292409.0\"},{\"static\":\"11\",\"dynamic\":\"11\",\"id\":\"13\",\"experience\":\"1371.5\"},{\"static\":\"75\",\"dynamic\":\"75\",\"id\":\"14\",\"experience\":\"1254300.0\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"15\",\"experience\":\"0.0\"},{\"static\":\"42\",\"dynamic\":\"42\",\"id\":\"16\",\"experience\":\"47742.5\"},{\"static\":\"10\",\"dynamic\":\"10\",\"id\":\"17\",\"experience\":\"1160.0\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"18\",\"experience\":\"0.0\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"19\",\"experience\":\"0.0\"},{\"static\":\"5\",\"dynamic\":\"5\",\"id\":\"20\",\"experience\":\"500.0\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"21\",\"experience\":\"0.0\"},{\"static\":\"1\",\"dynamic\":\"1\",\"id\":\"22\",\"experience\":\"0.0\"},{\"static\":\"11\",\"dynamic\":\"11\",\"id\":\"23\",\"experience\":\"1429.0\"}]") as JSONArray + player.version = 1 + player.skills.parse(json) + Assertions.assertTrue(player.skills.prayerPoints == 20.0) + Assertions.assertTrue(player.skills.lifepoints == 20) + Assertions.assertTrue(player.skills.dynamicLevels[Skills.PRAYER] == 23) + Assertions.assertTrue(player.skills.dynamicLevels[Skills.HITPOINTS] == 26) + + // Test that serializing and parsing them again correctly updates the dynamic levels and keeps the hp/prayer points + player.version = 2 + val root = JSONObject() + PlayerSaver(player).saveSkills(root) + val saveparser = PlayerSaveParser(player) + saveparser.saveFile = root + saveparser.parseSkills() + Assertions.assertTrue(player.skills.prayerPoints == 20.0) + Assertions.assertTrue(player.skills.lifepoints == 20) + Assertions.assertTrue(player.skills.dynamicLevels[Skills.PRAYER] == 23) + Assertions.assertTrue(player.skills.dynamicLevels[Skills.HITPOINTS] == 26) + } +} From 4799176c14f7d8a542ecfdc1e0034e28e2617b32 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 11:03:33 +0000 Subject: [PATCH 016/306] Fix bugs with familiars Fixed a bug where familiars would sometimes not respond to the 'Call' button Fixed random events not spawning when standing in front of the Lumbridge furnace Fixed incorrect restrictions on familiars and random events inside POHs --- .../global/skill/construction/HouseZone.java | 2 +- .../main/core/game/world/map/RegionManager.kt | 36 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index dd0075f23..7157912ae 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -37,7 +37,7 @@ public final class HouseZone extends MapZone { * Constructs the house zone object. */ public HouseZone(HouseManager house) { - super("poh-zone" + house, true, ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.FOLLOWERS); + super("poh-zone" + house, true); this.house = house; } diff --git a/Server/src/main/core/game/world/map/RegionManager.kt b/Server/src/main/core/game/world/map/RegionManager.kt index 91ccf4f25..46022fd01 100644 --- a/Server/src/main/core/game/world/map/RegionManager.kt +++ b/Server/src/main/core/game/world/map/RegionManager.kt @@ -312,23 +312,37 @@ object RegionManager { if (owner == null || node == null) { return null } - var destination: Location? = null outer@ for (i in 0..7) { val dir = Direction.get(i) - inner@for(j in 0 until node.size()) { - val l = owner.location.transform(dir, j) - for (x in 0 until node.size()) { - for (y in 0 until node.size()) { - if (isClipped(l.transform(x, y, 0))) { - continue@inner - } + var stepX = dir.stepX + var stepY = dir.stepY + // For objects that are larger than 1, the below corrects for the fact that their origin is on the SW tile + if (dir.stepX < 0) { + stepX -= (node.size() - 1) + } + if (dir.stepY < 0) { + stepY -= (node.size() - 1) + } + if (owner.size() > 1) { //e.g. if you used ::pnpc to morph yourself into a large NPC + if (dir.stepX > 0) { + stepX += (owner.size() - 1) + } + if (dir.stepY > 0) { + stepY += (owner.size() - 1) + } + } + val l = owner.location.transform(stepX, stepY, 0) + // Check if ALL target tiles are unclipped + for (x in 0 until node.size()) { + for (y in 0 until node.size()) { + if (isClipped(l.transform(x, y, 0))) { + continue@outer } } - destination = l - break@outer } + return l } - return destination + return null } /** From b2f7f86d6a2632de2333c4a0ea8867e796846308 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 11:14:56 +0000 Subject: [PATCH 017/306] Fixed blessing of graves belonging to ironmen Fixed POH teleport issue Fixed charter requirements Fixed entrana weapon check bypass Small authenticity improvements --- .../ame/events/drilldemon/DrillDemonUtils.kt | 4 +- .../global/ame/events/evilbob/EvilBobUtils.kt | 5 +- .../ame/events/freakyforester/FreakUtils.kt | 4 +- .../events/supriseexam/SurpriseExamUtils.kt | 6 +-- .../skill/construction/HouseManager.java | 2 + .../global/skill/runecrafting/Altar.java | 2 +- .../global/travel/ship/ShipCharter.java | 46 ++++++++++++++----- .../minigame/vinesweeper/Vinesweeper.kt | 8 +++- .../entity/combat/graves/GraveController.kt | 9 +++- 9 files changed, 63 insertions(+), 23 deletions(-) diff --git a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt index d81f3ed51..105b14fc2 100644 --- a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt +++ b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt @@ -23,7 +23,9 @@ object DrillDemonUtils { val DD_NPC = NPCs.SERGEANT_DAMIEN_2790 fun teleport(player: Player) { - setAttribute(player, DD_KEY_RETURN_LOC, player.location) + if (getAttribute(player, DD_KEY_RETURN_LOC, null) == null) { + setAttribute(player, DD_KEY_RETURN_LOC, player.location) + } teleport(player, Location.create(3163, 4819, 0)) player.interfaceManager.closeDefaultTabs() setComponentVisibility(player, 548, 69, true) diff --git a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt index e07703ab9..a74835f33 100644 --- a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt +++ b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt @@ -16,7 +16,6 @@ object EvilBobUtils { const val prevLocation = "/save:original-loc" const val eventComplete = "/save:evilbob:eventcomplete" const val assignedFishingZone = "/save:evilbob:fishingzone" - const val fishCaught = "evilbob:fishcaught" const val attentive = "/save:evilbob:attentive" const val servantHelpDialogueSeen = "/save:evilbob:servantdialogeseen" const val attentiveNewSpot = "/save:evilbob:attentivenewspot" @@ -53,7 +52,9 @@ object EvilBobUtils { } fun teleport(player: Player) { - setAttribute(player, prevLocation, player.location) + if (getAttribute(player, prevLocation, null) == null) { + setAttribute(player, prevLocation, player.location) + } player.properties.teleportLocation = Location.create(3419, 4776, 0) } diff --git a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt index c08701297..c49d155d7 100644 --- a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt +++ b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt @@ -27,7 +27,9 @@ object FreakUtils{ } fun teleport(player: Player) { - setAttribute(player, freakPreviousLoc, player.location) + if (getAttribute(player, freakPreviousLoc,null) == null) { + setAttribute(player, freakPreviousLoc, player.location) + } teleport(player, Location.create(2599, 4777 ,0)) } diff --git a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt b/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt index ca0d405f6..f3b5f10b9 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt +++ b/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt @@ -30,12 +30,12 @@ object SurpriseExamUtils { ) fun teleport(player: Player){ - player.setAttribute(SE_KEY_LOC,player.location) - + if (getAttribute(player, SE_KEY_LOC, null) == null) { + player.setAttribute(SE_KEY_LOC, player.location) + } registerLogoutListener(player, SE_LOGOUT_KEY){p -> p.location = getAttribute(p, SE_KEY_LOC, ServerConstants.HOME_LOCATION) } - player.properties.teleportLocation = Location.create(1886, 5025, 0) } diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 8afd8dcff..fd4968171 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -188,6 +188,7 @@ public final class HouseManager { construct(); } player.setAttribute("poh_entry", HouseManager.this); + player.setAttribute("/save:original-loc", location.getExitLocation()); player.lock(1); player.debug("House location: " + houseRegion.getBaseLocation() + ", entry: " + getEnterLocation()); } @@ -267,6 +268,7 @@ public final class HouseManager { if (house.isInHouse(player)) { player.animate(Animation.RESET); player.getProperties().setTeleportLocation(house.location.getExitLocation()); + removeAttribute(player, "original-loc"); } } diff --git a/Server/src/main/content/global/skill/runecrafting/Altar.java b/Server/src/main/content/global/skill/runecrafting/Altar.java index 29cc03953..8be433efc 100644 --- a/Server/src/main/content/global/skill/runecrafting/Altar.java +++ b/Server/src/main/content/global/skill/runecrafting/Altar.java @@ -85,7 +85,7 @@ public enum Altar { } if (this == LAW) { if (!ItemDefinition.canEnterEntrana(player)) { - player.sendMessage("You can't take weapons and armour into the law rift."); + player.sendMessage("The power of Saradomin prevents you from taking armour or weaponry to Entrana."); return; } } diff --git a/Server/src/main/content/global/travel/ship/ShipCharter.java b/Server/src/main/content/global/travel/ship/ShipCharter.java index 99121e375..5d275f6a9 100644 --- a/Server/src/main/content/global/travel/ship/ShipCharter.java +++ b/Server/src/main/content/global/travel/ship/ShipCharter.java @@ -84,7 +84,10 @@ public final class ShipCharter { */ public static int getCost(final Player player, Destination destination) { int cost = destination.getCost(player, destination); - if (player.getEquipment().containsItem(RING_OF_CHAROS)) {// TODO: cabin fever quest + if (player.getQuestRepository().isComplete("Cabin Fever")) { + cost -= Math.round((cost / 2.)); + } + if (player.getEquipment().containsItem(RING_OF_CHAROS)) { cost -= Math.round((cost / 2.)); } return cost; @@ -96,12 +99,10 @@ public final class ShipCharter { * @return the hidden childs. */ public static int[] getHiddenComponents(final Player player, Destination base) { - final Destination[] restrictions = new Destination[] { /** - * - * Destination.MOS_LE_HARMLESS, - */ - Destination.OO_GLOG, Destination.SHIPYARD, /* Destination.PORT_TYRAS, */ - Destination.CRANDOR }; + final Destination[] restrictions = new Destination[] { /* Destination.MOS_LE_HARMLESS, */ + Destination.OO_GLOG, Destination.SHIPYARD, /* Destination.PORT_TYRAS, */ + Destination.CRANDOR + }; List childs = new ArrayList<>(20); for (Destination destination : restrictions) { childs.add(destination.getXChild()); @@ -141,10 +142,15 @@ public final class ShipCharter { PORT_PHASMATYS(Location.create(3705, 3503, 1), 24, new int[] { 3650, 3250, 1850, 0, 0, 0, 2050, 1850, 3200, 1100 }, Location.create(3702, 3502, 0), 2, 13) { @Override public boolean checkTravel(Player player) { - return requireQuest(player, "Priest in Peril", "to go there"); + return requireQuest(player, "Priest in Peril", "to go there."); + } + }, + CRANDOR(Location.create(2792, 3417, 1), 32, new int[] { 0, 480, 480, 925, 400, 3650, 1600, 400, 3200, 3800 }, null, 10, 21) { + @Override + public boolean checkTravel(Player player) { + return requireQuest(player, "Dragon Slayer", "to go there."); } }, - CRANDOR(new Location(2792, 3417, 1), 32, new int[] { 0, 480, 480, 925, 400, 3650, 1600, 400, 3200, 3800 }, null, 10, 21), BRIMHAVEN(Location.create(2763, 3238, 1), 28, new int[] { 0, 480, 480, 925, 400, 3650, 1600, 400, 3200, 3800 }, Location.create(2760, 3238, 0), 6, 17){ @Override public int getCost(Player player, Destination destination) { @@ -161,7 +167,13 @@ public final class ShipCharter { return super.getCost(player, destination); } }, - PORT_TYRAS(Location.create(2142, 3122, 0), 23, new int[] { 3200, 3200, 3200, 1600, 3200, 3200, 3200, 3200, 0, 3200 }, Location.create(2143, 3122, 0), 1, 12), + PORT_TYRAS(Location.create(2142, 3122, 0), 23, new int[] { 3200, 3200, 3200, 1600, 3200, 3200, 3200, 3200, 0, 3200 }, Location.create(2143, 3122, 0), 1, 12) { + @Override + public boolean checkTravel(Player player) { + return hasRequirement(player, "Regicide"); + } + + }, KARAMJA(Location.create(2957, 3158, 1), 27, new int[] { 200, 480, 0, 225, 400, 1850, 0, 200, 3200, 2000 }, Location.create(2954, 3156, 0), 5, 16) { @Override public int getCost(Player player, Destination destination) { @@ -178,9 +190,19 @@ public final class ShipCharter { return super.getCost(player, destination); } }, - SHIPYARD(Location.create(3001, 3032, 0), 26, new int[] { 400, 1600, 200, 225, 720, 1850, 400, 0, 3200, 900 }, Location.create(3001, 3032, 0), 4, 15), + SHIPYARD(Location.create(3001, 3032, 0), 26, new int[] { 400, 1600, 200, 225, 720, 1850, 400, 0, 3200, 900 }, Location.create(3001, 3032, 0), 4, 15) { + @Override + public boolean checkTravel(Player player) { + return requireQuest(player, "The Grand Tree", "to go there."); + } + }, OO_GLOG(Location.create(2623, 2857, 0), 33, new int[] { 300, 3400, 2000, 550, 5000, 2800, 1400, 900, 3200, 0}, Location.create(2622, 2857, 0), 11, 22), - MOS_LE_HARMLESS(Location.create(3671, 2931, 0), 31, new int[] { 725, 625, 1025, 0, 1025, 0, 325, 275, 1600, 500 }, Location.create(3671, 2933, 0), 9, 20); + MOS_LE_HARMLESS(Location.create(3671, 2931, 0), 31, new int[] { 725, 625, 1025, 0, 1025, 0, 325, 275, 1600, 500 }, Location.create(3671, 2933, 0), 9, 20) { + @Override + public boolean checkTravel(Player player) { + return hasRequirement(player, "Cabin Fever"); + } + }; /** * Constructs a new {@code ShipCharter} {@code Object}. diff --git a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt index 031d86d02..cce206947 100644 --- a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt +++ b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt @@ -34,6 +34,7 @@ import content.minigame.vinesweeper.Vinesweeper.Companion.SEED_LOCS import content.minigame.vinesweeper.Vinesweeper.Companion.populateSeeds import content.minigame.vinesweeper.Vinesweeper.Companion.scheduleNPCs import content.minigame.vinesweeper.Vinesweeper.Companion.sendPoints +import core.cache.def.impl.ItemDefinition import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.interaction.InterfaceListener @@ -83,7 +84,12 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { on(Sceneries.PORTAL_29534, IntType.SCENERY, "enter") { player, _ -> val x = player.getAttribute("vinesweeper:return-tele:x", 3052) val y = player.getAttribute("vinesweeper:return-tele:y", 3304) - teleport(player, Location(x, y)) + val loc = Location(x, y) + if (ZoneBorders.forRegion(11060).insideBorder(loc) && !ItemDefinition.canEnterEntrana(player)) { + sendMessage(player, "The power of Saradomin prevents you from taking armour or weaponry to Entrana."); + return@on true + } + teleport(player, loc) return@on true } on(SIGNS, IntType.SCENERY, "read") { player, node -> diff --git a/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt b/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt index 98998d120..cfead670c 100644 --- a/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt +++ b/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt @@ -106,6 +106,12 @@ class GraveController : PersistWorld, TickListener, InteractionListener, Command return true } + val gOwner = Repository.uid_map[g.ownerUid] + if (gOwner != null && gOwner.ironmanManager.isIronman) { + sendMessage(player, "This grave belongs to an Ironman.") + return true + } + if (getStatLevel(player, Skills.PRAYER) < 70) { sendMessage(player, "You need a Prayer level of 70 to bless a grave.") return true @@ -125,7 +131,6 @@ class GraveController : PersistWorld, TickListener, InteractionListener, Command playAudio(player, Sounds.PRAYER_RECHARGE_2674) animate(player, 645) - val gOwner = Repository.uid_map[g.ownerUid] if (gOwner != null) { sendMessage(gOwner, colorize("%RYour grave has been blessed.")) } @@ -290,4 +295,4 @@ class GraveController : PersistWorld, TickListener, InteractionListener, Command } } } -} \ No newline at end of file +} From 9f61ffb1533fdef1903fc7e1ee2cc0463e98d352 Mon Sep 17 00:00:00 2001 From: Doggo Date: Sun, 6 Oct 2024 12:23:24 +0000 Subject: [PATCH 018/306] Rewrote the swing/attack handler for authenticity: Fixed a lot of off-by-1 miscalculations Fixed the void ranger bonus, which should be 20% Fixed granite maul spec not giving xp and ignoring protection prayers Fixed accuracy being too high Fixed set bonuses that boost attack or defence being applied twice or to all attacks Fixed ranged attacks not taking into account prayers that boost defence or defensive attack styles Fixed red chinchompa having the same damage as normal chinchompas Fixed some specs being boosted by offensive prayers ::calcmaxhit now has better formatting ::calc_accuracy renamed to ::calcaccuracy for consistency with other commands, and now also gives the actual hit chance --- .../special/AncientMaceSpecialHandler.java | 2 +- .../special/BackstabSpecialHandler.java | 11 +- .../special/ChainhitSpecialHandler.java | 14 +- .../special/ChinchompaSwingHandler.java | 9 +- .../special/CleaveSpecialHandler.java | 4 +- .../DescentOfDarknessSpecialHandler.java | 6 +- .../special/EnergyDrainSpecialHandler.java | 4 +- .../special/FeintSpecialHandler.java | 5 +- .../special/HamstringSpecialHandler.java | 3 +- .../special/HealingBladeSpecialHandler.java | 24 ++-- .../special/IceCleaveSpecialHandler.java | 4 +- .../special/ImpaleSpecialHandler.java | 2 +- .../special/JudgementSpecialHandler.java | 4 +- .../special/PhantomStrikeSpecialHandler.java | 2 +- .../special/PowershotSpecialHandler.java | 5 +- .../special/PowerstabSpecialHandler.java | 2 +- .../special/PunctureSpecialHandler.java | 13 +- .../special/QuickSmashSpecialHandler.java | 14 +- .../special/RampageSpecialHandler.java | 14 +- .../special/SaradominsLightningHandler.java | 6 +- .../special/SeercullSpecialHandler.java | 14 +- .../special/SeverSpecialHandler.java | 4 +- .../special/ShatterSpecialHandler.java | 4 +- .../special/SliceAndDiceSpecialHandler.java | 25 ++-- .../special/SmashSpecialHandler.java | 3 +- .../special/SnapshotSpecialHandler.java | 16 ++- .../special/SnipeSpecialHandler.java | 7 +- .../special/SpearWallSpecialHandler.java | 2 +- .../special/SweepSpecialHandler.java | 8 +- .../special/WarstrikeSpecialHandler.java | 10 +- .../special/WeakenSpecialHandler.java | 21 +-- .../skill/slayer/SlayerEquipmentFlags.kt | 2 +- .../container/impl/EquipmentContainer.java | 3 - .../node/entity/combat/CombatSwingHandler.kt | 17 +-- .../node/entity/combat/MagicSwingHandler.kt | 80 +++++++---- .../node/entity/combat/MeleeSwingHandler.kt | 136 ++++++++++-------- .../node/entity/combat/RangeSwingHandler.kt | 106 +++++++++----- .../entity/combat/equipment/ArmourSet.java | 8 +- .../system/command/sets/MiscCommandSet.kt | 16 ++- Server/src/test/kotlin/content/CombatTests.kt | 15 +- 40 files changed, 369 insertions(+), 276 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/equipment/special/AncientMaceSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/AncientMaceSpecialHandler.java index 330523540..9c04d990f 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/AncientMaceSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/AncientMaceSpecialHandler.java @@ -57,7 +57,7 @@ public final class AncientMaceSpecialHandler extends MeleeSwingHandler implement state.setStyle(CombatStyle.MELEE); int hit = 0; if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.1, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1)); + hit = RandomFunction.random(calculateHit(entity, victim, 1) + 1); if (entity.getSkills().getPrayerPoints() < entity.getSkills().getStaticLevel(5)) { entity.getSkills().setPrayerPoints(entity.getSkills().getPrayerPoints() + hit); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/BackstabSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/BackstabSpecialHandler.java index bb243ad37..2baaab97e 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/BackstabSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/BackstabSpecialHandler.java @@ -59,13 +59,10 @@ public final class BackstabSpecialHandler extends MeleeSwingHandler implements P } state.setStyle(CombatStyle.MELEE); int hit = 0; - double accuracy = 1.0; - if (!victim.getProperties().getCombatPulse().isAttacking()) { - accuracy = 1.75; - } - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, accuracy, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); - victim.getSkills().updateLevel(Skills.DEFENCE, -hit / 10, 0); + if (!victim.getProperties().getCombatPulse().isAttacking() || isAccurateImpact(entity, victim, CombatStyle.MELEE)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); + if (victim.getSkills().getStaticLevel(Skills.DEFENCE) >= victim.getSkills().getDynamicLevels()[Skills.DEFENCE]) + victim.getSkills().updateLevel(Skills.DEFENCE, -hit, 0); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java index a4682149f..b3e276dcd 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java @@ -1,9 +1,7 @@ package content.global.handlers.item.equipment.special; import core.game.node.entity.Entity; -import core.game.node.entity.combat.BattleState; -import core.game.node.entity.combat.CombatStyle; -import core.game.node.entity.combat.DeathTask; +import core.game.node.entity.combat.*; import core.game.node.entity.combat.ImpactHandler.HitsplatType; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.impl.Projectile; @@ -17,7 +15,6 @@ import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; import core.plugin.Plugin; import core.tools.RandomFunction; -import core.game.node.entity.combat.RangeSwingHandler; import core.game.world.GameWorld; import core.game.world.repository.Repository; import org.rs09.consts.Sounds; @@ -34,6 +31,13 @@ import static core.api.ContentAPIKt.playGlobalAudio; @Initializable public final class ChainhitSpecialHandler extends RangeSwingHandler implements Plugin { + /** + * Constructs a new {@code ChainhitSpecialHandler} {@code Object}. + */ + public ChainhitSpecialHandler() { + super(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE); + } + /** * The sp::ecial energy required. */ @@ -159,7 +163,7 @@ public final class ChainhitSpecialHandler extends RangeSwingHandler implements P public boolean pulse() { BattleState bs = new BattleState(entity, e); bs.setMaximumHit(calculateHit(player, e, 1.0)); - bs.setEstimatedHit(RandomFunction.RANDOM.nextInt(bs.getMaximumHit())); + bs.setEstimatedHit(RandomFunction.random(bs.getMaximumHit() + 1)); handleHit(victim, e, player, bs); ChainhitSpecialHandler.super.visualizeImpact(player, e, bs); return true; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java index fea739a85..0bd2e6d33 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java @@ -31,13 +31,6 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler { */ private static final Graphics END_GRAPHIC = new Graphics(157, 96); - /** - * Constructs a new {@code ChinchompaSwingHandler} {@code Object}. - */ - public ChinchompaSwingHandler() { - super(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE); - } - @Override public int swing(Entity entity, Entity victim, BattleState state) { boolean multi = entity.getProperties().isMultiZone() && victim.getProperties().isMultiZone(); @@ -72,7 +65,7 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler { s.setStyle(CombatStyle.RANGE); int hit = 0; if (isAccurateImpact(entity, e, CombatStyle.RANGE)) { - hit = RandomFunction.random(calculateHit(entity, e, 1.0)); + hit = RandomFunction.random(calculateHit(entity, e, 1.0) + 1); } s.setEstimatedHit(hit); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/CleaveSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/CleaveSpecialHandler.java index dd669c168..f728dbaf2 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/CleaveSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/CleaveSpecialHandler.java @@ -57,8 +57,8 @@ public final class CleaveSpecialHandler extends MeleeSwingHandler implements Plu } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.18, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.2203)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.25) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/DescentOfDarknessSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/DescentOfDarknessSpecialHandler.java index 519f9462a..75ae1f8a8 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/DescentOfDarknessSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/DescentOfDarknessSpecialHandler.java @@ -30,7 +30,7 @@ public final class DescentOfDarknessSpecialHandler extends RangeSwingHandler imp /** * The special energy required. */ - private static final int SPECIAL_ENERGY = 65; + private static final int SPECIAL_ENERGY = 55; /** * The descent of dragons projectile. @@ -102,13 +102,13 @@ public final class DescentOfDarknessSpecialHandler extends RangeSwingHandler imp state.setMaximumHit(max); int hit = minDamage; if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.15, 1.0)) { - hit += RandomFunction.random(max - minDamage); + hit += RandomFunction.random(max - minDamage + 1); } state.setEstimatedHit(hit); if (w.getType() == WeaponType.DOUBLE_SHOT) { hit = minDamage; if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.15, 1.0)) { - hit += RandomFunction.random(max - minDamage); + hit += RandomFunction.random(max - minDamage + 1); } state.setSecondaryHit(hit); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/EnergyDrainSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/EnergyDrainSpecialHandler.java index c7b6dec41..4686eb2b8 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/EnergyDrainSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/EnergyDrainSpecialHandler.java @@ -57,8 +57,8 @@ public final class EnergyDrainSpecialHandler extends MeleeSwingHandler implement } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.2, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1) + 1); } if (victim instanceof Player) { ((Player) victim).getSettings().updateRunEnergy(10); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/FeintSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/FeintSpecialHandler.java index a22ba8c10..b85962790 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/FeintSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/FeintSpecialHandler.java @@ -52,8 +52,9 @@ public final class FeintSpecialHandler extends MeleeSwingHandler implements Plug } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, RandomFunction.random(1.0, 1.2))); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 0.25)) { + int minDamage = calculateHit(entity, victim, 0.2); + hit = minDamage + RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java index fefffaabd..6a89af4fc 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/HamstringSpecialHandler.java @@ -46,7 +46,8 @@ public final class HamstringSpecialHandler extends RangeSwingHandler implements state.setMaximumHit(max); int hit = 0; if (isAccurateImpact(entity, victim)) { - hit = RandomFunction.random(max); + int minDamage = calculateHit(entity, victim, 0.2); + hit = minDamage + RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); } state.setEstimatedHit(hit); Companion.useAmmo(entity, state, victim.getLocation()); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/HealingBladeSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/HealingBladeSpecialHandler.java index 76780908b..5589c48c0 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/HealingBladeSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/HealingBladeSpecialHandler.java @@ -57,20 +57,20 @@ public final class HealingBladeSpecialHandler extends MeleeSwingHandler implemen } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.12, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.005)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1); + int healthRestore = hit / 2; + double prayerRestore = hit * 0.25; + if (healthRestore < 10) { + healthRestore = 10; + } + if (prayerRestore < 5) { + prayerRestore = 5; + } + entity.getSkills().heal(healthRestore); + entity.getSkills().incrementPrayerPoints(prayerRestore); } state.setEstimatedHit(hit); - int healthRestore = hit / 2; - double prayerRestore = hit * 0.25; - if (healthRestore < 10) { - healthRestore = 10; - } - if (prayerRestore < 5) { - prayerRestore = 5; - } - entity.getSkills().heal(healthRestore); - entity.getSkills().incrementPrayerPoints(prayerRestore); return 1; } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/IceCleaveSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/IceCleaveSpecialHandler.java index 42053679b..83c1e4a50 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/IceCleaveSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/IceCleaveSpecialHandler.java @@ -57,8 +57,8 @@ public final class IceCleaveSpecialHandler extends MeleeSwingHandler implements } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.075, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.005)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ImpaleSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ImpaleSpecialHandler.java index 11ddbd9f9..2e0ff5aa4 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ImpaleSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ImpaleSpecialHandler.java @@ -59,7 +59,7 @@ public final class ImpaleSpecialHandler extends MeleeSwingHandler implements Plu state.setStyle(CombatStyle.MELEE); int hit = 0; if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.1, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.1)); + hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/JudgementSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/JudgementSpecialHandler.java index 0fb647924..abdb00cc5 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/JudgementSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/JudgementSpecialHandler.java @@ -57,8 +57,8 @@ public final class JudgementSpecialHandler extends MeleeSwingHandler implements } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.25)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) { + hit = RandomFunction.random((int) (calculateHit(entity, victim, 1.1) * 1.25) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java index 18af20d24..82f5b3eb3 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/PhantomStrikeSpecialHandler.java @@ -49,7 +49,7 @@ public final class PhantomStrikeSpecialHandler extends RangeSwingHandler impleme state.setMaximumHit(max); int hit = 0; if (isAccurateImpact(entity, victim)) { - hit = RandomFunction.random(max); + hit = RandomFunction.random(max + 1); } state.setEstimatedHit(hit); Companion.useAmmo(entity, state, victim.getLocation()); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PowershotSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PowershotSpecialHandler.java index aca1a0070..4fe5e5f90 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/PowershotSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/PowershotSpecialHandler.java @@ -56,10 +56,7 @@ public final class PowershotSpecialHandler extends RangeSwingHandler implements return -1; } state.setStyle(CombatStyle.RANGE); - int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.98, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); - } + int hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); state.setEstimatedHit(hit); Companion.useAmmo(entity, state, victim.getLocation()); return 1 + (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java index 4c7ea7a83..172ca036c 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java @@ -85,7 +85,7 @@ public final class PowerstabSpecialHandler extends MeleeSwingHandler implements BattleState s = targets[count++] = new BattleState(entity, e); int hit = 0; if (isAccurateImpact(entity, e)) { - hit = RandomFunction.random(calculateHit(entity, e, 1.0)); + hit = RandomFunction.random(calculateHit(entity, e, 1.0) + 1); } s.setStyle(CombatStyle.MELEE); s.setEstimatedHit(hit); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PunctureSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PunctureSpecialHandler.java index e489173fc..b5fc3357f 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/PunctureSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/PunctureSpecialHandler.java @@ -61,18 +61,13 @@ public final class PunctureSpecialHandler extends MeleeSwingHandler implements P return -1; } state.setStyle(CombatStyle.MELEE); - // First hit - //double accuracyMod, double defenceMod int hit = 0; - // accuracyMod defenceMod - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.05, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.1306)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.15, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.15) + 1); } state.setEstimatedHit(hit); - // Second hit - // accuracyMod defenceMod - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.05, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.1306)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.15, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.15) + 1); } else { hit = 0; } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/QuickSmashSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/QuickSmashSpecialHandler.java index cc5e5a557..e1d043c9d 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/QuickSmashSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/QuickSmashSpecialHandler.java @@ -3,9 +3,11 @@ package content.global.handlers.item.equipment.special; import core.game.node.entity.Entity; import core.game.node.entity.combat.BattleState; import core.game.node.entity.combat.CombatStyle; +import core.game.node.entity.combat.DeathTask; import core.game.node.entity.combat.MeleeSwingHandler; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.player.Player; +import core.game.node.entity.player.link.prayer.PrayerType; import core.game.world.GameWorld; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; @@ -65,16 +67,22 @@ public final class QuickSmashSpecialHandler extends MeleeSwingHandler implements return -1; } } + if (DeathTask.isDead(victim)) { + return -1; + } if (!p.getSettings().drainSpecial(SPECIAL_ENERGY)) { return -1; } - // TODO: apply protection prayers/experience manually (since this is bypassing normal BattleState machinery) visualize(entity, victim, null); int hit = 0; if (isAccurateImpact(entity, victim)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.)); + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); } - victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MELEE); + if (victim.hasProtectionPrayer(CombatStyle.MELEE)) + hit *= (victim instanceof Player) ? 0.6 : 0; + BattleState b = new BattleState(); + b.setEstimatedHit(victim.getImpactHandler().handleImpact(entity, hit, CombatStyle.MELEE).getAmount()); + addExperience(entity, victim, b); return 1; } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/RampageSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/RampageSpecialHandler.java index 0aef9cd2b..2e70ab9ec 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/RampageSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/RampageSpecialHandler.java @@ -65,15 +65,15 @@ public final class RampageSpecialHandler extends MeleeSwingHandler implements Pl p.visualize(ANIMATION, GRAPHIC); @SuppressWarnings("unused") int boost = 0; - for (int i = 0; i < 6; i++) { - if (i == 2 || i == 3 || i == 5) { - continue; + for (int i = 0; i < 7; i++) { + if (i == Skills.ATTACK || i == Skills.DEFENCE || i == Skills.RANGE || i == Skills.MAGIC) { + int drain = (int) (p.getSkills().getLevel(i) * 0.1); + boost += drain; + p.getSkills().updateLevel(i, -drain, 0); } - double drain = p.getSkills().getLevel(i) * 0.1; - boost += drain; - p.getSkills().updateLevel(i, (int) -drain, (int) (p.getSkills().getStaticLevel(i) - drain)); } - p.getSkills().updateLevel(Skills.STRENGTH, (int) (p.getSkills().getStaticLevel(Skills.STRENGTH) * 0.20)); + boost = 10 + (boost / 4); + p.getSkills().updateLevel(Skills.STRENGTH, boost, Math.max(p.getSkills().getStaticLevel(Skills.STRENGTH) + boost, p.getSkills().getLevel(Skills.STRENGTH))); return -1; } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SaradominsLightningHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SaradominsLightningHandler.java index 3875ba7be..9e672f4db 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SaradominsLightningHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SaradominsLightningHandler.java @@ -52,9 +52,9 @@ public final class SaradominsLightningHandler extends MeleeSwingHandler implemen state.setStyle(CombatStyle.MAGIC); int hit = 0; int secondary = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.10, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.1)); - secondary = 5 + RandomFunction.RANDOM.nextInt(14); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.10, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.1) + 1); + secondary = 1 + RandomFunction.random(16); } state.setEstimatedHit(hit); state.setSecondaryHit(secondary); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SeercullSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SeercullSpecialHandler.java index 5d9bc30ef..b4a374d3e 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SeercullSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SeercullSpecialHandler.java @@ -1,5 +1,6 @@ package content.global.handlers.item.equipment.special; +import core.game.node.entity.combat.SwingHandlerFlag; import core.game.node.entity.skill.Skills; import core.game.node.entity.Entity; import core.game.node.entity.combat.BattleState; @@ -24,6 +25,13 @@ import static core.api.ContentAPIKt.playGlobalAudio; @Initializable public final class SeercullSpecialHandler extends RangeSwingHandler implements Plugin { + /** + * Constructs a new {@code SeercullSpecialHandler} {@code Object}. + */ + public SeercullSpecialHandler() { + super(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE); + } + /** * The special energy required. */ @@ -57,11 +65,9 @@ public final class SeercullSpecialHandler extends RangeSwingHandler implements P if (!((Player) entity).getSettings().drainSpecial(SPECIAL_ENERGY)) { return -1; } - int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.05, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); + int hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); + if (victim.getSkills().getLevel(Skills.MAGIC) >= victim.getSkills().getStaticLevel(Skills.MAGIC)) victim.getSkills().updateLevel(Skills.MAGIC, -hit, 0); - } Companion.useAmmo(entity, state, victim.getLocation()); state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SeverSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SeverSpecialHandler.java index 116e993d4..eb8419c10 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SeverSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SeverSpecialHandler.java @@ -56,8 +56,8 @@ public final class SeverSpecialHandler extends MeleeSwingHandler implements Plug return -1; state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.124, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); if (victim instanceof Player) { Player p = (Player) victim; if (p.getPrayer().get(PrayerType.PROTECT_FROM_MAGIC)) { diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ShatterSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ShatterSpecialHandler.java index aebbd909f..1b226c390 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ShatterSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ShatterSpecialHandler.java @@ -56,8 +56,8 @@ public final class ShatterSpecialHandler extends MeleeSwingHandler implements Pl } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 0.87, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.3546)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.5) + 1); } state.setEstimatedHit(hit); return 1; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SliceAndDiceSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SliceAndDiceSpecialHandler.java index 808cae7a4..9f755280c 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SliceAndDiceSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SliceAndDiceSpecialHandler.java @@ -56,24 +56,25 @@ public final class SliceAndDiceSpecialHandler extends MeleeSwingHandler implemen return -1; } int maximum = calculateHit(entity, victim, 1.0); - int[] hits = new int[] {0, 1}; - int hit = getHit(entity, victim, maximum); + int[] hits; + int hit = getHit(entity, victim, maximum - 1, maximum / 2); if (hit > 0) { - hits = new int[] {hit, hit / 2, (hit / 2) / 2, (hit / 2) - ((hit / 2) / 2)}; + hits = new int[] {hit, hit / 2, (hit / 2) / 2, (hit / 2) / 2 + 1}; } else { - hit = getHit(entity, victim, maximum); + hit = getHit(entity, victim, maximum * 7 / 8, maximum * 3 / 8); if (hit > 0) { - hits = new int[] {0, hit, hit / 2, hit - (hit / 2)}; + hits = new int[] {0, hit, hit / 2, hit / 2 + 1}; } else { - hit = getHit(entity, victim, maximum); + hit = getHit(entity, victim, maximum * 3 / 4, maximum / 4); if (hit > 0) { - hits = new int[] {0, 0, hit / 2, (hit / 2) + 10}; + hits = new int[] {0, 0, hit, hit + 1}; } else { - hit = getHit(entity, victim, (int) (maximum * 1.5)); + hit = getHit(entity, victim, maximum * 5 / 4, maximum / 4); if (hit > 0) { hits = new int[] {0, 0, 0, hit}; } else { - hits = new int[] {0, RandomFunction.random(2)}; + hit = RandomFunction.random(2); + hits = new int[] {0, 0, hit, hit}; } } } @@ -95,9 +96,9 @@ public final class SliceAndDiceSpecialHandler extends MeleeSwingHandler implemen * @param maximum The maximum hit. * @return The hit. */ - private int getHit(Entity entity, Entity victim, int maximum) { - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.25, 0.98)) { - return RandomFunction.random(maximum); + private int getHit(Entity entity, Entity victim, int maximum, int minimum) { + if (isAccurateImpact(entity, victim, CombatStyle.MELEE)) { + return RandomFunction.random(minimum, maximum + 1); } return 0; } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SmashSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SmashSpecialHandler.java index e4137d26c..ba4989eda 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SmashSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SmashSpecialHandler.java @@ -59,7 +59,8 @@ public final class SmashSpecialHandler extends MeleeSwingHandler implements Plug state.setStyle(CombatStyle.MELEE); int hit = 0; if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, RandomFunction.random(1.0, 1.5))); + int max = calculateHit(entity, victim, 1.0); + hit = max / 4 + RandomFunction.random(max + 1); int lower = (int) (victim.getSkills().getLevel(Skills.DEFENCE) * 0.30); victim.getSkills().updateLevel(Skills.DEFENCE, -lower, 0); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SnapshotSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SnapshotSpecialHandler.java index ddd761a21..618a0f4b2 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SnapshotSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SnapshotSpecialHandler.java @@ -3,6 +3,7 @@ package content.global.handlers.item.equipment.special; import core.game.node.entity.Entity; import core.game.node.entity.combat.BattleState; import core.game.node.entity.combat.CombatStyle; +import core.game.node.entity.combat.SwingHandlerFlag; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.impl.Projectile; import core.game.node.entity.player.Player; @@ -25,6 +26,13 @@ import static core.api.ContentAPIKt.playGlobalAudio; @Initializable public final class SnapshotSpecialHandler extends RangeSwingHandler implements Plugin { + /** + * Constructs a new {@code SnapshotSpecialHandler} {@code Object}. + */ + public SnapshotSpecialHandler() { + super(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE); + } + /** * The special energy required. */ @@ -67,13 +75,13 @@ public final class SnapshotSpecialHandler extends RangeSwingHandler implements P int max = calculateHit(entity, victim, 1.0); state.setMaximumHit(max); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 0.9, 1.0)) { - hit = RandomFunction.random(max); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.43, 1.0)) { + hit = RandomFunction.random(max + 1); } state.setEstimatedHit(hit); hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 0.9, 1.0)) { - hit = RandomFunction.random(max); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.43, 1.0)) { + hit = RandomFunction.random(max + 1); } state.setSecondaryHit(hit); Companion.useAmmo(entity, state, victim.getLocation()); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SnipeSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SnipeSpecialHandler.java index b3941ef7c..4d5b66609 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SnipeSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SnipeSpecialHandler.java @@ -60,9 +60,10 @@ public final class SnipeSpecialHandler extends RangeSwingHandler implements Plug } state.setStyle(CombatStyle.RANGE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.RANGE, 1.05, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); - victim.getSkills().updateLevel(Skills.DEFENCE, -hit, 0); + if (!victim.getProperties().getCombatPulse().isAttacking() || isAccurateImpact(entity, victim, CombatStyle.RANGE)) { + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); + if (victim.getSkills().getStaticLevel(Skills.DEFENCE) >= victim.getSkills().getDynamicLevels()[Skills.DEFENCE]) + victim.getSkills().updateLevel(Skills.DEFENCE, -hit, 0); } Companion.useAmmo(entity, state, victim.getLocation()); state.setEstimatedHit(hit); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java index bdbef4ee4..c83d2fd5d 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java @@ -85,7 +85,7 @@ public final class SpearWallSpecialHandler extends MeleeSwingHandler implements if (CombatStyle.RANGE.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT) { BattleState s = targets[count++] = new BattleState(entity, e); int hit = 0; - hit = RandomFunction.random(calculateHit(entity, e, 1.0)); + hit = RandomFunction.random(calculateHit(entity, e, 1.0) + 1); s.setStyle(CombatStyle.MELEE); s.setEstimatedHit(hit); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java index 4b7947736..3ef8ce0f7 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java @@ -66,14 +66,14 @@ public final class SweepSpecialHandler extends MeleeSwingHandler implements Plug for (BattleState s : targets) { s.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, s.getVictim(), CombatStyle.MELEE, 1, 0.94)) { - hit = RandomFunction.random(calculateHit(entity, s.getVictim(), 1.1)); + if (isAccurateImpact(entity, s.getVictim(), CombatStyle.MELEE)) { + hit = RandomFunction.random(calculateHit(entity, s.getVictim(), 1.1) + 1); } s.setEstimatedHit(hit); if (s.getVictim().size() > 1) { hit = 0; - if (isAccurateImpact(entity, s.getVictim(), CombatStyle.MELEE, 1, 0.94)) { - hit = RandomFunction.random(calculateHit(entity, s.getVictim(), 1.1)); + if (isAccurateImpact(entity, s.getVictim(), CombatStyle.MELEE, 0.75, 1.0)) { + hit = RandomFunction.random(calculateHit(entity, s.getVictim(), 1.1) + 1); } s.setSecondaryHit(hit); } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/WarstrikeSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/WarstrikeSpecialHandler.java index 8982b198b..177769d5d 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/WarstrikeSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/WarstrikeSpecialHandler.java @@ -57,8 +57,8 @@ public final class WarstrikeSpecialHandler extends MeleeSwingHandler implements } state.setStyle(CombatStyle.MELEE); int hit = 0; - if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.049, 0.98)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.1)); + if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 2.0, 1.0)) { + hit = RandomFunction.random((int) (calculateHit(entity, victim, 1.1) * 1.1) + 1); } state.setEstimatedHit(hit); if (victim instanceof Player) { @@ -68,10 +68,10 @@ public final class WarstrikeSpecialHandler extends MeleeSwingHandler implements if (left > 0) { left = -victim.getSkills().updateLevel(Skills.STRENGTH, -left, 0); if (left > 0) { - left = -victim.getSkills().updateLevel(Skills.ATTACK, -left, 0); + left = (int) -(victim.getSkills().getPrayerPoints() + left); + victim.getSkills().decrementPrayerPoints(left); if (left > 0) { - left = (int) -(victim.getSkills().getPrayerPoints() + left); - victim.getSkills().decrementPrayerPoints(left); + left = -victim.getSkills().updateLevel(Skills.ATTACK, -left, 0); if (left > 0) { left = -victim.getSkills().updateLevel(Skills.MAGIC, -left, 0); if (left > 0) diff --git a/Server/src/main/content/global/handlers/item/equipment/special/WeakenSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/WeakenSpecialHandler.java index 0fda16c8c..b8f45d90f 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/WeakenSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/WeakenSpecialHandler.java @@ -57,18 +57,19 @@ public final class WeakenSpecialHandler extends MeleeSwingHandler implements Plu state.setStyle(CombatStyle.MELEE); int hit = 0; if (isAccurateImpact(entity, victim, CombatStyle.MELEE, 1.0, 1.0)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)); + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1); + if (victim instanceof Player) { + ((Player) victim).getPacketDispatch().sendMessage("You have been drained."); + } + // TODO 10% drain to demons + int lower = (int) (victim.getSkills().getStaticLevel(Skills.DEFENCE) * 0.05) + 1; + victim.getSkills().updateLevel(Skills.DEFENCE, -lower, 0); + lower = (int) (victim.getSkills().getStaticLevel(Skills.ATTACK) * 0.05) + 1; + victim.getSkills().updateLevel(Skills.ATTACK, -lower, 0); + lower = (int) (victim.getSkills().getStaticLevel(Skills.STRENGTH) * 0.05) + 1; + victim.getSkills().updateLevel(Skills.STRENGTH, -lower, 0); } state.setEstimatedHit(hit); - if (victim instanceof Player) { - ((Player) victim).getPacketDispatch().sendMessage("You have been drained."); - } - int lower = (int) (victim.getSkills().getLevel(Skills.DEFENCE) * 0.05); - victim.getSkills().updateLevel(Skills.DEFENCE, -lower, 0); - int lower2 = (int) (victim.getSkills().getLevel(Skills.ATTACK) * 0.05); - victim.getSkills().updateLevel(Skills.ATTACK, -lower2, 0); - int lower3 = (int) (victim.getSkills().getLevel(Skills.STRENGTH) * 0.05); - victim.getSkills().updateLevel(Skills.STRENGTH, -lower3, 0); return hit; } diff --git a/Server/src/main/content/global/skill/slayer/SlayerEquipmentFlags.kt b/Server/src/main/content/global/skill/slayer/SlayerEquipmentFlags.kt index c953bf9de..e8c5e01e6 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerEquipmentFlags.kt +++ b/Server/src/main/content/global/skill/slayer/SlayerEquipmentFlags.kt @@ -72,7 +72,7 @@ object SlayerEquipmentFlags { val isCape = SlayerManager.getInstance(player).flags.equipmentFlags == 0x3F val hasMask = hasBlackMask(player) - return if(hasMask) 1.15 + return if(hasMask) 1.1667 else if(isCape) 1.075 else 1.0 } diff --git a/Server/src/main/core/game/container/impl/EquipmentContainer.java b/Server/src/main/core/game/container/impl/EquipmentContainer.java index 8ecc54bf5..1e5eba34b 100644 --- a/Server/src/main/core/game/container/impl/EquipmentContainer.java +++ b/Server/src/main/core/game/container/impl/EquipmentContainer.java @@ -323,9 +323,6 @@ public final class EquipmentContainer extends Container { if (item != null) { int[] bonus = item.getDefinition().getConfiguration(ItemConfigParser.BONUS, new int[15]); for (int i = 0; i < bonus.length; i++) { - if (i == 14 && bonuses[i] != 0) { - continue; - } bonuses[i] += bonus[i]; } } diff --git a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt index b5633d588..40df6d765 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt @@ -173,26 +173,21 @@ abstract class CombatSwingHandler(var type: CombatStyle?) { * @return `True` if the hit is accurate. */ fun isAccurateImpact(entity: Entity?, victim: Entity?, style: CombatStyle?, accuracyMod: Double, defenceMod: Double): Boolean { - var mod = 1.33 + var mod = 1.0 if (victim == null || style == null) { return false } if (victim is Player && entity is Familiar && victim.prayer[PrayerType.PROTECT_FROM_SUMMONING]) { mod = 0.0 } - val attack = calculateAccuracy(entity) * accuracyMod * mod * getSetMultiplier(entity, Skills.ATTACK) - val defence = calculateDefence(victim, entity) * defenceMod * getSetMultiplier(victim, Skills.DEFENCE) + val attack = calculateAccuracy(entity) * accuracyMod * mod + val defence = calculateDefence(victim, entity) * defenceMod val chance: Double = if (attack > defence) { - 1 - ((defence + 2) / ((2 * attack) + 1)) + 1 - ((defence + 2) / (2 * (attack + 1))) } else { - attack / ((2 * defence) + 1) + attack / (2 * (defence + 1)) } - val ratio = chance * 100 - val accuracy = floor(ratio) - val block = floor(101 - ratio) - val acc = Math.random() * accuracy - val def = Math.random() * block - return (acc > def).also { if(entity?.username?.toLowerCase() == "test10") log(this::class.java, Log.FINE, "Should hit: $it") } + return Math.random() < chance } /** diff --git a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt index c7d850781..82bf1d5d8 100644 --- a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt @@ -1,5 +1,6 @@ package core.game.node.entity.combat +import content.global.skill.skillcapeperks.SkillcapePerks import core.game.node.entity.Entity import core.game.node.entity.combat.equipment.ArmourSet import core.game.node.entity.combat.spell.SpellType @@ -61,7 +62,7 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag) for (s in state.targets) { var hit = -1 s.spell = spell - if (isAccurateImpact(entity, s.victim, CombatStyle.MAGIC, 1.3, 1.0)) { + if (isAccurateImpact(entity, s.victim, CombatStyle.MAGIC)) { s.maximumHit = max hit = RandomFunction.random(max) } @@ -136,31 +137,31 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag) } override fun calculateAccuracy(entity: Entity?): Int { - val baseLevel = entity!!.skills.getStaticLevel(Skills.MAGIC) - var spellRequirement = baseLevel - if (entity is Player) { - if (entity.getProperties().spell != null) { - spellRequirement = entity.getProperties().spell.level - } else if (entity.getProperties().autocastSpell != null) { - spellRequirement = entity.getProperties().autocastSpell.level + entity ?: return 0 + + val styleAttackBonus = entity.properties.bonuses[WeaponInterface.BONUS_MAGIC] + 64 + when (entity) { + is Player -> { + var effectiveMagicLevel = entity.skills.getLevel(Skills.MAGIC, true).toDouble() + if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) + effectiveMagicLevel = floor(effectiveMagicLevel + (entity.prayer.getSkillBonus(Skills.MAGIC) * effectiveMagicLevel)) + effectiveMagicLevel += 8 + effectiveMagicLevel *= getSetMultiplier(entity, Skills.MAGIC) + effectiveMagicLevel = floor(effectiveMagicLevel) + + if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) + effectiveMagicLevel *= styleAttackBonus + else effectiveMagicLevel *= 64 + + return effectiveMagicLevel.toInt() + } + is NPC -> { + val magicLevel = entity.skills.getLevel(Skills.MAGIC) + 9 + return magicLevel * styleAttackBonus } } - var spellBonus = 0.0 - if (baseLevel > spellRequirement) { - spellBonus = (baseLevel - spellRequirement) * .3 - } - val level = entity.skills.getLevel(Skills.MAGIC, true) - var prayer = 1.0 - if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) { - prayer += entity.prayer.getSkillBonus(Skills.MAGIC) - } - val additional = getSetMultiplier(entity, Skills.MAGIC) - val effective = floor(level * prayer * additional + spellBonus) - val bonus = - if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) - entity.properties.bonuses[WeaponInterface.BONUS_MAGIC] - else 0 - return floor((effective + 8) * (bonus + 64) / 10).toInt() + + return 0 } override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int { @@ -183,14 +184,31 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag) } override fun calculateDefence(victim: Entity?, attacker: Entity?): Int { - val level = victim!!.skills.getLevel(Skills.DEFENCE, true) - var prayer = 1.0 - if (victim is Player) { - prayer += victim.prayer.getSkillBonus(Skills.MAGIC) + victim ?: return 0 + attacker ?: return 0 + + val styleDefenceBonus = victim.properties.bonuses[WeaponInterface.BONUS_MAGIC + 5] + 64 + when (victim) { + is Player -> { + var effectiveDefenceLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble() + effectiveDefenceLevel = floor(effectiveDefenceLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefenceLevel)) + if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefenceLevel += 3 + else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1 + effectiveDefenceLevel *= getSetMultiplier(victim, Skills.DEFENCE) + + var effectiveMagicLevel = victim.skills.getLevel(Skills.MAGIC).toDouble() + effectiveMagicLevel = floor(effectiveMagicLevel + (victim.prayer.getSkillBonus(Skills.MAGIC) * effectiveMagicLevel)) + + effectiveDefenceLevel = effectiveDefenceLevel * 0.3 + effectiveMagicLevel * 0.7 + 8 + return effectiveDefenceLevel.toInt() * styleDefenceBonus + } + is NPC -> { + val defLevel = victim.skills.getLevel(Skills.MAGIC) + 9 + return defLevel * styleDefenceBonus + } } - val effective = floor(level * prayer * 0.3) + victim.skills.getLevel(Skills.MAGIC, true) * 0.7 - val equipment = victim.properties.bonuses[WeaponInterface.BONUS_MAGIC + 5] - return floor((effective + 8) * (equipment + 64) / 10).toInt() + + return 0 } override fun getSetMultiplier(e: Entity?, skillId: Int): Double { diff --git a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt index d755c269d..c32a7567e 100644 --- a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt @@ -64,13 +64,16 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) if (entity is Player) { state.weapon = Weapon(entity.equipment[3]) } - if (entity!!.properties.armourSet === ArmourSet.VERAC && RandomFunction.random(100) < 21) { + if (entity!!.properties.armourSet === ArmourSet.VERAC && RandomFunction.random(100) < 25) { state.armourEffect = ArmourSet.VERAC } if (state.armourEffect === ArmourSet.VERAC || isAccurateImpact(entity, victim, CombatStyle.MELEE)) { - val max = calculateHit(entity, victim, 1.0) + var max = calculateHit(entity, victim, 1.0) + if (victim != null) { + if (entity is NPC && state.armourEffect === ArmourSet.VERAC && victim.hasProtectionPrayer(CombatStyle.MELEE)) max = max * 2 / 3 + } state.maximumHit = max - hit = RandomFunction.random(max + 1) + hit = RandomFunction.random(max + 1) + (if (entity is Player && state.armourEffect === ArmourSet.VERAC) 1 else 0) } state.estimatedHit = hit if(victim != null) { @@ -128,68 +131,79 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) override fun calculateAccuracy(entity: Entity?): Int { //formula taken from wiki: https://oldschool.runescape.wiki/w/Damage_per_second/Melee#Step_six:_Calculate_the_hit_chance Yes I know it's old school. It's the best resource we have for potentially authentic formulae. entity ?: return 0 - var effectiveAttackLevel = entity.skills.getLevel(Skills.ATTACK).toDouble() - if(entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) - effectiveAttackLevel = floor(effectiveAttackLevel + (entity.prayer.getSkillBonus(Skills.ATTACK) * effectiveAttackLevel)) - if(entity.properties.attackStyle.style == WeaponInterface.STYLE_ACCURATE) effectiveAttackLevel += 3 - else if(entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveAttackLevel += 1 - effectiveAttackLevel += 8 - if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.PRECISION_STRIKES, entity)){ //Attack skillcape perk - effectiveAttackLevel += 6 - } - effectiveAttackLevel *= getSetMultiplier(entity, Skills.ATTACK) - effectiveAttackLevel = floor(effectiveAttackLevel) - if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) - effectiveAttackLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64) - else effectiveAttackLevel *= 64 + val styleAttackBonus = entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64 + when (entity) { + is Player -> { + var effectiveAttackLevel = entity.skills.getLevel(Skills.ATTACK).toDouble() + if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) + effectiveAttackLevel = floor(effectiveAttackLevel + (entity.prayer.getSkillBonus(Skills.ATTACK) * effectiveAttackLevel)) + if(entity.properties.attackStyle.style == WeaponInterface.STYLE_ACCURATE) effectiveAttackLevel += 3 + else if(entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveAttackLevel += 1 + effectiveAttackLevel += 8 + if(SkillcapePerks.isActive(SkillcapePerks.PRECISION_STRIKES, entity)){ //Attack skillcape perk + effectiveAttackLevel += 6 + } + effectiveAttackLevel *= getSetMultiplier(entity, Skills.ATTACK) + effectiveAttackLevel = floor(effectiveAttackLevel) + if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) + effectiveAttackLevel *= styleAttackBonus + else effectiveAttackLevel *= 64 - val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none" + val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none" - // attack bonus for specialized equipments (salve amulets, slayer equips) - if (entity is Player) { - val amuletId = getItemFromEquipment(entity, EquipmentSlot.NECK)?.id ?: 0 - if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) { - effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2 - } else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) { - effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape - if (getSlayerTask(entity)?.dragon == true && inEquipment(entity, Items.DRAGON_SLAYER_GLOVES_12862)) - effectiveAttackLevel *= 1.1 + // attack bonus for specialized equipments (salve amulets, slayer equips) + val amuletId = getItemFromEquipment(entity, EquipmentSlot.NECK)?.id ?: 0 + if ((amuletId == Items.SALVE_AMULET_4081 || amuletId == Items.SALVE_AMULETE_10588) && checkUndead(victimName)) { + effectiveAttackLevel *= if (amuletId == Items.SALVE_AMULET_4081) 1.15 else 1.2 + } else if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) { + effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape + if (getSlayerTask(entity)?.dragon == true && inEquipment(entity, Items.DRAGON_SLAYER_GLOVES_12862)) + effectiveAttackLevel *= 1.1 + } + + return effectiveAttackLevel.toInt() + } + is NPC -> { + val attackLevel = entity.skills.getLevel(Skills.ATTACK) + 9 + return attackLevel * styleAttackBonus } } - return floor(effectiveAttackLevel).toInt() + return 0 + + } override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int { - val level = entity!!.skills.getLevel(Skills.STRENGTH) - var bonus = entity.properties.bonuses[11] - var prayer = 1.0 - if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) { - prayer += entity.prayer.getSkillBonus(Skills.STRENGTH) - } - var cumulativeStr = floor(level * prayer) - if (entity.properties.attackStyle.style == WeaponInterface.STYLE_AGGRESSIVE) { - cumulativeStr += 3.0 - } else if (entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) { - cumulativeStr += 1.0 + entity ?: return 0 + + var styleStrengthBonus = entity.properties.bonuses[11] + 64 + when (entity) { + is Player -> { + var effectiveStrengthLevel = entity.skills.getLevel(Skills.STRENGTH).toDouble() + if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) + effectiveStrengthLevel = floor(effectiveStrengthLevel + (entity.prayer.getSkillBonus(Skills.STRENGTH) * effectiveStrengthLevel)) + if(entity.properties.attackStyle.style == WeaponInterface.STYLE_AGGRESSIVE) effectiveStrengthLevel += 3 + else if (entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveStrengthLevel += 1 + effectiveStrengthLevel += 8 + effectiveStrengthLevel *= getSetMultiplier(entity, Skills.STRENGTH) + effectiveStrengthLevel = floor(effectiveStrengthLevel) + if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE)) + effectiveStrengthLevel *= styleStrengthBonus + else effectiveStrengthLevel *= 64 + if (getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) + effectiveStrengthLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape + + return (floor((0.5 + (effectiveStrengthLevel / 640.0))) * modifier).toInt() + } + is NPC -> { + val strengthLevel = entity.skills.getLevel(Skills.STRENGTH) + 9 + return (floor((0.5 + (strengthLevel * styleStrengthBonus / 640.0))) * modifier).toInt() + } } - //Strength skillcape perk - if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.FINE_ATTUNEMENT, entity) && getItemFromEquipment(entity, EquipmentSlot.WEAPON)?.definition?.getRequirement(Skills.STRENGTH) != 0) - bonus = ceil(bonus * 1.20).toInt() - - if (flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE)) - bonus = 0 - - cumulativeStr *= getSetMultiplier(entity, Skills.STRENGTH) - - if(entity is Player && getSlayerTask(entity)?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) - cumulativeStr *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer helm/black mask/skillcape - - /*val hit = (16 + cumulativeStr + bonus / 8 + cumulativeStr * bonus * 0.016865) * modifier - return (hit / 10).toInt() + 1*/ - return ((1.3 + (cumulativeStr / 10) + (bonus / 80) + ((cumulativeStr * bonus) / 640)) * modifier).toInt() + return 0 } override fun calculateDefence(victim: Entity?, attacker: Entity?): Int { @@ -197,19 +211,19 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) victim ?: return 0 attacker ?: return 0 - when(victim){ + val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64 + when (victim) { is Player -> { var effectiveDefenceLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble() effectiveDefenceLevel = floor(effectiveDefenceLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefenceLevel)) - if(victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE) effectiveDefenceLevel += 3 - else if(victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1 + if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefenceLevel += 3 + else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefenceLevel += 1 effectiveDefenceLevel += 8 - effectiveDefenceLevel = floor(effectiveDefenceLevel) - return floor(effectiveDefenceLevel * (victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64)).toInt() + effectiveDefenceLevel *= getSetMultiplier(victim, Skills.DEFENCE) + return effectiveDefenceLevel.toInt() * styleDefenceBonus } is NPC -> { - val defLevel = victim.skills.getLevel(Skills.DEFENCE) - val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64 + val defLevel = victim.skills.getLevel(Skills.DEFENCE) + 9 return defLevel * styleDefenceBonus } } diff --git a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt index 325dd3f78..c0e20bf67 100644 --- a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt @@ -13,14 +13,14 @@ import core.game.node.entity.skill.Skills import core.game.node.item.GroundItem import core.game.node.item.GroundItemManager import core.game.node.item.Item +import core.game.system.config.ItemConfigParser import core.game.system.task.Pulse +import core.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.update.flag.context.Graphics -import core.tools.RandomFunction -import core.tools.SystemLogger -import core.game.world.GameWorld import core.tools.Log +import core.tools.RandomFunction import java.util.* import kotlin.math.ceil import kotlin.math.floor @@ -83,7 +83,7 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) state.estimatedHit = hit if (state.weapon.type == WeaponType.DOUBLE_SHOT) { if (isAccurateImpact(entity, victim, CombatStyle.RANGE)) { - hit = RandomFunction.random(calculateHit(entity, victim, 1.0)) + hit = RandomFunction.random(calculateHit(entity, victim, 1.0) + 1) } state.secondaryHit = hit } @@ -183,56 +183,92 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) override fun calculateAccuracy(entity: Entity?): Int { entity ?: return 0 - var effectiveRangedLevel = entity.skills.getLevel(Skills.RANGE).toDouble() - if(entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) - effectiveRangedLevel = floor(effectiveRangedLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveRangedLevel)) - if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveRangedLevel += 3 - effectiveRangedLevel += 8 - effectiveRangedLevel *= getSetMultiplier(entity, Skills.RANGE) - if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.ACCURATE_MARKSMAN,entity)) effectiveRangedLevel *= 1.1 - effectiveRangedLevel = floor(effectiveRangedLevel) - if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) - effectiveRangedLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64) - else effectiveRangedLevel *= 64 + val styleAttackBonus = entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64 + when (entity) { + is Player -> { + var effectiveRangedLevel = entity.skills.getLevel(Skills.RANGE).toDouble() + if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_ACCURACY)) + effectiveRangedLevel = floor(effectiveRangedLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveRangedLevel)) + if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveRangedLevel += 3 + effectiveRangedLevel += 8 + effectiveRangedLevel *= getSetMultiplier(entity, Skills.RANGE) + if(SkillcapePerks.isActive(SkillcapePerks.ACCURATE_MARKSMAN,entity)) effectiveRangedLevel *= 1.1 - return floor(effectiveRangedLevel).toInt() + effectiveRangedLevel = floor(effectiveRangedLevel) + if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_ACCURACY)) + effectiveRangedLevel *= styleAttackBonus + else effectiveRangedLevel *= 64 + + return effectiveRangedLevel.toInt() + } + is NPC -> { + val rangedLevel = entity.skills.getLevel(Skills.RANGE) + 9 + return rangedLevel * styleAttackBonus + } + } + + return 0 } override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int { - val level = entity!!.skills.getLevel(Skills.RANGE) - val bonus = entity.properties.bonuses[14] - var prayer = 1.0 - if (entity is Player && !flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) { - prayer += entity.prayer.getSkillBonus(Skills.RANGE) - } - var cumulativeStr = floor(level * prayer) - if (entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) { - cumulativeStr += 3.0 - } - cumulativeStr *= getSetMultiplier(entity, Skills.RANGE) + entity ?: return 0 - if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE)) - cumulativeStr *= (bonus + 64) - else cumulativeStr *= 64 + var styleStrengthBonus = entity.properties.bonuses[14] + 64 + when (entity) { + is Player -> { + if(entity.equipment[EquipmentContainer.SLOT_WEAPON] != null && RangeWeapon.get(entity.equipment[EquipmentContainer.SLOT_WEAPON].id).ammunitionSlot != EquipmentContainer.SLOT_ARROWS && entity.equipment[EquipmentContainer.SLOT_ARROWS] != null) + styleStrengthBonus -= entity.equipment[EquipmentContainer.SLOT_ARROWS].definition.getConfiguration(ItemConfigParser.BONUS)[14] + var effectiveStrengthLevel = entity.skills.getLevel(Skills.RANGE).toDouble() + if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) + effectiveStrengthLevel = floor(effectiveStrengthLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveStrengthLevel)) + if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveStrengthLevel += 3 + effectiveStrengthLevel += 8 + effectiveStrengthLevel *= getSetMultiplier(entity, Skills.RANGE) + effectiveStrengthLevel = floor(effectiveStrengthLevel) + if (!flags.contains(SwingHandlerFlag.IGNORE_STAT_BOOSTS_DAMAGE)) + effectiveStrengthLevel *= styleStrengthBonus + else effectiveStrengthLevel *= 64 - return floor((1.5 + (ceil(cumulativeStr) / 640.0)) * modifier).toInt() - //return ((14 + cumulativeStr + bonus / 8 + cumulativeStr * bonus * 0.016865) * modifier).toInt() / 10 + 1 + return (floor((0.5 + (effectiveStrengthLevel / 640.0))) * modifier).toInt() + } + is NPC -> { + val rangedLevel = entity.skills.getLevel(Skills.RANGE) + 9 + return (floor((0.5 + (rangedLevel * styleStrengthBonus / 640.0))) * modifier).toInt() + } + } + + return 0 } override fun calculateDefence(victim: Entity?, attacker: Entity?): Int { victim ?: return 0 attacker ?: return 0 - val defLevel = victim.skills.getLevel(Skills.DEFENCE) val styleDefenceBonus = victim.properties.bonuses[attacker.properties.attackStyle.bonusType + 5] + 64 - return defLevel * styleDefenceBonus + when (victim) { + is Player -> { + var effectiveDefLevel = victim.skills.getLevel(Skills.DEFENCE).toDouble() + effectiveDefLevel = floor(effectiveDefLevel + (victim.prayer.getSkillBonus(Skills.DEFENCE) * effectiveDefLevel)) + if (victim.properties.attackStyle.style == WeaponInterface.STYLE_DEFENSIVE || victim.properties.attackStyle.style == WeaponInterface.STYLE_LONG_RANGE) effectiveDefLevel += 3 + else if (victim.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) effectiveDefLevel += 1 + effectiveDefLevel += 8 + effectiveDefLevel *= getSetMultiplier(victim, Skills.DEFENCE) + return effectiveDefLevel.toInt() * styleDefenceBonus + } + is NPC -> { + val defLevel = victim.skills.getLevel(Skills.DEFENCE) + 9 + return defLevel * styleDefenceBonus + } + } + + return 0 } override fun getSetMultiplier(e: Entity?, skillId: Int): Double { if(skillId == Skills.RANGE) { if(e is Player && e.isWearingVoid(CombatStyle.RANGE)) { - return 1.1 + return 1.2 } } return 1.0 diff --git a/Server/src/main/core/game/node/entity/combat/equipment/ArmourSet.java b/Server/src/main/core/game/node/entity/combat/equipment/ArmourSet.java index 16097c032..f311b95e6 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/ArmourSet.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/ArmourSet.java @@ -21,7 +21,7 @@ public enum ArmourSet { AHRIM(new Graphics(401, 96), new int[][] { { 4708, 4856, 4857, 4858, 4859 }, { 4710, 4862, 4863, 4864, 4865 }, { 4712, 4868, 4869, 4870, 4871 }, { 4714, 4874, 4875, 4876, 4877 } }) { @Override public boolean effect(Entity e, Entity victim, BattleState state) { - if (RandomFunction.random(100) < 20) { + if (RandomFunction.random(100) < 25 && state.getEstimatedHit() > -1) { victim.getSkills().updateLevel(Skills.STRENGTH, -5, 0); return true; } @@ -78,8 +78,8 @@ public enum ArmourSet { KARIL(new Graphics(400, 96), new int[][] { { 4732, 4928, 4929, 4930, 4931 }, { 4734, 4934, 4935, 4936, 4937 }, { 4736, 4940, 4941, 4942, 4943 }, { 4738, 4946, 4947, 4948, 4949 } }) { @Override public boolean effect(Entity e, Entity victim, BattleState state) { - if (state.getEstimatedHit() > 9 && RandomFunction.random(100) < 20) { - victim.getSkills().updateLevel(Skills.AGILITY, -(state.getEstimatedHit() / 10), 0); + if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 25) { + victim.getSkills().updateLevel(Skills.AGILITY, -(victim.getSkills().getDynamicLevels()[Skills.AGILITY] / 5), 0); return true; } return false; @@ -100,7 +100,7 @@ public enum ArmourSet { TORAG(new Graphics(399, 96), new int[][] { { 4745, 4952, 4953, 4954, 4955 }, { 4747, 4958, 4959, 4960, 4961 }, { 4749, 4964, 4965, 4966, 4967 }, { 4751, 4970, 4971, 4972, 4973 } }) { @Override public boolean effect(Entity e, Entity victim, BattleState state) { - if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 20) { + if (state.getEstimatedHit() > 0 && RandomFunction.random(100) < 25) { if (victim instanceof Player) { ((Player) victim).getSettings().updateRunEnergy(20); } diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 9893a25a8..fb7b7b544 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -46,10 +46,11 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ player.toggleDebug() } - define("calc_accuracy", Privilege.STANDARD, "::calc_accuracy NPC ID", "Calculates and prints your current chance to hit a given NPC."){ player, args -> + define("calcaccuracy", Privilege.STANDARD, "::calcaccuracy NPC ID", "Calculates and prints your current chance to hit a given NPC."){ player, args -> val handler = player.getSwingHandler(false) player.sendMessage("handler type: ${handler.type}") - player.sendMessage("calculateAccuracy: ${handler.calculateAccuracy(player)}") + val accuracy = handler.calculateAccuracy(player) + player.sendMessage("calculateAccuracy: ${accuracy}") if (args.size > 1) { @@ -57,7 +58,14 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ val npc = NPC(npcId) npc.initConfig() player.sendMessage("npc: ${npc.name}. npc defence: ${npc.skills.getLevel(Skills.DEFENCE)}") - player.sendMessage("calculateDefence: ${handler.calculateDefence(npc, player)}") + val defence = handler.calculateDefence(npc, player) + player.sendMessage("calculateDefence: ${defence}") + val chance: Double = if (accuracy > defence) { + 1.0 - ((defence + 2.0) / (2.0 * (accuracy + 1.0))) + } else { + accuracy / (2.0 * (defence + 1.0)) + } + player.sendMessage("chance to hit: ${chance}") } } @@ -107,7 +115,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ define("calcmaxhit", Privilege.STANDARD, "", "Calculates and shows you your current max hit.") { player, _ -> val swingHandler = player.getSwingHandler(false) val hit = swingHandler.calculateHit(player, player, 1.0) - notify(player, "max hit (${(swingHandler as Object).getClass().getName()}): ${hit}") + notify(player, "max hit: ${hit} (${(swingHandler as Object).getClass().getName()})") } /** diff --git a/Server/src/test/kotlin/content/CombatTests.kt b/Server/src/test/kotlin/content/CombatTests.kt index 55ffc715e..762ed8406 100644 --- a/Server/src/test/kotlin/content/CombatTests.kt +++ b/Server/src/test/kotlin/content/CombatTests.kt @@ -2,6 +2,10 @@ package content import TestUtils import content.global.handlers.item.equipment.special.ChinchompaSwingHandler +import core.api.EquipmentSlot +import core.game.container.impl.EquipmentContainer.updateBonuses +import core.game.interaction.IntType +import core.game.interaction.InteractionListeners import core.game.node.entity.combat.MagicSwingHandler import core.game.node.entity.combat.MeleeSwingHandler import core.game.node.entity.combat.RangeSwingHandler @@ -9,8 +13,10 @@ import core.game.node.entity.combat.SwingHandlerFlag import core.game.node.entity.combat.equipment.WeaponInterface import core.game.node.entity.player.link.prayer.PrayerType import core.game.node.entity.skill.Skills +import core.game.node.item.Item import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import org.rs09.consts.Items class CombatTests { init { @@ -115,12 +121,17 @@ class CombatTests { } } - @Test fun chinchompaSwingHandlerIgnoresStatsForDamage() { + @Test fun chinchompaSwingHandlerIgnoresAmmoSlotForDamage() { val handler = ChinchompaSwingHandler() TestUtils.getMockPlayer("chinchompaStatTest").use { p -> + p.skills.staticLevels[Skills.RANGE] = 99 + p.skills.dynamicLevels[Skills.RANGE] = 99 + p.equipment.replace(Item(Items.CHINCHOMPA_10033), EquipmentSlot.WEAPON.ordinal) + updateBonuses(p) val damageBaseline = handler.calculateHit(p, p, 1.0) - p.properties.bonuses[14] = 250 + p.equipment.replace(Item(Items.DRAGON_ARROW_11212), EquipmentSlot.AMMO.ordinal) + updateBonuses(p) Assertions.assertEquals(damageBaseline, handler.calculateHit(p, p, 1.0)) } } From e31397b42f886c71e7531d6e6f4f3e43a31995e1 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 12:29:06 +0000 Subject: [PATCH 019/306] Corrected summoning point drain rate --- .../skill/summoning/familiar/Familiar.java | 100 +++++++++++++----- 1 file changed, 72 insertions(+), 28 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java index b74f15e6b..b85c1ec16 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java +++ b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java @@ -27,7 +27,6 @@ import core.tools.Log; import core.tools.RandomFunction; import core.game.node.entity.combat.CombatPulse; import core.game.node.entity.combat.CombatSwingHandler; -import core.tools.SystemLogger; import core.game.world.GameWorld; import content.global.skill.summoning.SummoningPouch; import org.rs09.consts.Sounds; @@ -120,7 +119,30 @@ public abstract class Familiar extends NPC implements Plugin { */ private final int attackStyle; - private boolean firstCall = true; + /** + * The amount of points to drain every tick. + * This is a constant depending on the familiar's level req and time remaining (GL #1903). + * https://runescape.wiki/w/Summoning_points?oldid=2171795: "Over the life of the familiar, the number of summoning + * points drained will be equal to the level required to summon the familiar (unless you run out of summoning + * points). This means that if a player summons a bunyip with 75 Summoning points remaining, 7 points will be + * drained immediately, and 61 more will be drained over the life the bunyip, for a total of 68 points (the level of + * the bunyip)." + */ + private final double pointsPerTick; + + /** + * Keeps track of the fractional pointsPerTick that have been drained already. If >1.0, drain a point and subtract + * 1.0. Note that this means that we will never drain a point on the final tick (unless pointsPerTick turned out to + * be integer, but this case is handled by the 'ticks > 0' check in handleTickActions()). This is intentional; it + * allows us to, correctly, artificially extend the interval by one so that the drain events are evenly spaced + * throughout the lifetime of the summon (refer to the dreadfowl example below). + */ + private double fracDrain = 0.0; + + /** + * Whether this is the first call (i.e. not a renew summon). + */ + private boolean firstCall = true; /** * Constructs a new {@code Familiar} {@code Object}. @@ -141,6 +163,23 @@ public abstract class Familiar extends NPC implements Plugin { this.specialCost = specialCost; this.combatFamiliar = NPCDefinition.forId(getOriginalId() + 1).getName().equals(getName()); this.attackStyle = attackStyle; + /* The initial points are drained on summon. Then, the remaining points are drained over an interval. + * To prevent the last point from being drained only very late, we artificially extend the interval by one. + * Example: a dreadfowl drains 1 point on summon, and then needs to drain 3 points over 400 ticks. Naively + * draining a point on ticks 133, 266, and 399 allows players to save a point at the expense of just one tick. + * Instead, we drain on ticks 100, 200, and 300. + * Example 2: a spirit tz-kih drains 3 points on summon, then needs to drain 19 more points over 1800 ticks. + * This means it needs to drain a point every 90 ticks, since the 0th tick remaining will not drain. + * Example 3: a vampire bat needs to drain 27 points over 3300 ticks. It hence drains a point every ~118 ticks. + * Example 4: an abyssal titan drains 10 points on summon, then needs to drain 83 more points over 3200 ticks. + * This means it needs to drain a point every ~34 ticks. + */ + if (pouchId == -1) { + this.pointsPerTick = 0.0; + } else { + int drain = pouch.getLevelRequired() - pouch.getSummonCost() + 1; + this.pointsPerTick = (double) drain / maximumTicks; + } } /** @@ -176,17 +215,22 @@ public abstract class Familiar extends NPC implements Plugin { transform(); } } - - @Override + + @Override public void init() { init(getSpawnLocation(), true); } @Override public void handleTickActions() { - if (ticks-- % 50 == 0) { - updateSpecialPoints(-15); + ticks--; + fracDrain += pointsPerTick; + if (fracDrain > 1.0 && ticks > 0) { + fracDrain -= 1.0; owner.getSkills().updateLevel(Skills.SUMMONING, -1, 0); + } + if (ticks % 50 == 0) { + updateSpecialPoints(-15); if (!getText().isEmpty()) { super.sendChat(getText()); } @@ -231,7 +275,7 @@ public abstract class Familiar extends NPC implements Plugin { @Override public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { if (entity == owner) { - if(message) { + if (message) { owner.getPacketDispatch().sendMessage("You can't just betray your own familiar like that!"); } return false; @@ -243,13 +287,13 @@ public abstract class Familiar extends NPC implements Plugin { } if (!getProperties().isMultiZone()) { if (entity instanceof Player && !((Player) entity).getProperties().isMultiZone()) { - if(message) { + if (message) { ((Player) entity).getPacketDispatch().sendMessage("You have to be in multicombat to attack a player's familiar."); } return false; } if (entity instanceof Player) { - if(message) { + if (message) { ((Player) entity).getPacketDispatch().sendMessage("This familiar is not in the a multicombat zone."); } } @@ -257,13 +301,13 @@ public abstract class Familiar extends NPC implements Plugin { } if (entity instanceof Player) { if (!((Player) entity).getSkullManager().isWilderness()) { - if(message) { + if (message) { ((Player) entity).getPacketDispatch().sendMessage("You have to be in the wilderness to attack a player's familiar."); } return false; } if (!owner.getSkullManager().isWilderness()) { - if(message) { + if (message) { ((Player) entity).getPacketDispatch().sendMessage("This familiar's owner is not in the wilderness."); } return false; @@ -340,8 +384,8 @@ public abstract class Familiar extends NPC implements Plugin { private void sendTimeRemaining() { int minutes = ticks / 100; int centiminutes = ticks % 100; - setVarbit(owner, 4534, minutes); - setVarbit(owner, 4290, centiminutes > 49 ? 1 : 0); + setVarbit(owner, 4534, minutes); + setVarbit(owner, 4290, centiminutes > 49 ? 1 : 0); } /** @@ -542,9 +586,9 @@ public abstract class Familiar extends NPC implements Plugin { * Sends the familiar packets. */ public void sendConfiguration() { - setVarp(owner, 448, getPouchId()); - setVarp(owner, 1174, getOriginalId()); - setVarp(owner, 1175, specialCost << 23); + setVarp(owner, 448, getPouchId()); + setVarp(owner, 1174, getOriginalId()); + setVarp(owner, 1175, specialCost << 23); sendTimeRemaining(); updateSpecialPoints(0); } @@ -565,13 +609,13 @@ public abstract class Familiar extends NPC implements Plugin { if (isInvisible()) return true; getProperties().setTeleportLocation(destination); if (!(this instanceof Pet)) { - if(firstCall) { + if (firstCall) { // TODO: Each familiar has its own initial summon sound that needs to be implemented at some point - playAudio(owner, Sounds.SUMMON_NPC_188); - firstCall = false; - } else { - playAudio(owner, Sounds.SUMMON_NPC_188); - } + playAudio(owner, Sounds.SUMMON_NPC_188); + firstCall = false; + } else { + playAudio(owner, Sounds.SUMMON_NPC_188); + } if (size() > 1) { graphics(LARGE_SUMMON_GRAPHIC); } else { @@ -607,10 +651,10 @@ public abstract class Familiar extends NPC implements Plugin { getPulseManager().clear(); owner.getInterfaceManager().removeTabs(7); owner.getFamiliarManager().setFamiliar(null); - setVarp(owner, 448, -1); - setVarp(owner, 1176, 0); - setVarp(owner, 1175, 182986); - setVarp(owner, 1174, -1); + setVarp(owner, 448, -1); + setVarp(owner, 1176, 0); + setVarp(owner, 1175, 182986); + setVarp(owner, 1174, -1); owner.getAppearance().sync(); owner.getInterfaceManager().setViewedTab(3); } @@ -624,14 +668,14 @@ public abstract class Familiar extends NPC implements Plugin { if (specialPoints > 60) { specialPoints = 60; } - setVarp(owner, 1177, specialPoints); + setVarp(owner, 1177, specialPoints); } @Override public Plugin newInstance(Object arg) throws Throwable { for (int id : getIds()) { if (FamiliarManager.getFamiliars().containsKey(id)) { - log(this.getClass(), Log.ERR, "Familiar " + id + " was already registered!"); + log(this.getClass(), Log.ERR, "Familiar " + id + " was already registered!"); return null; } FamiliarManager.getFamiliars().put(id, this); From 64fa1d89c3d85f739d34f8662e0f2c6720bfa385 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 12:35:49 +0000 Subject: [PATCH 020/306] Players are now rescued out of the unimplemented high-level Bounty Hunter crater --- .../bountyhunter/UnimplementedCraterArea.kt | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Server/src/main/content/minigame/bountyhunter/UnimplementedCraterArea.kt diff --git a/Server/src/main/content/minigame/bountyhunter/UnimplementedCraterArea.kt b/Server/src/main/content/minigame/bountyhunter/UnimplementedCraterArea.kt new file mode 100644 index 000000000..60050f9c7 --- /dev/null +++ b/Server/src/main/content/minigame/bountyhunter/UnimplementedCraterArea.kt @@ -0,0 +1,75 @@ +package content.minigame.bountyhunter.handlers + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.system.task.Pulse +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import org.rs09.consts.NPCs +import core.game.dialogue.DialogueFile +import core.game.world.GameWorld + +class UnimplementedCraterArea : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf( + ZoneBorders(3200, 5632, 3391, 5823) + ) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player && ( + defineAreaBorders()[0].insideBorder(entity) + )) { + kickThemOut(entity) + } + } + + private fun kickThemOut(entity: Player) { + val watchdog = NPC(NPCs.BANKER_6538) + watchdog.isNeverWalks = true + watchdog.isWalks = false + watchdog.location = entity.location + watchdog.init() + entity.lock() + + runTask(watchdog, 1) { + watchdog.moveStep() + watchdog.face(entity) + openDialogue(entity, UnimplementedCraterDialogue(), watchdog) + GameWorld.Pulser.submit(object : Pulse() { + override fun pulse(): Boolean { + if (getAttribute(entity, "teleporting-away", false)) + return true + if (!entity.isActive) + poofClear(watchdog) + if (entity.dialogueInterpreter.dialogue == null || entity.dialogueInterpreter.dialogue.file == null) + openDialogue(entity, UnimplementedCraterDialogue(), watchdog) + return !watchdog.isActive || !entity.isActive + } + }) + } + } + + class UnimplementedCraterDialogue : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when(stage) { + 0 -> npcl(core.game.dialogue.FacialExpression.WORRIED, "This is unimplemented content, and you are now stuck. Don't worry, I'll get you out of here!").also { stage++ } + 1 -> { + end() + visualize(npc!!, 1818, 343) + sendGraphics(342, player!!.location) + setAttribute(player!!, "teleporting-away", true) + runTask(player!!, 3) { + poofClear(npc!!) + teleport(player!!, Location.create(3179, 3685, 0)) + unlock(player!!) + removeAttribute(player!!, "teleporting-away") + } + } + } + } + } +} + From 9d38357c4ee5dfc046fa7809607d6d314fe5fe25 Mon Sep 17 00:00:00 2001 From: GregF Date: Sun, 6 Oct 2024 12:43:22 +0000 Subject: [PATCH 021/306] Corrected Lighthouse Dagannoth drop table --- Server/data/configs/drop_tables.json | 202 +++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 2e5f8b80e..1a8525af4 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -20143,6 +20143,208 @@ } ] }, + { + "default": [ + { + "minAmount": "1", + "weight": "1.0", + "id": "526", + "maxAmount": "1" + } + ], + "charm": [ + { + "minAmount": "1", + "weight": "55.0", + "id": "0", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "13.0", + "id": "12158", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "6.0", + "id": "12159", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "25.0", + "id": "12160", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "12163", + "maxAmount": "1" + } + ], + "ids": "1338", + "description": "Chaos Tunnels / Lighthouse Dagannoths", + "main": [ + { + "minAmount": "1", + "weight": "5.0", + "id": "1237", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "5.0", + "id": "1239", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "1243", + "maxAmount": "1" + }, + { + "minAmount": "15", + "weight": "4.0", + "id": "555", + "maxAmount": "15" + }, + { + "minAmount": "15", + "weight": "2.0", + "id": "886", + "maxAmount": "15" + }, + { + "minAmount": "3", + "weight": "1.0", + "id": "828", + "maxAmount": "3" + }, + { + "minAmount": "1", + "weight": "18.0", + "id": "14428", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "12.0", + "id": "301", + "maxAmount": "1" + }, + { + "minAmount": "3", + "weight": "4.0", + "id": "345", + "maxAmount": "3" + }, + { + "minAmount": "5", + "weight": "4.0", + "id": "327", + "maxAmount": "5" + }, + { + "minAmount": "1", + "weight": "3.0", + "id": "311", + "maxAmount": "1" + }, + { + "minAmount": "15", + "weight": "2.0", + "id": "314", + "maxAmount": "15" + }, + { + "minAmount": "50", + "weight": "2.0", + "id": "313", + "maxAmount": "50" + }, + { + "minAmount": "1", + "weight": "2.0", + "id": "377", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "2.0", + "id": "359", + "maxAmount": "1" + }, + { + "minAmount": "10", + "weight": "2.0", + "id": "402", + "maxAmount": "10" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "413", + "maxAmount": "1" + }, + { + "minAmount": "2", + "weight": "1.0", + "id": "411", + "maxAmount": "2" + }, + { + "minAmount": "56", + "weight": "29.0", + "id": "995", + "maxAmount": "56" + }, + { + "minAmount": "25", + "weight": "9.0", + "id": "995", + "maxAmount": "25" + }, + { + "minAmount": "44", + "weight": "8.0", + "id": "995", + "maxAmount": "44" + }, + { + "minAmount": "41", + "weight": "6.0", + "id": "995", + "maxAmount": "41" + }, + { + "minAmount": "12", + "weight": "2.0", + "id": "45", + "maxAmount": "12" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "405", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "5733", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "14426", + "maxAmount": "1" + } + ] + }, { "default": [ { From 97b8ed19a6200a608ca38064adc2ab657835f652 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 6 Oct 2024 12:45:10 +0000 Subject: [PATCH 022/306] Fixed the Priest in Peril items not showing up in HD --- .../PriestInPerilOptionPlugin.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java index 4e0c6ef3d..efc682437 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java @@ -22,6 +22,7 @@ import org.rs09.consts.NPCs; */ @Initializable public class PriestInPerilOptionPlugin extends OptionHandler { + /** * (non-Javadoc) * @see Plugin#newInstance(Object) @@ -105,6 +106,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 2347; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 128, 0); message = "Saradomin is the hammer that crushes evil everywhere."; } if (id == 3498) { @@ -113,6 +116,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 1733; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 128, 0); message = "Saradomin is the needle that binds our lives together."; } if (id == 3495) { @@ -121,6 +126,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 1931; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 128, 0); message = "Saradomin is the vessel that keeps our lives from harm."; } if (id == 3497) { @@ -129,6 +136,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 314; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 128, 0); message = "Saradomin is the delicate touch that brushes us with love."; } if (id == 3494) { @@ -137,6 +146,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 36; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 256, 0); message = "Saradomin is the light that shines throughout our lives."; } if (id == 3499) { @@ -145,6 +156,8 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 2944; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 512, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 512, 256, 0); message = "Saradomin is the key that unlocks the mysteries of life."; } if (id == 3493) { @@ -153,10 +166,13 @@ public class PriestInPerilOptionPlugin extends OptionHandler { } else { item = 590; } + player.getPacketDispatch().sendItemZoomOnInterface(item, 320, 272, 4); + player.getPacketDispatch().sendAngleOnInterface(272, 4, 320, 256, 0); message = "Saradomin is the spark that lights the fire in our hearts."; } player.getPacketDispatch().sendString(message, 272, 17); - player.getPacketDispatch().sendItemZoomOnInterface(item, 175, 272, 4); + // In SD, this is fine. in HD, this gets clipped when you zoom out too much or zoom in too much. + //player.getPacketDispatch().sendItemZoomOnInterface(item, 175, 272, 4); break; case "take-from": player.getImpactHandler().handleImpact(player, 2, CombatStyle.MELEE); From 5abe50430d1a29911613b932d46f65dd0bc5b1b9 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Sun, 6 Oct 2024 12:47:54 +0000 Subject: [PATCH 023/306] Improved bank updates, likely fix for bank UI delay --- .../src/main/core/game/container/impl/BankContainer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index 8974faa68..f8f994d4d 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -2,6 +2,7 @@ package core.game.container.impl; import core.api.IfaceSettingsBuilder; import core.game.container.access.InterfaceContainer; +import kotlin.Unit; import kotlin.ranges.IntRange; import org.rs09.consts.Vars; import core.ServerConstants; @@ -238,7 +239,7 @@ public final class BankContainer extends Container { } } - if (player.getInventory().remove(item, slot, true)) { + if (player.getInventory().remove(item, slot, false)) { int preferredSlot = -1; if (tabIndex != 0 && tabIndex != 10 && !super.contains(add.getId(), 1)) { preferredSlot = tabStartSlot[tabIndex] + getItemsInTab(tabIndex); @@ -246,6 +247,7 @@ public final class BankContainer extends Container { increaseTabStartSlots(tabIndex); } super.add(add, true, preferredSlot); + player.getInventory().update(); } } @@ -283,13 +285,14 @@ public final class BankContainer extends Container { add = item; } if (super.remove(item, slot, false)) { - player.getInventory().add(add); + player.getInventory().add(add, false); } if (get(slot) == null) { int tabId = getTabByItemSlot(slot); decreaseTabStartSlots(tabId); shift(); } else update(); + player.getInventory().update(); } /** From 2be422e7da4ecb404fa48a07f3ae812240891c0d Mon Sep 17 00:00:00 2001 From: Kennynes Date: Sun, 6 Oct 2024 12:49:54 +0000 Subject: [PATCH 024/306] Reverted some tutorial island dialogue --- .../region/misc/tutisland/handlers/TutorialStage.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/region/misc/tutisland/handlers/TutorialStage.kt b/Server/src/main/content/region/misc/tutisland/handlers/TutorialStage.kt index 0fafa1c84..3ab07f9ac 100644 --- a/Server/src/main/content/region/misc/tutisland/handlers/TutorialStage.kt +++ b/Server/src/main/content/region/misc/tutisland/handlers/TutorialStage.kt @@ -814,10 +814,10 @@ object TutorialStage { Component.setUnclosable( player, player.dialogueInterpreter.sendPlaneMessageWithBlueTitle( - "This is your worn equipment.", - "From here you can see what items you have equipped. You will", - "notice the button 'Show Equipment Stats'. Click on this now to", - "display the details of what you have equipped.", + "This is your worn inventory.", + "From here you can see what items you have equipped. Let's", + "get one of those slots filled, go back to your inventory and", + "right click your dagger, select wield from the menu.", "" ) ) From 39822585004dbeb19f595ccfba3b7eabc160665a Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 6 Oct 2024 13:06:07 +0000 Subject: [PATCH 025/306] Corrected iron-ore-smelting success rate --- .../content/global/skill/smithing/smelting/SmeltingPulse.java | 2 +- Server/src/main/core/tools/RandomFunction.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java index 06c55f1e1..e48e85508 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java +++ b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java @@ -204,7 +204,7 @@ public class SmeltingPulse extends SkillPulse { } return true; } else { - return RandomFunction.getRandom(100) <= (player.getSkills().getLevel(Skills.SMITHING) >= 45 ? 80 : 50); + return RandomFunction.nextBool(); } } return true; diff --git a/Server/src/main/core/tools/RandomFunction.java b/Server/src/main/core/tools/RandomFunction.java index 7e8dd580f..61d3275ad 100644 --- a/Server/src/main/core/tools/RandomFunction.java +++ b/Server/src/main/core/tools/RandomFunction.java @@ -49,9 +49,9 @@ public class RandomFunction { * @param chance the 1/chance rate for the roll to succeed * @return true if you hit the roll, false otherwise */ - public static boolean roll(int chance){ + public static boolean roll(int chance) { if (chance <= 1) return true; - return random(chance + 1) == chance / 2; + return random(chance) == 1; } /** From cc8dd4edb40fb4c081b45f7159d6335b5012163c Mon Sep 17 00:00:00 2001 From: Bonesy <15719383-joshking071@users.noreply.gitlab.com> Date: Sun, 6 Oct 2024 13:12:33 +0000 Subject: [PATCH 026/306] Rewrote some Varrock plugins Removed duplicated handlers for many Varrock related stairs and ladders Fixed the Champions' Guild trapdoor being unable to be closed Changed the model ID for the logs outside of Seth Groats's house when the axe is taken The drawers in Guidor's house will no longer disappear. There doesn't appear to be a related open object, so they just won't open The Benny NPC yells about newspapers again Knocking on the door in the Varrock bank will start the dialogue with the bankers The Varrock Census object in the Varrock castle will now open the Varrock Census interface Added sounds for opening/closing drawers, wardrobes, and cupboards and animations for wardrobes Added the Kudos overlay in the Varrock Museum Corrected the spawns for archeologists in the Varrock Museum dig site area Implemented the Varrock museum map interface to open from the objects and item The tool shelf in the museum dig site area will now give items Looking at the displays in the in the Natural History area of the museum will open the interface for the exam and provided some notes --- Server/data/configs/npc_spawns.json | 18 +- .../cchallange/ChampionChallengeListener.kt | 31 +- .../handlers/scenery/DoogleLeafPlugin.java | 39 --- .../handlers/scenery/DoorManagingPlugin.java | 19 ++ .../scenery/LadderManagingPlugin.java | 2 + .../handlers/LumbridgeNodePlugin.java | 14 +- .../varrock/dialogue/KnockAtBankDoor.kt | 59 ++++ .../varrock/dialogue/MuseumGuardDialogue.java | 88 ----- .../dialogue/MuseumGuardVarrockDialogue.java | 69 ---- .../dialogue/MuseumGuardsDialoguePlugin.kt | 89 +++++ .../misthalin/varrock/handlers/BennyNPC.java | 64 ---- .../misthalin/varrock/handlers/BennyNPC.kt | 39 +++ .../varrock/handlers/BrassKeyDoorPlugin.java | 43 --- .../handlers/ChampionsArenaPlugin.java | 37 --- .../varrock/handlers/GuidorDoorPlugin.java | 30 -- .../varrock/handlers/MuseumGatePlugin.java | 36 -- .../handlers/MuseumInteractionListener.kt | 125 +++++++ .../handlers/MuseumInterfaceListener.kt | 91 +++++ .../varrock/handlers/MuseumMapArea.kt | 29 ++ .../varrock/handlers/VarrockBrokenCart.java | 28 -- .../handlers/VarrockCensusInterface.kt | 27 ++ .../handlers/VarrockInteractionListener.kt | 91 +++++ .../varrock/handlers/VarrockNodePlugin.java | 313 ------------------ .../quest/demonslayer/DemonSlayerPlugin.java | 20 -- .../dragonslayer/DragonSlayerPlugin.java | 17 - .../global/action/ClimbActionHandler.java | 2 + 26 files changed, 612 insertions(+), 808 deletions(-) delete mode 100644 Server/src/main/content/global/handlers/scenery/DoogleLeafPlugin.java create mode 100644 Server/src/main/content/region/misthalin/varrock/dialogue/KnockAtBankDoor.kt delete mode 100644 Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardDialogue.java delete mode 100644 Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardVarrockDialogue.java create mode 100644 Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.java create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.kt delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/BrassKeyDoorPlugin.java delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/ChampionsArenaPlugin.java delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/GuidorDoorPlugin.java delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/MuseumGatePlugin.java create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/MuseumInteractionListener.kt create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/MuseumInterfaceListener.kt create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/MuseumMapArea.kt delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/VarrockBrokenCart.java create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/VarrockCensusInterface.kt create mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/VarrockInteractionListener.kt delete mode 100644 Server/src/main/content/region/misthalin/varrock/handlers/VarrockNodePlugin.java diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 5eb7c1910..72660d047 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -157,7 +157,7 @@ }, { "npc_id": "47", - "loc_data": "{2821,3170,0,1,1}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3341,3267,0,1,5}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2568,9620,0,1,0}-{2573,9612,0,1,0}-{2579,9631,0,1,0}-{2580,9600,0,1,0}-{2580,9614,0,1,0}-{2580,9620,0,1,0}-{2580,9626,0,1,0}-{2583,9632,0,1,0}-{2584,9625,0,1,0}-{2584,9637,0,1,0}-{2589,9644,0,1,0}-{2590,9601,0,1,0}-{2590,9638,0,1,0}-{2591,9601,0,1,0}-{2591,9621,0,1,0}-{2594,9636,0,1,0}-{2594,9644,0,1,0}-{2597,9604,0,1,0}-{2607,9615,0,1,0}-{2608,9628,0,1,0}-{2614,9651,0,1,0}-{2614,9656,0,1,0}-{2615,9647,0,1,0}-{2615,9661,0,1,0}-{2616,9633,0,1,0}-{2618,9630,0,1,0}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3233,3237,0,1,7}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}-{3001,3202,0,1,5}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{2801,3158,0,1,2}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{3021,3205,0,1,6}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{2531,3325,0,1,3}-{2530,3327,0,1,5}-{2521,3331,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-" + "loc_data": "{2821,3170,0,1,1}-{3341,3267,0,1,5}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2568,9620,0,1,0}-{2573,9612,0,1,0}-{2579,9631,0,1,0}-{2580,9600,0,1,0}-{2580,9614,0,1,0}-{2580,9620,0,1,0}-{2580,9626,0,1,0}-{2583,9632,0,1,0}-{2584,9625,0,1,0}-{2584,9637,0,1,0}-{2589,9644,0,1,0}-{2590,9601,0,1,0}-{2590,9638,0,1,0}-{2591,9601,0,1,0}-{2591,9621,0,1,0}-{2594,9636,0,1,0}-{2594,9644,0,1,0}-{2597,9604,0,1,0}-{2607,9615,0,1,0}-{2608,9628,0,1,0}-{2614,9651,0,1,0}-{2614,9656,0,1,0}-{2615,9647,0,1,0}-{2615,9661,0,1,0}-{2616,9633,0,1,0}-{2618,9630,0,1,0}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3233,3237,0,1,7}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}-{3001,3202,0,1,5}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{2801,3158,0,1,2}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{3021,3205,0,1,6}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{2531,3325,0,1,3}-{2530,3327,0,1,5}-{2521,3331,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-" }, { "npc_id": "48", @@ -9677,19 +9677,27 @@ }, { "npc_id": "5932", - "loc_data": "{3255,3442,0,0,0}-" + "loc_data": "{3253,3445,0,0,6}-" }, { "npc_id": "5933", - "loc_data": "{3254,3443,0,0,0}-" + "loc_data": "{3254,3444,0,0,1}-" }, { "npc_id": "5934", - "loc_data": "{3259,3443,0,0,0}-" + "loc_data": "{3256,3443,0,0,6}-" }, { "npc_id": "5935", - "loc_data": "{3260,3442,0,0,0}-" + "loc_data": "{3257,3442,0,0,1}-" + }, + { + "npc_id": "5936", + "loc_data": "{3266,3445,0,0,6}-" + }, + { + "npc_id": "5937", + "loc_data": "{3267,3444,0,0,1}-" }, { "npc_id": "5938", diff --git a/Server/src/main/content/global/activity/cchallange/ChampionChallengeListener.kt b/Server/src/main/content/global/activity/cchallange/ChampionChallengeListener.kt index 8cea6d806..e1e2cd6c8 100644 --- a/Server/src/main/content/global/activity/cchallange/ChampionChallengeListener.kt +++ b/Server/src/main/content/global/activity/cchallange/ChampionChallengeListener.kt @@ -114,7 +114,6 @@ class ChampionChallengeListener : InteractionListener, MapArea { ) private val PORTCULLIS = Scenery.PORTCULLIS_10553 - private val LADDER = Scenery.LADDER_10554 private val CHAMPION_STATUE_CLOSED = Scenery.CHAMPION_STATUE_10556 private val CHAMPION_STATUE_OPEN = Scenery.CHAMPION_STATUE_10557 private val TRAPDOOR_CLOSED = Scenery.TRAPDOOR_10558 @@ -124,6 +123,13 @@ class ChampionChallengeListener : InteractionListener, MapArea { private val ARENA_ZONE = 12696 override fun defineListeners() { + // Champion's Guild Basement Ladder to Main Floor + addClimbDest(Location(3190, 9758, 0), Location(3190, 3356, 0)) + // Champion Statue Ladder to Arena + addClimbDest(Location(3184, 9758, 0), Location(3182, 9758, 0)) + // Arena Ladder to Champion's Guild Basement + addClimbDest(Location(3183, 9758, 0), Location(3185, 9758, 0)) + on(LARXUS, IntType.NPC, "talk-to") { player, _ -> openDialogue(player, LarxusDialogue(false)) return@on true @@ -134,18 +140,18 @@ class ChampionChallengeListener : InteractionListener, MapArea { return@on true } - on(TRAPDOOR_CLOSED, IntType.SCENERY, "open") { _, node -> - replaceScenery(node.asScenery(), TRAPDOOR_OPEN, 100, node.location) - return@on true - } - onUseWith(IntType.NPC, ChampionScrollsDropHandler.SCROLLS, NPCs.LARXUS_3050) { player, _, _ -> openDialogue(player, LarxusDialogue(true)) return@onUseWith true } + on(TRAPDOOR_CLOSED, IntType.SCENERY, "open") { _, node -> + replaceScenery(node.asScenery(), TRAPDOOR_OPEN, 100, node.location) + return@on true + } + on(TRAPDOOR_OPEN, IntType.SCENERY, "close") { _, node -> - replaceScenery(node.asScenery(), TRAPDOOR_CLOSED, 100, node.location) + replaceScenery(node.asScenery(), TRAPDOOR_CLOSED, -1, node.location) return@on true } @@ -154,15 +160,6 @@ class ChampionChallengeListener : InteractionListener, MapArea { return@on true } - on(LADDER, IntType.SCENERY, "climb-up") { player, _ -> - teleport(player, Location.create(3185, 9758, 0)) - return@on true - } - on(CHAMPION_STATUE_OPEN, IntType.SCENERY, "climb-down") { player, _ -> - teleport(player, Location.create(3182, 9758, 0)) - return@on true - } - on(PORTCULLIS, IntType.SCENERY, "open") { player, node -> if (player.getAttribute("championsarena:start", false) == false) { sendNPCDialogue(player, NPCs.LARXUS_3050, "You need to arrange a challenge with me before you enter the arena.") @@ -229,4 +226,4 @@ class ChampionChallengeListener : InteractionListener, MapArea { ZoneRestriction.RANDOM_EVENTS ) } -} +} \ No newline at end of file diff --git a/Server/src/main/content/global/handlers/scenery/DoogleLeafPlugin.java b/Server/src/main/content/global/handlers/scenery/DoogleLeafPlugin.java deleted file mode 100644 index 99da19d9c..000000000 --- a/Server/src/main/content/global/handlers/scenery/DoogleLeafPlugin.java +++ /dev/null @@ -1,39 +0,0 @@ -package content.global.handlers.scenery; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.item.Item; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the doogle leaf plugin for this object. - * @author 'Vexia - * @version 1.0 - */ -public class DoogleLeafPlugin extends OptionHandler { - - /** - * Represents the leaf item. - */ - private static final Item LEAF = new Item(1573, 1); - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(31155).getHandlers().put("option:pick-leaf", this); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - if (!player.getInventory().add(LEAF)) { - player.getPacketDispatch().sendMessage("You don't have have enough space in your inventory."); - } else { - player.getPacketDispatch().sendMessage("You pick some doogle leaves."); - } - return true; - } - -} diff --git a/Server/src/main/content/global/handlers/scenery/DoorManagingPlugin.java b/Server/src/main/content/global/handlers/scenery/DoorManagingPlugin.java index 295badfd8..b6d18c0fa 100644 --- a/Server/src/main/content/global/handlers/scenery/DoorManagingPlugin.java +++ b/Server/src/main/content/global/handlers/scenery/DoorManagingPlugin.java @@ -11,6 +11,9 @@ import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.plugin.Initializable; import core.plugin.Plugin; +import org.rs09.consts.Sounds; + +import static core.api.ContentAPIKt.*; /** * Plugin used for handling the opening/closing of (double) @@ -39,6 +42,14 @@ public final class DoorManagingPlugin extends OptionHandler { if (name.contains("drawers") || name.contains("wardrobe") || name.contains("cupboard")) { switch(option) { case "open": + if (name.contains("drawers")) { + playAudio(player, Sounds.DRAWER_OPEN_64); + } else if (name.contains("wardrobe")) { + animate(player, 545, false); + playAudio(player, Sounds.WARDROBE_OPEN_96); + } else if (name.contains("cupboard")) { + playAudio(player, Sounds.CUPBOARD_OPEN_58); + } case "go-through": if (object.isActive()) { SceneryBuilder.replace(object, object.transform(object.getId() + 1), 80); @@ -46,6 +57,14 @@ public final class DoorManagingPlugin extends OptionHandler { return true; case "close": case "shut": + if (name.contains("drawers")) { + playAudio(player, Sounds.DRAWER_CLOSE_63); + } else if (name.contains("wardrobe")) { + animate(player, 544, false); + playAudio(player, Sounds.WARDROBE_CLOSE_95); + } else if (name.contains("cupboard")) { + playAudio(player, Sounds.CUPBOARD_CLOSE_57); + } SceneryBuilder.replace(object, object.transform(object.getId() - 1)); return true; } diff --git a/Server/src/main/content/global/handlers/scenery/LadderManagingPlugin.java b/Server/src/main/content/global/handlers/scenery/LadderManagingPlugin.java index 0cb9a6500..9712fe790 100644 --- a/Server/src/main/content/global/handlers/scenery/LadderManagingPlugin.java +++ b/Server/src/main/content/global/handlers/scenery/LadderManagingPlugin.java @@ -23,6 +23,8 @@ public final class LadderManagingPlugin extends OptionHandler { SceneryDefinition.setOptionHandler("climb-up", this); SceneryDefinition.setOptionHandler("climb-down", this); SceneryDefinition.setOptionHandler("climb", this); + SceneryDefinition.setOptionHandler("walk-up", this); + SceneryDefinition.setOptionHandler("walk-down", this); return this; } diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeNodePlugin.java b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeNodePlugin.java index e170abbe7..0a0d61107 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeNodePlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeNodePlugin.java @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.handlers; +import core.api.Container; import core.cache.def.impl.SceneryDefinition; import core.game.node.entity.player.link.diary.DiaryType; import core.game.component.Component; @@ -21,6 +22,9 @@ import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import org.rs09.consts.Items; + +import static core.api.ContentAPIKt.*; /** * Represents the node option handler for lumbridge. @@ -45,6 +49,7 @@ public final class LumbridgeNodePlugin extends OptionHandler { SceneryDefinition.forId(22114).getHandlers().put("option:open", this); SceneryDefinition.forId(29355).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(37655).getHandlers().put("option:view", this); + SceneryDefinition.forId(org.rs09.consts.Scenery.LOGS_36974).getHandlers().put("option:take-axe", this); return this; } @@ -114,8 +119,13 @@ public final class LumbridgeNodePlugin extends OptionHandler { case 37655: player.getInterfaceManager().open(new Component(270)); break; - - + case org.rs09.consts.Scenery.LOGS_36974: + if (!addItem(player, Items.BRONZE_AXE_1351, 1, Container.INVENTORY)) { + sendMessage(player, "You don't have enough inventory space to hold that item."); + } else { + replaceScenery(node.asScenery(), org.rs09.consts.Scenery.LOGS_36975, 300, null); + } + return true; } return true; } diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/KnockAtBankDoor.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/KnockAtBankDoor.kt new file mode 100644 index 000000000..d62ded784 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/KnockAtBankDoor.kt @@ -0,0 +1,59 @@ +package content.region.misthalin.varrock.dialogue + +import core.api.lock +import core.api.queueScript +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.world.map.Location +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.NPCs + +class KnockAtBankDoor : DialogueFile() { + private val femaleBankerNPC = NPC(NPCs.BANKER_45) + private val maleBankerNPC = NPC(NPCs.BANKER_44) + private val femaleBankerDoorLoc = Location(3182, 3434, 0) + + override fun handle(componentID: Int, buttonID: Int) { + npc = if (player!!.location == femaleBankerDoorLoc) femaleBankerNPC else maleBankerNPC + + when (stage) { + START_DIALOGUE -> { + player!!.dialogueInterpreter.sendPlainMessage( + true, "Knock knock..." + ).also { + lock(player!!, 3) + queueScript(player!!, 3) { + npcl(FacialExpression.NEUTRAL, "Who's there?") + stage++ + return@queueScript true + } + } + } + + 1 -> showTopics( + Topic("I'm ${player!!.username}. Please let me in.", 10), + Topic("Boo.", 20), + Topic("Kanga.", 30), + Topic("Thank.", 40), + Topic("Doctor.", 50) + ) + 10 -> npcl("No. Staff only beyond this point. You can't come in here.").also { stage = END_DIALOGUE } + 20 -> npcl("Boo who?").also { stage++ } + 21 -> playerl("There's no need to cry!").also { stage++ } + 22 -> npcl(FacialExpression.FURIOUS, "What? I'm not... oh, just go away!").also { stage = END_DIALOGUE } + 30 -> npcl("Kanga who?").also { stage++ } + 31 -> playerl("No, 'kangaroo'.").also { stage++ } + 32 -> npcl(FacialExpression.FURIOUS, "Stop messing about and go away!").also { stage = END_DIALOGUE } + 40 -> npcl("Thank who?").also { stage++ } + 41 -> playerl("You're welcome!").also { stage++ } + 42 -> npcl(FacialExpression.FURIOUS, "Stop it!").also { stage = END_DIALOGUE } + 50 -> npcl( + FacialExpression.FURIOUS, + "Doctor. wh.. hang on, I'm not falling for that one again! Go away." + ).also { stage = END_DIALOGUE } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardDialogue.java deleted file mode 100644 index b988a0eb7..000000000 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardDialogue.java +++ /dev/null @@ -1,88 +0,0 @@ -package content.region.misthalin.varrock.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.global.action.DoorActionHandler; -import core.game.node.entity.player.Player; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.game.world.map.RegionManager; - -/** - * Represents the museum guard dialogue. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class MuseumGuardDialogue extends DialoguePlugin { - - /** - * Represents the gate location. - */ - private static final Location LOCATION = new Location(3261, 3446, 0); - - /** - * Constructs a new {@code MuseumGuardDialogue} {@code Object}. - */ - public MuseumGuardDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code MuseumGuardDialogue} {@code Object}. - * @param player the player. - */ - public MuseumGuardDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new MuseumGuardDialogue(player); - } - - @Override - public boolean open(Object... args) { - interpreter.sendDialogues(5941, FacialExpression.HALF_GUILTY, "Welcome! Would you like to go into the Dig Site", "archaeology cleaning area?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Select an Option", "Yes, I'll go in!", "No thanks, I'll take a look around out there."); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yes, I'll go in!"); - stage = 20; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No thanks, I'll take a look around out there."); - stage = 3; - break; - } - break; - case 3: - end(); - break; - case 20: - end(); - DoorActionHandler.handleAutowalkDoor(player, RegionManager.getObject(LOCATION)); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 5941 }; - } - -} diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardVarrockDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardVarrockDialogue.java deleted file mode 100644 index 9bfee30fa..000000000 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardVarrockDialogue.java +++ /dev/null @@ -1,69 +0,0 @@ -package content.region.misthalin.varrock.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Handles the MuseumGuardVarrockDialogue dialogue. - * @author 'Vexia - */ -@Initializable -public class MuseumGuardVarrockDialogue extends DialoguePlugin { - - public MuseumGuardVarrockDialogue() { - - } - - public MuseumGuardVarrockDialogue(Player player) { - super(player); - } - - @Override - public int[] getIds() { - return new int[] { 5943 }; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - - switch (stage) { - case 0: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yes, how do I get in?"); - stage = 2; - break; - case 2: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, the main entrance is 'round the front. Just head", "west then north slightly, you can't miss it!"); - stage = 3; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What about these doors?"); - stage = 4; - break; - case 4: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "They're primarily for the workmen bringing finds from the", "Dig Site, but you can go through if you want."); - stage = 5; - break; - case 5: - end(); - break; - } - - return true; - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new MuseumGuardVarrockDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hello there. Come to see the new museum?"); - stage = 0; - return true; - } -} diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt new file mode 100644 index 000000000..332ee4407 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt @@ -0,0 +1,89 @@ +package content.region.misthalin.varrock.dialogue + +import content.region.misthalin.varrock.handlers.MuseumInteractionListener.Companion.handleMuseumDoor +import core.api.forceWalk +import core.api.getScenery +import core.api.isQuestComplete +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.NPCs + +@Initializable +class DoorGuardDialogue(player: Player? = null) : DialoguePlugin(player) { + override fun open(vararg args: Any?): Boolean { + npcl(FacialExpression.NEUTRAL, "Hello there. Come to see the new museum?").also { stage = START_DIALOGUE } + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when (stage) { + START_DIALOGUE -> playerl(FacialExpression.NEUTRAL, "Yes, how do I get in?").also { stage++ } + 1 -> npcl(FacialExpression.NEUTRAL, "Well, the main entrance is 'round the front. Just head west then north slightly, you can't miss it!").also { stage++ } + 2 -> playerl(FacialExpression.NEUTRAL, "What about these doors?").also { stage++ } + 3 -> { + if (isQuestComplete(player, "The Dig Site")) { + npcl(FacialExpression.NEUTRAL, "They're primarily for the workmen bringing finds from the Dig Site, but you can go through if you want.").also { stage++ } + } else { + npcl(FacialExpression.NEUTRAL, "They're for the workmen bringing finds from the Dig Site; sorry, but you can't go through.").also { stage = END_DIALOGUE } + } + } + 4 -> playerl(FacialExpression.NEUTRAL, "Okay, thanks.").also { stage++ } + 5 -> { + end() + handleMuseumDoor(player, getScenery(3264, 3441, 0)) + } + } + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return DoorGuardDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MUSEUM_GUARD_5943) + } +} + +@Initializable +class GateGuardDialogue(player: Player? = null) : DialoguePlugin(player) { + override fun open(vararg args: Any?): Boolean { + // Shows the player walking to this spot first https://www.youtube.com/watch?v=t-oeY3a-ZSA&t=53s + if (player.location != Location(3261, 3447)) forceWalk(player, Location(3261, 3447), "smart") + + if (isQuestComplete(player, "The Dig Site")) { + npcl(FacialExpression.NEUTRAL, "Welcome! Would you like to go into the Dig Site archaeology cleaning area?").also { stage = START_DIALOGUE } + } else { + npcl(FacialExpression.NEUTRAL, "You're not permitted in this area.").also { stage = END_DIALOGUE } + } + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when (stage) { + START_DIALOGUE -> showTopics( + Topic("Yes, I'll go in!", 1, true), + Topic("No thanks, I'll take a look around out here.", END_DIALOGUE, true) + ) + 1 -> { + end() + handleMuseumDoor(player, getScenery(3261, 3446, 0)) + } + } + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return GateGuardDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MUSEUM_GUARD_5941) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.java b/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.java deleted file mode 100644 index 0ada0d65e..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.java +++ /dev/null @@ -1,64 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.game.node.entity.npc.AbstractNPC; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.tools.RandomFunction; - -/** - * Represents the representation of the benny npc. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class BennyNPC extends AbstractNPC { - - /** - * The NPC ids of NPCs using this plugin. - */ - private static final int[] ID = { 5925 }; - - /** - * Represents the random messages for benny to display. - */ - private static final String[] MESSAGES = new String[] { "Read all about it!", "Varrock Herald, on sale here!", "Buy your Varrock Herald now!", "Extra! Extra! Read all about it!", "Varrock Herald, now only 50 gold!" }; - - /** - * Constructs a new {@code BennyNPC} {@code Object}. - */ - public BennyNPC() { - super(0, null); - } - - /** - * Constructs a new {@code BennyNPC} {@code Object}. - * @param id the id. - * @param location the location. - */ - private BennyNPC(int id, Location location) { - super(id, location); - } - - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new BennyNPC(id, location); - } - - @Override - public void tick() { - super.tick(); - if (RandomFunction.random(0, 12) == 5) { - sendChat(MESSAGES[RandomFunction.random(MESSAGES.length)]); - } - } - - @Override - public int[] getIds() { - return ID; - } - - @Override - public int getWalkRadius() { - return 6; - } -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.kt b/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.kt new file mode 100644 index 000000000..1e047b4d2 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/BennyNPC.kt @@ -0,0 +1,39 @@ +package content.region.misthalin.varrock.handlers + +import core.game.node.entity.npc.AbstractNPC +import core.game.world.map.Location +import core.plugin.Initializable +import core.tools.RandomFunction +import org.rs09.consts.NPCs + +@Initializable +class BennyNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) { + override fun construct(id: Int, location: Location?, vararg objects: Any?): AbstractNPC { + return BennyNPC(id, location) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.BENNY_5925) + } + + override fun handleTickActions() { + super.handleTickActions() + if (RandomFunction.roll(12)) { + core.api.sendChat(this, messages.random()) + } + } + + override fun getWalkRadius(): Int { + return 6 + } + + companion object { + private val messages = arrayOf( + "Read all about it!", + "Varrock Herald, on sale here!", + "Buy your Varrock Herald now!", + "Extra! Extra! Read all about it!", + "Varrock Herald, now only 50 gold!" + ) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/BrassKeyDoorPlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/BrassKeyDoorPlugin.java deleted file mode 100644 index 0e74482b9..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/BrassKeyDoorPlugin.java +++ /dev/null @@ -1,43 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.global.action.DoorActionHandler; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.scenery.Scenery; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the plugin used to handle the brass key door plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class BrassKeyDoorPlugin extends OptionHandler { - - @Override - public boolean handle(Player player, Node node, String option) { - if (player.getInventory().contains(983, 1)) { - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - } else { - player.getPacketDispatch().sendMessage("This door is locked."); - return true; - } - return true; - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(1804).getHandlers().put("option:open", this); - return this; - } - - @Override - public Location getDestination(Node node, Node n) { - return DoorActionHandler.getDestination(((Player) node), ((Scenery) n)); - } - -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/ChampionsArenaPlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/ChampionsArenaPlugin.java deleted file mode 100644 index 7539754d3..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/ChampionsArenaPlugin.java +++ /dev/null @@ -1,37 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.scenery.Scenery; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the champions arena plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class ChampionsArenaPlugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(10556).getHandlers().put("option:open", this); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - int id = node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); - switch (id) { - case 10556: - player.getDialogueInterpreter().open(3050, true, true); - break; - } - return true; - } - -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/GuidorDoorPlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/GuidorDoorPlugin.java deleted file mode 100644 index fa4da00a0..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/GuidorDoorPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the guidor door plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class GuidorDoorPlugin extends OptionHandler { - - @Override - public boolean handle(Player player, Node node, String option) { - player.getDialogueInterpreter().open(342, true, true); - return true; - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(2032).getHandlers().put("option:open", this); - return this; - } - -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/MuseumGatePlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumGatePlugin.java deleted file mode 100644 index 1ce507bb3..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/MuseumGatePlugin.java +++ /dev/null @@ -1,36 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.global.action.DoorActionHandler; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.scenery.Scenery; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the plugin used for the museum gate plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class MuseumGatePlugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(24536).getHandlers().put("option:open", this); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - if (player.getLocation().getY() >= 3447) { - player.getDialogueInterpreter().open(5941); - } else { - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - return true; - } - return true; - } -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInteractionListener.kt b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInteractionListener.kt new file mode 100644 index 000000000..f72eed5d1 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInteractionListener.kt @@ -0,0 +1,125 @@ +package content.region.misthalin.varrock.handlers + +import core.api.* +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import org.rs09.consts.Components +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class MuseumInteractionListener : InteractionListener { + override fun defineListeners() { + // Basement Stairs + addClimbDest(Location(3255, 3451, 0), Location(1759, 4958, 0)) + addClimbDest(Location(1758, 4959, 0), Location(3258, 3452, 0)) + + on(mapObject, IntType.SCENERY, "look-at", "take") { player, node -> + if (getUsedOption(player) == "take") { + if (!addItem(player, Items.MUSEUM_MAP_11184)) { + sendMessage(player, "You don't have enough space in your inventory.") + } + } else { + when (node.id) { + Scenery.MAP_24390 -> setAttribute(player, "iface:527:floor", "main") + Scenery.MAP_24391 -> setAttribute(player, "iface:527:floor", "second") + Scenery.MAP_24392 -> setAttribute(player, "iface:527:floor", "top") + } + openInterface(player, Components.VM_MUSEUM_MAP_527) + } + return@on true + } + + on(Items.MUSEUM_MAP_11184, IntType.ITEM, "look-at") { player, node -> + openInterface(player, Components.VM_MUSEUM_MAP_527) + return@on true + } + + on(Scenery.INFORMATION_BOOTH_24452, IntType.SCENERY, "look-at") { player, node -> + // TODO: I cannot find anything that shows what this does in 2009. + sendMessage(player, "Nothing interesting happens.") + return@on true + } + + on(doorsToDigsite, IntType.SCENERY, "open") { player, node -> + if (node.id == Scenery.GATE_24536) { + if (player.location.y <= 3446) { + handleMuseumDoor(player, node.asScenery()) + } else { + openDialogue(player, NPCs.MUSEUM_GUARD_5941) + } + return@on true + } else { + if (player.location.y >= 3442) { + handleMuseumDoor(player, node.asScenery()) + } else { + openDialogue(player, NPCs.MUSEUM_GUARD_5943) + } + } + return@on true + } + + on(Scenery.TOOLS_24535, IntType.SCENERY, "take") { player, node -> + sendDialogueOptions( + player, + "Which tool would you like?", + "Trowel", + "Rock pick", + "Specimen brush", + "Leather gloves", + "Leather boots" + ) + addDialogueAction(player) { _, button -> + val item = when (button) { + 2 -> Items.TROWEL_676 + 3 -> Items.ROCK_PICK_675 + 4 -> Items.SPECIMEN_BRUSH_670 + 5 -> Items.LEATHER_GLOVES_1059 + 6 -> Items.LEATHER_BOOTS_1061 + else -> return@addDialogueAction + } + val name = item.asItem().name.lowercase() + val word = if (name.startsWith("leather")) "pair of " else "" + + if (!addItem(player, item)) { + sendMessage(player, "You don't have enough space in your inventory.") + } else { + sendItemDialogue(player, item, "You take a $word$name from the rack.") + } + } + return@on true + } + + on(naturalHistoryPlaques, IntType.SCENERY, "study") { player, node -> + openInterface(player, 533) + return@on true + } + } + + companion object { + private val doorsToDigsite = intArrayOf(Scenery.GATE_24536, Scenery.DOOR_24565, Scenery.DOOR_24567) + private val mapObject = intArrayOf(Scenery.MAP_24390, Scenery.MAP_24391, Scenery.MAP_24392) + private val naturalHistoryPlaques = intArrayOf( + Scenery.PLAQUE_24605, Scenery.PLAQUE_24606, Scenery.PLAQUE_24607, Scenery.PLAQUE_24608, + Scenery.PLAQUE_24609, Scenery.PLAQUE_24610, Scenery.PLAQUE_24611, Scenery.PLAQUE_24612, + Scenery.PLAQUE_24613, Scenery.PLAQUE_24614, Scenery.PLAQUE_24615, Scenery.PLAQUE_24616, + Scenery.PLAQUE_24617, Scenery.PLAQUE_24618 + ) + + fun handleMuseumDoor(player: Player, door: core.game.node.scenery.Scenery?) { + val npc = if (door?.id == Scenery.GATE_24536) findLocalNPC(player, NPCs.MUSEUM_GUARD_5941) else findLocalNPC(player, NPCs.MUSEUM_GUARD_5943) + val animation = if (DoorActionHandler.getEndLocation(player, door).y > player.location.y) Animation(6391) else Animation(6392) + + if (npc != null) { + animate(npc, animation) + queueScript(player, animationDuration(animation)) { DoorActionHandler.handleAutowalkDoor(player, door) } + } else { + DoorActionHandler.handleAutowalkDoor(player, door) + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInterfaceListener.kt b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInterfaceListener.kt new file mode 100644 index 000000000..e31f4cefe --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumInterfaceListener.kt @@ -0,0 +1,91 @@ +package content.region.misthalin.varrock.handlers + +import core.api.* +import core.game.interaction.InterfaceListener +import core.game.node.entity.player.Player +import org.rs09.consts.Components +import org.rs09.consts.NPCs +import org.rs09.consts.Sounds + +class MuseumInterfaceListener : InterfaceListener { + override fun defineInterfaceListeners() { + onOpen(Components.VM_MUSEUM_MAP_527) { player, _ -> + showMapFloor(player, getAttribute(player, "iface:527:floor", "main")) + removeAttribute(player, "iface:527:floor") + return@onOpen true + } + + on(Components.VM_MUSEUM_MAP_527) { player, _, _, buttonID, _, _ -> + showMapFloor(player, when (buttonID) { + in mapButtonsToBasement -> "basement" + in mapButtonsToMainFloor -> "main" + in mapButtonsToSecondFloor -> "second" + in mapButtonsToTopFloor -> "top" + else -> return@on true + }) + return@on true + } + + onOpen(NATURAL_HISTORY_EXAM_533) { player, component -> + // The model for each display is confusing as hell. Some are objects and some are NPCs. + val model = getScenery(1763, 4937, 0)?.definition?.modelIds?.first() + player.packetDispatch.sendModelOnInterface(model!!, component.id, 3, 0) + + // Showing this child makes child 28 - 31 visible. + setComponentVisibility(player, component.id, 27, false) + + // The case number to display. + setInterfaceText(player, "1", component.id, 25) + + // The question text. + setInterfaceText(player, "When will the Natural History Quiz be implemented?", component.id, 28) + + // The choices. + setInterfaceText(player, "Never.", component.id, 29) + setInterfaceText(player, "In 2 days.", component.id, 30) + setInterfaceText(player, "After Barbarian Assault.", component.id, 31) + return@onOpen true + } + + on(NATURAL_HISTORY_EXAM_533) { player, component, opcode, buttonID, slot, itemID -> + if (buttonID in 29..31) { + closeInterface(player) + setVarbit(player, 3637, 1, false) + playAudio(player, Sounds.VM_GAIN_KUDOS_3653) + sendNPCDialogue(player, NPCs.ORLANDO_SMITH_5965, "Nice job, mate. That looks about right.") + } + return@on true + } + } + companion object { + private const val NATURAL_HISTORY_EXAM_533 = 533 + + private val mapButtonsToBasement = intArrayOf(41, 186) + private val mapButtonsToMainFloor = intArrayOf(117, 120, 187, 188) + private val mapButtonsToSecondFloor = intArrayOf(42, 44, 152, 153) + private val mapButtonsToTopFloor = intArrayOf(42, 44, 118, 119) + + private fun showMapFloor(player: Player, floor: String) { + when (floor) { + "basement" -> { + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 2, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 7, false) + } + "main" -> { + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 3, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 7, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 2, false) + } + "second" -> { + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 2, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 5, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 3, false) + } + "top" -> { + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 3, true) + setComponentVisibility(player, Components.VM_MUSEUM_MAP_527, 5, false) + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/MuseumMapArea.kt b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumMapArea.kt new file mode 100644 index 000000000..cdb5dcb96 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/MuseumMapArea.kt @@ -0,0 +1,29 @@ +package content.region.misthalin.varrock.handlers + +import core.api.MapArea +import core.api.closeOverlay +import core.api.openOverlay +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.world.map.zone.ZoneBorders +import org.rs09.consts.Components + +class MuseumMapArea : MapArea { + override fun defineAreaBorders(): Array { + val vmArea = ZoneBorders(3253, 3442, 3267, 3455) + val vmBasementArea = ZoneBorders(1730, 4932, 1788, 4988) + return arrayOf(vmArea, vmBasementArea) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + openOverlay(entity.asPlayer(), Components.VM_KUDOS_532) + } + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + closeOverlay(entity.asPlayer()) + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockBrokenCart.java b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockBrokenCart.java deleted file mode 100644 index 22d6b9e7e..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockBrokenCart.java +++ /dev/null @@ -1,28 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * @author 'Vexia - */ -@Initializable -public class VarrockBrokenCart extends OptionHandler { - - @Override - public boolean handle(Player player, Node node, String option) { - player.getDialogueInterpreter().open(70099, "You search the cart but are surprised to find very little there. It's a", "little odd for a travelling trader not to have anything to trade."); - return true; - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(23055).getHandlers().put("option:search", this); - return this; - } - -} diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockCensusInterface.kt b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockCensusInterface.kt new file mode 100644 index 000000000..6cb95f014 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockCensusInterface.kt @@ -0,0 +1,27 @@ +package content.region.misthalin.varrock.handlers + +import core.api.getVarbit +import core.api.setVarbit +import core.game.interaction.InterfaceListener + +class VarrockCensusInterface : InterfaceListener { + override fun defineInterfaceListeners() { + on(INTERFACE_ID) { player, _, _, buttonID, _, _ -> + when (buttonID) { + 2 -> setVarbit(player, VARBIT_ID, getVarbit(player, VARBIT_ID).plus(1)) + 3 -> setVarbit(player, VARBIT_ID, getVarbit(player, VARBIT_ID).minus(1)) + else -> return@on true + } + return@on true + } + + onClose(INTERFACE_ID) { player, _ -> + setVarbit(player, VARBIT_ID, 0) + return@onClose true + } + } + companion object { + const val INTERFACE_ID = 794 + const val VARBIT_ID = 5390 + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockInteractionListener.kt b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockInteractionListener.kt new file mode 100644 index 000000000..1610dafb6 --- /dev/null +++ b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockInteractionListener.kt @@ -0,0 +1,91 @@ +package content.region.misthalin.varrock.handlers + +import content.region.misthalin.varrock.dialogue.KnockAtBankDoor +import core.api.* +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.world.map.Location +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery +import org.rs09.consts.Sounds + +class VarrockInteractionListener : InteractionListener { + override fun defineListeners() { + // Varrock Sewer Manhole + on(VARROCK_MANHOLE, IntType.SCENERY, "open", "close") { player, node -> + if (getUsedOption(player) == "open") { + playAudio(player, Sounds.MANHOLE_OPEN_75) + replaceScenery(node.asScenery(), Scenery.VARROCK_MANHOLE_OPEN_882, 100) + } else { + playAudio(player, Sounds.MANHOLE_CLOSE_74) + replaceScenery(node.asScenery(), Scenery.VARROCK_MANHOLE_CLOSED_881, -1) + } + return@on true + } + + // Phoenix Gang Hideout Plaque + on(Scenery.PLAQUE_23636, IntType.SCENERY, "read") { player, _ -> + openInterface(player, VTAM_IFACE) + return@on true + } + + // Varrock Census in the palace Library + on(Scenery.VARROCK_CENSUS_37209, IntType.SCENERY, "read") { player, _ -> + sendPlayerDialogue(player, "Hmm. The Varrock Census - year 160. That means it's nine years out of date.") + addDialogueAction(player) { _, buttonID -> + if (buttonID == 6) { + openInterface(player, VARROCK_CENSUS_IFACE) + } + } + return@on true + } + + // Broken Cart next to Rat Burgiss + on(Scenery.BROKEN_CART_23055, IntType.SCENERY, "search") { player, node -> + sendDialogue(player, "You search the cart but are surprised to find very little there. " + + "It's a little odd for a travelling trader not to have anything to trade.") + return@on true + } + + on(openOptionNodes, IntType.SCENERY, "open") { player, node -> + when (node.id) { + // Guidor's Bedroom Door + Scenery.BEDROOM_DOOR_2032 -> { + openDialogue(player, NPCs.GUIDORS_WIFE_342, true, true) + } + + // Guidor's Drawers + Scenery.DRAWERS_17466 -> { + sendMessage(player, "The drawers are locked shut.") + } + + // Brass Key Door to Edgeville Dungeon + Scenery.DOOR_1804 -> { + if (inInventory(player, Items.BRASS_KEY_983)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendMessage(player, "This door is locked.") + } + } + } + return@on true + } + + // Varrock West Bank Door + on(Scenery.DOOR_24389, IntType.SCENERY, "knock-at") { player, node -> + openDialogue(player, KnockAtBankDoor()) + return@on true + } + + // TODO: Cooking Guild + // TODO: Fix Achievements + } + companion object { + private val VARROCK_MANHOLE = intArrayOf(Scenery.VARROCK_MANHOLE_CLOSED_881, Scenery.VARROCK_MANHOLE_OPEN_882) + private val openOptionNodes = intArrayOf(Scenery.BEDROOM_DOOR_2032, Scenery.DRAWERS_17466, Scenery.DOOR_1804) + private const val VTAM_IFACE = 531 + private const val VARROCK_CENSUS_IFACE = 794 + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockNodePlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/VarrockNodePlugin.java deleted file mode 100644 index eb2307284..000000000 --- a/Server/src/main/content/region/misthalin/varrock/handlers/VarrockNodePlugin.java +++ /dev/null @@ -1,313 +0,0 @@ -package content.region.misthalin.varrock.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.component.Component; -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.global.action.ClimbActionHandler; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.item.Item; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; -import core.game.world.map.Location; -import core.game.world.update.flag.context.Animation; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the plugin used to handle node interactions in varrock. - * - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class VarrockNodePlugin extends OptionHandler { - - /** - * Represents the bronze axe item. - */ - private static final Item BRONZE_AXE = new Item(1351); - - /** - * Represents the spade item. - */ - private static final Item SPADE = new Item(952); - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(24357).getHandlers().put("option:climb-up", this); - SceneryDefinition.forId(24359).getHandlers().put("option:climb-down", this); - SceneryDefinition.forId(5581).getHandlers().put("option:take-axe", this); - SceneryDefinition.forId(36974).getHandlers().put("option:take-axe", this); - SceneryDefinition.forId(24427).getHandlers().put("option:walk-up", this); - SceneryDefinition.forId(24428).getHandlers().put("option:walk-down", this); - SceneryDefinition.forId(1749).getHandlers().put("option:climb-down", this); - SceneryDefinition.forId(23636).getHandlers().put("option:read", this); - SceneryDefinition.forId(24389).getHandlers().put("option:knock-at", this); - SceneryDefinition.forId(9662).getHandlers().put("option:take", this); - SceneryDefinition.forId(29534).getHandlers().put("option:enter", this); - SceneryDefinition.forId(17985).getHandlers().put("option:climb-down", this); - SceneryDefinition.forId(24366).getHandlers().put("option:climb-up", this); - return this; - } - - @Override - public boolean handle(final Player player, Node node, String option) { - final int id = node instanceof Scenery ? ((Scenery) node).getId() : ((Item) node).getId(); - switch (id) { - case 24366: - ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, new Location(3237, 3459)); - return true; - case 29534: - player.getDialogueInterpreter().open(543543); - return true; - case 17985: - ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, new Location(3204, 9910), "You enter the murky sewers."); - return true; - case 24389: - player.getDialogueInterpreter().open(KnockatDoorDialogue.ID, player.getLocation().getX() == 3182 ? 45 : 44); - break; - case 28094: - player.getDialogueInterpreter().sendDialogues(player, FacialExpression.THINKING, "I don't think I should go inside."); - break; - case 23636: - player.getInterfaceManager().open(new Component(531)); - break; - case 1749: - if (player.getLocation().getZ() == 2 && player.getLocation().getDistance(new Location(3096, 3433, 2)) < 4) { - ClimbActionHandler.climb(player, new Animation(827), Location.create(3097, 3432, 1)); - return true; - } else if (player.getLocation().getZ() == 1 && player.getLocation().getDistance(new Location(3095, 3433, 1)) < 4) { - ClimbActionHandler.climb(player, new Animation(827), Location.create(3096, 3432, 0)); - return true; - } - ClimbActionHandler.climbLadder(player, (Scenery) node, option); - return true; - case 5581: - case 36974: - if (!player.getInventory().add(BRONZE_AXE)) { - player.getPacketDispatch().sendMessage("You don't have enough inventory space."); - return true; - } - SceneryBuilder.replace(((Scenery) node), ((Scenery) node).transform(5582), 5000); - break; - case 24357: - if (player.getLocation().getDistance(Location.create(3188, 3358, 0)) < 3) { - ClimbActionHandler.climb(player, new Animation(828), Location.create(3188, 3354, 1)); - return true; - } - if (((Scenery) node).getLocation().equals(new Location(3156, 3435, 0))) { - ClimbActionHandler.climb(player, new Animation(828), Location.create(3155, 3435, 1)); - return true; - } - ClimbActionHandler.climbLadder(player, (Scenery) node, option); - return true; - - case 24359: - if (player.getLocation().getDistance(Location.create(3231, 3382, 1)) < 3) { - ClimbActionHandler.climb(player, null, Location.create(3231, 3386, 0)); - return true; - } - ClimbActionHandler.climbLadder(player, (Scenery) node, option); - return true; - - case 24427: //varrock museum stairs that lead upstairs - if (player.getLocation().getDistance(Location.create(1758, 4959, 0)) < 3) { - ClimbActionHandler.climb(player, new Animation(-1), Location.create(3258, 3452, 0)); - return true; - } - return true; - - case 24428: //varrock museum stairs that lead downstairs - if (player.getLocation().getDistance(Location.create(3255, 3451, 0)) < 4) { - ClimbActionHandler.climb(player, new Animation(-1), Location.create(1759, 4958, 0)); - return true; - } - return true; - case 9662: - if (!player.getInventory().hasSpaceFor(SPADE)) { - player.getPacketDispatch().sendMessage("Not enough inventory space."); - return true; - } - player.getInventory().add(SPADE); - SceneryBuilder.replace((Scenery) node, ((Scenery) node).transform(0), 250); - return true; - } - return true; - } - - @Override - public boolean isWalk() { - return false; - } - - @Override - public boolean isWalk(final Player player, final Node node) { - return !(node instanceof Item); - } - - /** - * Represents the dialogue used for the knocking at a door in varrock bank. - * - * @author 'Vexia - * @version 1.0 - */ - public final class KnockatDoorDialogue extends DialoguePlugin { - - /** - * Represents the id of this dialogue. - */ - private static final int ID = 903042893; - - /** - * Represents the id to use. - */ - private int npcId; - - /** - * Constructs a new {@code KnockatDoorDialogue} {@code Object}. - */ - public KnockatDoorDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code KnockatDoorDialogue} {@code Object}. - * - * @param player the player. - */ - public KnockatDoorDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new KnockatDoorDialogue(player); - } - - @Override - public boolean open(Object... args) { - npcId = (int) args[0]; - player("I don't think I'm ever going to be allowed in there."); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - player.lock(3); - interpreter.sendPlainMessage(true, "Knock knock..."); - GameWorld.getPulser().submit(new Pulse(3, player) { - @Override - public boolean pulse() { - interpreter.sendDialogues(npcId, null, "Who's there?"); - stage = 1; - return true; - } - }); - break; - case 1: - options("I'm " + player.getUsername() + ". Please let me in.", "Boo.", "Kanga.", "Thank.", "Doctor."); - stage = 2; - break; - case 2: - switch (buttonId) { - case 1: - player("I'm " + player.getUsername() + ". Please let me in."); - stage = 10; - break; - case 2: - player("Boo."); - stage = 20; - break; - case 3: - player("Kanga."); - stage = 30; - break; - case 4: - player("Thank."); - stage = 40; - break; - case 5: - player("Doctor."); - stage = 50; - break; - } - break; - case 10: - interpreter.sendDialogues(npcId, null, "No. Staff only beyond this point.", "You can't come in here."); - stage = 11; - break; - case 11: - end(); - break; - case 20: - interpreter.sendDialogues(npcId, null, "Boo who?"); - stage = 21; - break; - case 21: - player("There's no need to cry!"); - stage = 22; - break; - case 22: - interpreter.sendDialogues(npcId, FacialExpression.FURIOUS, "What? I'm not... oh, just go away!"); - stage = 23; - break; - case 23: - end(); - break; - case 30: - interpreter.sendDialogues(npcId, null, "Kanga who?"); - stage = 31; - break; - case 31: - player("No, 'kangaroo'."); - stage = 32; - break; - case 32: - interpreter.sendDialogues(npcId, FacialExpression.FURIOUS, "Stop messing about and go away!"); - stage = 33; - break; - case 33: - end(); - break; - case 40: - interpreter.sendDialogues(npcId, null, "Thank who?"); - stage = 41; - break; - case 41: - player("You're welcome!"); - stage = 42; - break; - case 42: - interpreter.sendDialogues(npcId, FacialExpression.FURIOUS, "Stop it!"); - stage = 43; - break; - case 43: - end(); - break; - case 50: - interpreter.sendDialogues(npcId, FacialExpression.FURIOUS, "Doctor. wh.. hang on, I'm not falling for that one again!", "Go away."); - stage = 51; - break; - case 51: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{903042893}; - } - - } -} diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java index 1a051a67b..b31d4a22b 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java @@ -37,9 +37,6 @@ public final class DemonSlayerPlugin extends OptionHandler { @Override public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(881).getHandlers().put("option:open", this); - SceneryDefinition.forId(882).getHandlers().put("option:close", this); - SceneryDefinition.forId(882).getHandlers().put("option:climb-down", this); SceneryDefinition.forId(DRAIN_ID).getHandlers().put("option:search", this); SceneryDefinition.forId(17429).getHandlers().put("option:take", this); NPCDefinition.forId(DemonSlayerCutscene.DELRITH).getHandlers().put("option:attack", this); @@ -71,23 +68,6 @@ public final class DemonSlayerPlugin extends OptionHandler { player.sendMessage("You search the castle drain and find nothing of value."); } return true; - case 881: - SceneryBuilder.replace(((Scenery) node), ((Scenery) node).transform(882)); - break; - case 882: - switch (option) { - case "climb-down": - if (node.getLocation().equals(new Location(3237, 3458, 0))) { - ClimbActionHandler.climb(player, new Animation(828), SEWER_LOCATION); - } else { - ClimbActionHandler.climbLadder(player, (Scenery) node, option); - } - break; - case "close": - SceneryBuilder.replace(((Scenery) node), ((Scenery) node).transform(881)); - break; - } - break; case 17429: if (quest.getStage(player) == 20 && player.getInventory().add(DemonSlayer.FIRST_KEY)) { setVarp(player, 222, 4757762, true); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java index 85af8e2ed..4adfe8537 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java @@ -101,10 +101,6 @@ public final class DragonSlayerPlugin extends OptionHandler { SceneryDefinition.forId(25161).getHandlers().put("option:climb-over", this); NPCDefinition.forId(742).getHandlers().put("option:attack", this); NPCDefinition.forId(745).getHandlers().put("option:attack", this); - // guild - SceneryDefinition.forId(24357).getHandlers().put("option:climb-up", this); - SceneryDefinition.forId(10558).getHandlers().put("option:open", this); - SceneryDefinition.forId(10560).getHandlers().put("option:climb-up", this); return this; } @@ -113,12 +109,6 @@ public final class DragonSlayerPlugin extends OptionHandler { final Quest quest = player.getQuestRepository().getQuest("Dragon Slayer"); final int id = node instanceof Item ? ((Item) node).getId() : node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); switch (id) { - case 10560: - ClimbActionHandler.climb(player, new Animation(828), Location.create(3191, 3355, 0)); - break; - case 10558: - ClimbActionHandler.climb(player, new Animation(-1), Location.create(3189, 9758, 0)); - return true; case 1755: if (player.getLocation().withinDistance(Location.create(2939, 9656, 0))) { ClimbActionHandler.climb(player, new Animation(828), Location.create(2939, 3256, 0)); @@ -127,13 +117,6 @@ public final class DragonSlayerPlugin extends OptionHandler { return true; } break; - case 24357: - if (player.getLocation().getDistance(Location.create(3188, 3358, 0)) < 3) { - ClimbActionHandler.climb(player, new Animation(828), Location.create(3188, 3354, 1)); - } else { - ClimbActionHandler.climbLadder(player, (Scenery) node, "climb-up"); - } - break; case 742: if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { player.getPacketDispatch().sendMessage("You have already slain the dragon. Now you just need to return to Oziach for"); diff --git a/Server/src/main/core/game/global/action/ClimbActionHandler.java b/Server/src/main/core/game/global/action/ClimbActionHandler.java index f9042b724..1914c2440 100644 --- a/Server/src/main/core/game/global/action/ClimbActionHandler.java +++ b/Server/src/main/core/game/global/action/ClimbActionHandler.java @@ -77,9 +77,11 @@ public final class ClimbActionHandler { } switch (option) { case "climb-up": + case "walk-up": endLadder = getLadder(startLadder, false); break; case "climb-down": + case "walk-down": if (startLadder.getName().equals("Trapdoor")) { animation = CLIMB_DOWN; } From 218a040f8bab0a963d3589905598c5e0f9e94b38 Mon Sep 17 00:00:00 2001 From: zsrv Date: Mon, 7 Oct 2024 11:15:52 +0000 Subject: [PATCH 027/306] Major farming improvements including (but not limited to): Farming animation corrections Farming message updates and additions Gardeners will chop down fully grown trees for 200 gp Gardeners will give farming advice Compost bin debugging admin command ::finishbins restored (finishes any in-progress compost bins) Compost bin debugging admin command ::resetbins added (resets the player's compost bins to their initial states) Players can no longer pay gardeners to protect diseased or dead farming patches Can no longer water dead patches Weeds will now grow in farming patches as part of the offline catch-up Trees that are not fully grown can now be dug up --- .../global/dialogue/GardenerDialoguePlugin.kt | 253 +++++++++++------- .../global/skill/farming/CompostBin.kt | 13 + .../global/skill/farming/CropHarvester.kt | 15 +- .../skill/farming/DigUpPatchDialogue.kt | 2 +- .../skill/farming/FarmerPayOptionDialogue.kt | 133 ++++++--- .../skill/farming/FarmerPayOptionHandler.kt | 24 +- .../global/skill/farming/FarmingPatch.kt | 6 +- .../global/skill/farming/FarmingState.kt | 43 --- .../global/skill/farming/HealthChecker.kt | 21 +- .../content/global/skill/farming/Patch.kt | 26 +- .../global/skill/farming/PatchRaker.kt | 2 +- .../content/global/skill/farming/Plantable.kt | 142 +++++----- .../skill/farming/ToolLeprechaunInterface.kt | 14 +- .../skill/farming/UseWithPatchHandler.kt | 100 ++++--- .../global/skill/farming/timers/CropGrowth.kt | 22 +- .../woodcutting/WoodcuttingSkillPulse.java | 2 +- .../skill/magic/lunar/LunarListeners.kt | 32 ++- .../skill/summoning/familiar/HydraNPC.java | 2 +- .../main/core/game/dialogue/DialogueFile.kt | 8 +- .../system/command/sets/MiscCommandSet.kt | 18 ++ 20 files changed, 515 insertions(+), 363 deletions(-) delete mode 100644 Server/src/main/content/global/skill/farming/FarmingState.kt diff --git a/Server/src/main/content/global/dialogue/GardenerDialoguePlugin.kt b/Server/src/main/content/global/dialogue/GardenerDialoguePlugin.kt index 3fa655c5d..6c192972c 100644 --- a/Server/src/main/content/global/dialogue/GardenerDialoguePlugin.kt +++ b/Server/src/main/content/global/dialogue/GardenerDialoguePlugin.kt @@ -3,160 +3,227 @@ package content.global.dialogue import content.global.skill.farming.FarmerPayOptionDialogue import content.global.skill.farming.Farmers import content.global.skill.farming.FarmingPatch -import core.game.node.entity.npc.NPC +import content.global.skill.farming.PatchType +import core.api.* +import core.game.dialogue.FacialExpression +import core.game.dialogue.IfTopic +import core.game.dialogue.Topic import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE @Initializable class GardenerDialoguePlugin(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { - override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin { - return GardenerDialoguePlugin(player) - } - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - options("Would you look after my crops for me?","Can you sell me something?") - return true - } - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - 0 -> when(buttonId){ - 1 -> player("Would you look after my crops for me?").also { stage = 10 } - 2 -> player("Can you sell me something?").also { stage = 30 } + val patches = Farmers.forId(npc.id)!!.patches + when (stage) { + // TODO: Can fruit trees be chopped down by the gardener too? + START_DIALOGUE -> { + val patch = patches[0].getPatchFor(player) + showTopics( + IfTopic( + FacialExpression.ASKING, + "Would you chop my tree down for me?", + 1000, + patch.patch.type == PatchType.TREE_PATCH && patch.plantable != null && patch.isGrown() + ), + IfTopic( + FacialExpression.ASKING, + "Would you look after my crops for me?", + 10, + !(patch.patch.type == PatchType.TREE_PATCH && patch.plantable != null && patch.isGrown()) + ), + Topic(FacialExpression.ASKING, "Can you give me any farming advice?", 2000), + Topic(FacialExpression.ASKING, "Can you sell me something?", 30), + Topic(FacialExpression.NEUTRAL, "That's all, thanks.", END_DIALOGUE) + ) } - 10 -> npc("I might. Which one were you thinking of?").also { stage++ } - 11 -> when(npc.id){ - Farmers.ELSTAN.id, Farmers.LYRA.id -> options("The north-western allotment.","The south-eastern allotment.").also { stage = 15 } - Farmers.DANTAERA.id, Farmers.KRAGEN.id -> options("The north allotment.","The south allotment.").also { stage = 15 } - else -> player("Uh, that one.").also { stage++ } + 10 -> { + if (patches.size > 1) { + npc("I might. Which one were you thinking of?").also { stage = 20 } + } else { + openPayGardenerDialogue(player, patches[0]) + } } - 12 -> npc("Oh, right. My bad.").also { stage++ } - 13 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0]) - - 15 -> when(buttonId){ - 1 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0]) - 2 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[1]) + 20 -> when (npc.id) { + Farmers.ELSTAN.id, Farmers.LYRA.id -> showTopics( + Topic(FacialExpression.NEUTRAL, "The north-western allotment.", 21), + Topic(FacialExpression.NEUTRAL, "The south-eastern allotment.", 22) + ) + Farmers.DANTAERA.id, Farmers.KRAGEN.id -> showTopics( + Topic(FacialExpression.NEUTRAL, "The northern allotment.", 21), + Topic(FacialExpression.NEUTRAL, "The southern allotment.", 22) + ) } + 21 -> openPayGardenerDialogue(player, patches[0]) + 22 -> openPayGardenerDialogue(player, patches[1]) - 30 -> npc("That depends on whether I have it to sell.","What is it that you're looking for?").also { stage++ } - 31 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 } - 32 -> when(buttonId){ - 1 -> player("Some plant cure.").also { stage = 100 } - 2 -> player("A bucket of compost.").also { stage = 200 } - 3 -> player("A rake.").also { stage = 300 } - 4 -> options("A watering can.","A gardening trowel.","A seed dibber.","(See previous items)").also { stage++ } - } - 33 -> when(buttonId){ - 1 -> player("A watering can.").also { stage = 400 } - 2 -> player("A gardening trowel.").also { stage = 500 } - 3 -> player("A seed dibber.").also { stage = 600 } - 4 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 } - } + 30 -> npc(FacialExpression.NEUTRAL, "That depends on whether I have it to sell. What is it", "that you're looking for?").also { stage++ } + 31 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Some plant cure.", 100), + Topic(FacialExpression.NEUTRAL, "A bucket of compost.", 200), + Topic(FacialExpression.NEUTRAL, "A rake.", 300), + Topic("(See more items)", 32, true) + ) + 32 -> showTopics( + Topic(FacialExpression.NEUTRAL, "A watering can.", 400), + Topic(FacialExpression.NEUTRAL, "A gardening trowel.", 500), + Topic(FacialExpression.NEUTRAL, "A seed dibber.", 600), + Topic("(See previous items)", 31, true), + Topic(FacialExpression.NEUTRAL, "Forget it.", 40, true) + ) - 100 -> npc("Plant cure, eh? I might have some put aside for myself.","Tell you what, I'll sell you some plant cure","for 25 gp if you like.").also { stage++ } - 101 -> options("Yes, that sounds like a fair price.","No thanks, I can get that much cheaper.").also { stage++ } - 102 -> when(buttonId){ + 40 -> player("Forget it, you don't have anything I need.").also { stage = END_DIALOGUE } + + 100 -> npc("Plant cure, eh? I might have some put aside for myself.", "Tell you what. I'll sell you some plant cure for 25 gp if", "you like.").also { stage++ } + 101 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } + 102 -> when (buttonId) { 1 -> { - player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,25))){ - player.inventory.add(Item(Items.PLANT_CURE_6036)) + player(FacialExpression.HAPPY, "Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } + if (removeItem(player, Item(Items.COINS_995, 25))) { + addItemOrDrop(player, Items.PLANT_CURE_6036) } else { - player.sendMessage("You need 25 gp to pay for that.") + sendMessage(player, "You need 25 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } } - 200 -> npc("A bucket of compost, eh? I might have one spare...","tell you what, I'll sell it to you for 35 gp if you like.").also { stage++ } - 201 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ } - 202 -> when(buttonId){ + 200 -> npc("A bucket of compost, eh? I might have one spare...", "tell you what, I'll sell it to you for 35 gp if you like.").also { stage++ } + 201 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } + 202 -> when (buttonId) { 1 -> { player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,35))){ - player.inventory.add(Item(Items.COMPOST_6032)) + if (removeItem(player, Item(Items.COINS_995, 35))) { + addItemOrDrop(player, Items.COMPOST_6032) } else { - player.sendMessage("You need 35 gp to pay for that.") + sendMessage(player, "You need 35 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } } - 300 -> npc("A rake, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } - 301 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ } - 302 -> when(buttonId){ + 300 -> npc("A rake, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } + 301 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } + 302 -> when (buttonId) { 1 -> { player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,15))){ - player.inventory.add(Item(Items.RAKE_5341)) + if (removeItem(player, Item(Items.COINS_995, 15))) { + addItemOrDrop(player, Items.RAKE_5341) } else { - player.sendMessage("You need 15 gp to pay for that.") + sendMessage(player, "You need 15 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } } - 400 -> npc("A watering can, eh? I might have one spare...","tell you what, I'll sell it to you for 25 gp if you like.").also { stage++ } - 401 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ } + 400 -> npc("A watering can, eh? I might have one spare...", "tell you what, I'll sell it to you for 25 gp if you like.").also { stage++ } + 401 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } 402 -> when(buttonId){ 1 -> { player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,25))){ - player.inventory.add(Item(Items.WATERING_CAN8_5340)) + if (removeItem(player, Item(Items.COINS_995, 25))) { + addItemOrDrop(player, Items.WATERING_CAN8_5340) } else { - player.sendMessage("You need 25 gp to pay for that.") + sendMessage(player, "You need 25 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } } - 500 -> npc("A gardening trowel, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } - 501 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ } - 502 -> when(buttonId){ + 500 -> npc("A gardening trowel, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } + 501 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } + 502 -> when (buttonId) { 1 -> { player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,15))){ - player.inventory.add(Item(Items.GARDENING_TROWEL_5325)) + if (removeItem(player, Item(Items.COINS_995, 15))) { + addItemOrDrop(player, Items.GARDENING_TROWEL_5325) } else { - player.sendMessage("You need 15 gp to pay for that.") + sendMessage(player, "You need 15 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } } - 600 -> npc("A seed dibber, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } - 601 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ } - 602 -> when(buttonId){ + 600 -> npc("A seed dibber, eh? I might have one spare...", "tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ } + 601 -> options("Yes, that sounds like a fair price.", "No thanks, I can get that much cheaper elsewhere.").also { stage++ } + 602 -> when (buttonId) { 1 -> { player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE } - if(player.inventory.remove(Item(995,15))){ - player.inventory.add(Item(Items.SEED_DIBBER_5343)) + if (removeItem(player, Item(Items.COINS_995, 15))) { + addItemOrDrop(player, Items.SEED_DIBBER_5343) } else { - player.sendMessage("You need 15 gp to pay for that.") + sendMessage(player, "You need 15 gp to pay for that.") } } - 2 -> end() + 2 -> player("No thanks, I can get that much cheaper elsewhere.").also { stage = END_DIALOGUE } + } + + // Note: This dialogue changes slightly in April 2009, and significantly in December 2009 + 1000 -> npc(FacialExpression.THINKING, "Why? You look like you could chop it down yourself!").also { stage++ } + 1001 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Yes, you're right - I'll do it myself.", END_DIALOGUE), + Topic(FacialExpression.NEUTRAL, "I can't be bothered - I'd rather pay you to do it.", 1020) + ) + + 1020 -> npc(FacialExpression.NEUTRAL, "Well, it's a lot of hard work - if you pay me 200 GP", "I'll chop it down for you.").also { stage++ } + 1021 -> { + if (inInventory(player, Items.COINS_995, 200)) { + showTopics( + Topic(FacialExpression.NEUTRAL, "Here's 200GP - chop my tree down please.", 1022), + Topic(FacialExpression.NEUTRAL, "I don't want to pay that much, sorry.", END_DIALOGUE) + ) + } else { + player("I don't have that much money on me.").also { stage = END_DIALOGUE } // not authentic + } + } + 1022 -> { + end() + if (removeItem(player, Item(Items.COINS_995, 200))) { + patches[0].getPatchFor(player).clear() + } + } + + 2000 -> { + val advice = arrayOf( + "There are four main Farming areas - Elstan looks after an area south of Falador, Dantaera has one to the north of Catherby, Kragen has one near Ardougne, and Lyra looks after a place in north Morytania.", + "If you want to grow fruit trees you could try a few places: Catherby and Brimhaven have a couple of fruit tree patches, and I hear that the gnomes are big on that sort of thing.", + "Bittercap mushrooms can only be grown in a special patch in Morytania, near the Mort Myre swamp. There the ground is especially dank and suited to growing poisonous fungi.", + "There is a special patch for growing Belladonna - I believe it's somewhere near Draynor Manor, where the ground is a tad 'unblessed'.", + + "Don't just throw away your weeds after you've raked a patch - put them in a compost bin and make some compost.", + "Applying compost to a patch will not only reduce the chance that your crops will get diseased, but you will also grow more crops to harvest.", + "Supercompost is far better than normal compost, but more expensive to make. You need to rot the right type of item; show me an item, and I'll tell you if it's super-compostable or not.", + + "Tree seeds must be grown in a plantpot of soil into a sapling, and then transferred to a tree patch to continue growing to adulthood.", + "You don't have to buy all your plantpots you know, you can make them yourself on a pottery wheel. If you're a good enough ${if (player!!.isMale) "craftsman" else "craftswoman"}, that is.", + "You can fill plantpots with soil from Farming patches, if you have a gardening trowel.", + + "Vegetables, hops and flowers are far more likely to grow healthily if you water them periodically.", + "The only way to cure a bush or tree of disease is to prune away the diseased leaves with a pair of secateurs. For all other crops I would just apply some plant-cure.", + "If you need to be rid of your fruit trees for any reason, all you have to do is chop them down and then dig up the stump.", + + "You can put up to ten potatoes, cabbages or onions in vegetable sacks, although you can't have a mix in the same sack.", + "You can put up to five tomatoes, strawberries, apples, bananas or oranges into a fruit basket, although you can't have a mix in the same basket.", + "If you want to make your own sacks and baskets you'll need to use the loom that's near the Farming shop in Falador. If you're a good enough ${if (player!!.isMale) "craftsman" else "craftswoman"}, that is.", + "You can buy all the farming tools from farming shops, which can be found close to the allotments.", + + "Hops are good for brewing ales. I believe there's a brewery up in Keldagrim somewhere, and I've heard rumours that a place called Phasmatys used to be good for that type of thing. 'Fore they all died, of course.", + ) + npcl(FacialExpression.NEUTRAL, advice.random()).also { stage = START_DIALOGUE } } } return true } - fun checkPatch(player: Player,fPatch: FarmingPatch){ - if(fPatch.getPatchFor(player).isWeedy()){ - npc("You don't have anything planted in that patch.","Plant something and I might agree to look after it for you.").also { stage = END_DIALOGUE } - } else if(fPatch.getPatchFor(player).isGrown()){ - npc("That patch is already fully grown!","I don't know what you want me to do with it!").also { stage = END_DIALOGUE } - } else if(fPatch.getPatchFor(player).protectionPaid) { - npc("Are you alright? You've already", "paid me for that.").also { stage = END_DIALOGUE } - } else { - end() - player.dialogueInterpreter.open(FarmerPayOptionDialogue(fPatch.getPatchFor(player)),npc) - } + fun openPayGardenerDialogue(player: Player, fPatch: FarmingPatch) { + end() + openDialogue(player, FarmerPayOptionDialogue(fPatch.getPatchFor(player)), npc) } override fun getIds(): IntArray { diff --git a/Server/src/main/content/global/skill/farming/CompostBin.kt b/Server/src/main/content/global/skill/farming/CompostBin.kt index 617e800db..c7e7f5cc2 100644 --- a/Server/src/main/content/global/skill/farming/CompostBin.kt +++ b/Server/src/main/content/global/skill/farming/CompostBin.kt @@ -19,6 +19,19 @@ class CompostBin(val player: Player, val bin: CompostBins) { var finishedTime = 0L var isFinished = false + /** + * Resets the compost bin to its initial state. + */ + fun reset() { + items.clear() + isSuperCompost = true + isTomatoes = true + isClosed = false + finishedTime = 0L + isFinished = false + updateBit() + } + fun isFull() : Boolean { return items.size == 15 } diff --git a/Server/src/main/content/global/skill/farming/CropHarvester.kt b/Server/src/main/content/global/skill/farming/CropHarvester.kt index 779609bf8..f5fda6108 100644 --- a/Server/src/main/content/global/skill/farming/CropHarvester.kt +++ b/Server/src/main/content/global/skill/farming/CropHarvester.kt @@ -61,7 +61,13 @@ class CropHarvester : OptionHandler() { } } val anim = when (requiredItem) { - Items.SPADE_952 -> if (fPatch.type == PatchType.HERB_PATCH) Animation(2282) else Animation(830) + Items.SPADE_952 -> { + when (fPatch.type) { + PatchType.HERB_PATCH -> Animation(2282) + PatchType.FLOWER_PATCH -> Animation(2292) + else -> Animation(830) + } + } Items.SECATEURS_5329 -> if (fPatch.type == PatchType.TREE_PATCH) Animation(2277) else Animation(7227) Items.MAGIC_SECATEURS_7409 -> if (fPatch.type == PatchType.TREE_PATCH) Animation(3340) else Animation(7228) else -> Animation(0) @@ -76,12 +82,15 @@ class CropHarvester : OptionHandler() { sendMessage(player, "You lack the needed tool to harvest these crops.") return true } - if (firstHarvest) { + val sendHarvestMessages = if (fPatch.type == PatchType.FLOWER_PATCH) false else true + if (sendHarvestMessages && firstHarvest) { sendMessage(player, "You begin to harvest the $patchName.") firstHarvest = false } animate(player, anim) playAudio(player, sound) + // TODO: If a flower patch is being harvested, delay the clearing of the + // patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75 delay = 2 addItem(player, reward.id) rewardXP(player, Skills.FARMING, plantable.harvestXP) @@ -96,7 +105,7 @@ class CropHarvester : OptionHandler() { patch.clear() } } - if (patch.cropLives <= 0 || patch.harvestAmt <= 0) { + if (sendHarvestMessages && (patch.cropLives <= 0 || patch.harvestAmt <= 0)) { sendMessage(player, "The $patchName is now empty.") } return patch.cropLives <= 0 || patch.harvestAmt <= 0 diff --git a/Server/src/main/content/global/skill/farming/DigUpPatchDialogue.kt b/Server/src/main/content/global/skill/farming/DigUpPatchDialogue.kt index 21a773c20..a0d70bb07 100644 --- a/Server/src/main/content/global/skill/farming/DigUpPatchDialogue.kt +++ b/Server/src/main/content/global/skill/farming/DigUpPatchDialogue.kt @@ -24,7 +24,7 @@ class DigUpPatchDialogue(player: Player? = null) : DialoguePlugin(player) { } if (patch?.patch?.type == PatchType.TREE_PATCH) { val isTreeStump = patch?.getCurrentState() == patch?.plantable!!.value + patch?.plantable!!.stages + 2 - if (!isTreeStump) { + if (patch!!.isGrown() && !isTreeStump) { sendMessage(player, "You need to chop this tree down first.") // this message is not authentic stage = 1000 return true diff --git a/Server/src/main/content/global/skill/farming/FarmerPayOptionDialogue.kt b/Server/src/main/content/global/skill/farming/FarmerPayOptionDialogue.kt index eeb8903f5..7b29a5568 100644 --- a/Server/src/main/content/global/skill/farming/FarmerPayOptionDialogue.kt +++ b/Server/src/main/content/global/skill/farming/FarmerPayOptionDialogue.kt @@ -1,68 +1,113 @@ package content.global.skill.farming -import core.game.node.item.Item -import org.rs09.consts.Items +import core.api.* import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.item.Item import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import org.rs09.consts.Items -class FarmerPayOptionDialogue(val patch: Patch): DialogueFile() { +class FarmerPayOptionDialogue(val patch: Patch, val quickPay: Boolean = false): DialogueFile() { var item: Item? = null override fun handle(componentID: Int, buttonID: Int) { - when(stage){ + when (stage) { START_DIALOGUE -> { - item = patch.plantable?.protectionItem - val protectionText = when(item?.id){ - Items.COMPOST_6032 -> if(item?.amount == 1) "bucket of compost" else "buckets of compost" - Items.POTATOES10_5438 -> if(item?.amount == 1) "sack of potatoes" else "sacks of potatoes" - Items.ONIONS10_5458 -> if(item?.amount == 1) "sack of onions" else "sacks of onions" - Items.CABBAGES10_5478 -> if(item?.amount == 1) "sack of cabbages" else "sacks of cabbages" - Items.JUTE_FIBRE_5931 -> "jute fibres" - Items.APPLES5_5386 -> if(item?.amount == 1) "basket of apples" else "baskets of apples" - Items.MARIGOLDS_6010 -> "harvest of marigold" - Items.TOMATOES5_5968 -> if(item?.amount == 1) "basket of tomatoes" else "baskets of tomatoes" - Items.ORANGES5_5396 -> if(item?.amount == 1) "basket of oranges" else "baskets of oranges" - Items.COCONUT_5974 -> "coconuts" - Items.CACTUS_SPINE_6016 -> "cactus spines" - Items.STRAWBERRIES5_5406 -> if(item?.amount == 1) "basket of strawberries" else "baskets of strawberries" - Items.BANANAS5_5416 -> if(item?.amount == 1) "basket of bananas" else "baskets of bananas" - else -> item?.name?.toLowerCase() - } - if(item == null) npc("Sorry, I won't protect that.").also { stage = END_DIALOGUE } - else{ - npc("I would like ${item?.amount} $protectionText","to protect that patch.") - stage++ - } - } - - 1 -> options("Sure!","No, thanks.").also { stage++ } - 2 -> { - if(player!!.inventory.containsItem(item)){ - player("Here you go.").also { stage = 10 } + if (patch.patch.type == PatchType.TREE_PATCH && patch.plantable != null && patch.isGrown()) { + // This is for the right-click "Pay" option; full dialogue is in GardenerDialoguePlugin + showTopics( + Topic("Yes, get rid of the tree.", 300, true), + Topic("No thanks.", END_DIALOGUE, true), + title = "Pay 200 gp to have the tree chopped down?" + ) + } else if (patch.protectionPaid) { + npc("I don't know what you're talking about - I'm already", "looking after that patch for you.").also { stage = 100 } + } else if (patch.isDead) { + npc("That patch is dead - it's too late for me to do", "anything about it now.").also { stage = END_DIALOGUE } + } else if (patch.isDiseased) { + npc("That patch is diseased - I can't look after it", "until it has been cured.").also { stage = END_DIALOGUE } // this dialogue is not authentic + } else if (patch.isWeedy() || patch.isEmptyAndWeeded()) { + npc(FacialExpression.NEUTRAL, "You don't have anything planted in that patch. Plant", "something and I might agree to look after it for you.").also { stage = END_DIALOGUE } + } else if (patch.isGrown()) { + npc("That patch is already fully grown!", "I don't know what you want me to do with it!").also { stage = END_DIALOGUE } } else { - item = Item(item!!.noteChange,item!!.amount) - if(player!!.inventory.containsItem(item)){ - player("Here you go.").also { stage = 10 } + item = patch.plantable?.protectionItem + val protectionText = when (item?.id) { + Items.COMPOST_6032 -> if (item?.amount == 1) "bucket of compost" else "buckets of compost" + Items.POTATOES10_5438 -> if (item?.amount == 1) "sack of potatoes" else "sacks of potatoes" + Items.ONIONS10_5458 -> if (item?.amount == 1) "sack of onions" else "sacks of onions" + Items.CABBAGES10_5478 -> if (item?.amount == 1) "sack of cabbages" else "sacks of cabbages" + Items.JUTE_FIBRE_5931 -> "jute fibres" + Items.APPLES5_5386 -> if (item?.amount == 1) "basket of apples" else "baskets of apples" + Items.MARIGOLDS_6010 -> "harvest of marigold" + Items.TOMATOES5_5968 -> if (item?.amount == 1) "basket of tomatoes" else "baskets of tomatoes" + Items.ORANGES5_5396 -> if (item?.amount == 1) "basket of oranges" else "baskets of oranges" + Items.COCONUT_5974 -> "coconuts" + Items.CACTUS_SPINE_6016 -> "cactus spines" + Items.STRAWBERRIES5_5406 -> if (item?.amount == 1) "basket of strawberries" else "baskets of strawberries" + Items.BANANAS5_5416 -> if (item?.amount == 1) "basket of bananas" else "baskets of bananas" + else -> item?.name?.lowercase() + } + if (item == null) { + npc("Sorry, I won't protect that.").also { stage = END_DIALOGUE } + } else if (quickPay && !(inInventory(player!!, item!!.id, item!!.amount) || inInventory(player!!, note(item!!).id, note(item!!).amount))) { + val amount = if (item?.amount == 1) "one" else item?.amount + npc(FacialExpression.HAPPY, "I want $amount $protectionText for that.") + stage = 200 + } else if (quickPay) { + val amount = if (item?.amount == 1) "one" else item?.amount + showTopics( + Topic("Yes", 20, true), + Topic("No", END_DIALOGUE, true), + title = "Pay $amount $protectionText?" + ) } else { - player("I don't have that to give.").also { stage = 20 } + val amount = if (item?.amount == 1) "one" else item?.amount + npc("If you like, but I want $amount $protectionText for that.") + stage++ } } } - 10 -> { - if(player!!.inventory.remove(item)){ - npc("Thank you! I'll keep an eye on this patch.").also { stage = END_DIALOGUE } - patch?.protectionPaid = true + 1 -> { + if (!(inInventory(player!!, item!!.id, item!!.amount) || inInventory(player!!, note(item!!).id, note(item!!).amount))) { + player("I'm afraid I don't have any of those at the moment.").also { stage = 10 } } else { - npc("That stuff just... vanished....").also { stage = END_DIALOGUE } + showTopics( + Topic(FacialExpression.NEUTRAL, "Okay, it's a deal.", 20), + Topic(FacialExpression.NEUTRAL, "No, that's too much.", 10) + ) } } + 10 -> npc("Well, I'm not wasting my time for free.").also { stage = END_DIALOGUE } + 20 -> { - npc("Come back when you do.") - stage = END_DIALOGUE + if (removeItem(player!!, item) || removeItem(player!!, note(item!!))) { + patch.protectionPaid = true + // Note: A slight change in this dialogue was seen in a December 2009 video - https://youtu.be/7gVh42ylQ48?t=138 + npc("That'll do nicely, ${if (player!!.isMale) "sir" else "madam"}. Leave it with me - I'll make sure", "those crops grow for you.").also { stage = END_DIALOGUE } + } else { + npc("This shouldn't be happening. Please report this.").also { stage = END_DIALOGUE } + } + } + + 100 -> player("Oh sorry, I forgot.").also { stage = END_DIALOGUE } + + // Right-click "Pay" - protect patch - player doesn't have payment + 200 -> player(FacialExpression.NEUTRAL, "Thanks, maybe another time.").also { stage = END_DIALOGUE } + + // Right-click "Pay" - chop down tree + 300 -> { + if (removeItem(player!!, Item(Items.COINS_995, 200))) { + patch.clear() + dialogue("The gardener obligingly removes your tree.").also { stage = END_DIALOGUE } + } else { + dialogue("You need 200 gp to pay for that.").also { stage = END_DIALOGUE } // not authentic + } } } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/farming/FarmerPayOptionHandler.kt b/Server/src/main/content/global/skill/farming/FarmerPayOptionHandler.kt index 724ce6c73..52d7874ad 100644 --- a/Server/src/main/content/global/skill/farming/FarmerPayOptionHandler.kt +++ b/Server/src/main/content/global/skill/farming/FarmerPayOptionHandler.kt @@ -1,5 +1,6 @@ package content.global.skill.farming +import core.api.openDialogue import core.game.node.Node import core.game.node.entity.player.Player import core.game.interaction.InteractionListener @@ -8,35 +9,20 @@ import core.game.interaction.IntType class FarmerPayOptionHandler : InteractionListener { override fun defineListeners() { - on(IntType.NPC,"pay","pay (north)","pay (north-west)"){ player, node -> + on(IntType.NPC,"pay","pay (north)","pay (north-west)") { player, node -> return@on attemptPay(player,node,0) } - on(IntType.NPC,"pay (south)","pay (south-east)"){ player, node -> + on(IntType.NPC,"pay (south)","pay (south-east)") { player, node -> return@on attemptPay(player,node,1) } } - fun attemptPay(player: Player, node: Node, index: Int): Boolean{ + fun attemptPay(player: Player, node: Node, index: Int): Boolean { val farmer = Farmers.forId(node.id) ?: return false val patch = farmer.patches[index].getPatchFor(player) - if(patch.plantable == null){ - player.dialogueInterpreter.sendDialogue("I have nothing to protect in that patch.") - return true - } - - if(patch.protectionPaid){ - player.dialogueInterpreter.sendDialogue("I have already paid to protect that patch.") - return true - } - - if(patch.isGrown()){ - player.dialogueInterpreter.sendDialogue("This patch is already fully grown!") - return true - } - - player.dialogueInterpreter.open(FarmerPayOptionDialogue(patch),node.asNpc()) + openDialogue(player, FarmerPayOptionDialogue(patch, true), node.asNpc()) return true } } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/farming/FarmingPatch.kt b/Server/src/main/content/global/skill/farming/FarmingPatch.kt index c322e4de8..ed033d253 100644 --- a/Server/src/main/content/global/skill/farming/FarmingPatch.kt +++ b/Server/src/main/content/global/skill/farming/FarmingPatch.kt @@ -117,8 +117,8 @@ enum class FarmingPatch(val varbit: Int, val type: PatchType) { } } - fun getPatchFor(player: Player): Patch{ - var crops = getOrStartTimer (player)!! - return crops.getPatch(this) + fun getPatchFor(player: Player, addPatch : Boolean = true): Patch{ + val crops = getOrStartTimer (player) + return crops.getPatch(this, addPatch) } } diff --git a/Server/src/main/content/global/skill/farming/FarmingState.kt b/Server/src/main/content/global/skill/farming/FarmingState.kt deleted file mode 100644 index ed7f769e5..000000000 --- a/Server/src/main/content/global/skill/farming/FarmingState.kt +++ /dev/null @@ -1,43 +0,0 @@ -package content.global.skill.farming - -import core.api.* -import core.Util.clamp -import core.game.node.entity.player.Player -import core.game.system.task.Pulse -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import org.json.simple.JSONArray -import org.json.simple.JSONObject -import core.game.node.entity.state.PlayerState -import core.game.node.entity.state.State -import core.tools.SystemLogger -import java.util.concurrent.TimeUnit -import content.global.skill.farming.timers.* - -@PlayerState("farming") -/** - * Kept around solely for the purpose of porting save data from this old system to the new one. - * //TODO REMOVE BY END OF 2023 -**/ -class FarmingState(player: Player? = null) : State(player) { - override fun save(root: JSONObject) {} - override fun parse(_data: JSONObject) { - player ?: return - if(_data.containsKey("farming-bins")){ - _data["bins"] = _data["farming-bins"] - val timer = getOrStartTimer (player) - timer.parse (_data, player) - } - if(_data.containsKey("farming-patches")){ - _data["patches"] = _data["farming-patches"] - val timer = getOrStartTimer (player) - timer.parse(_data, player) - } - } - - override fun newInstance(player: Player?): State { - return FarmingState(player) - } - - override fun createPulse() {} -} diff --git a/Server/src/main/content/global/skill/farming/HealthChecker.kt b/Server/src/main/content/global/skill/farming/HealthChecker.kt index 43d0e24d9..5c819f1a3 100644 --- a/Server/src/main/content/global/skill/farming/HealthChecker.kt +++ b/Server/src/main/content/global/skill/farming/HealthChecker.kt @@ -36,13 +36,22 @@ class HealthChecker : OptionHandler() { rewardXP(player, Skills.FARMING, patch.plantable?.checkHealthXP ?: 0.0) patch.isCheckHealth = false when (type) { - PatchType.TREE_PATCH -> patch.setCurrentState(patch.getCurrentState() + 1) - PatchType.FRUIT_TREE_PATCH -> patch.setCurrentState(patch.getCurrentState() - 14) - PatchType.BUSH_PATCH -> { - sendMessage(player, "You examine the bush for signs of disease and find that it's in perfect health.") - patch.setCurrentState(patch.plantable!!.value + patch.plantable!!.stages + 4) + PatchType.TREE_PATCH -> { + patch.setCurrentState(patch.getCurrentState() + 1) + sendMessage(player, "You examine the tree for signs of disease and find that it is in perfect health.") + } + PatchType.FRUIT_TREE_PATCH -> { + patch.setCurrentState(patch.getCurrentState() - 14) + sendMessage(player, "You examine the tree for signs of disease and find that it is in perfect health.") + } + PatchType.BUSH_PATCH -> { + patch.setCurrentState(patch.plantable!!.value + patch.plantable!!.stages + 4) + sendMessage(player, "You examine the bush for signs of disease and find that it's in perfect health.") + } + PatchType.CACTUS_PATCH -> { + patch.setCurrentState(patch.plantable!!.value + patch.plantable!!.stages + 3) + sendMessage(player, "You examine the cactus for signs of disease and find that it is in perfect health.") } - PatchType.CACTUS_PATCH -> patch.setCurrentState(patch.plantable!!.value + patch.plantable!!.stages + 3) else -> log(this::class.java, Log.ERR, "Unreachable patch type from when(type) switch in HealthChecker.kt") } diff --git a/Server/src/main/content/global/skill/farming/Patch.kt b/Server/src/main/content/global/skill/farming/Patch.kt index 486f1d5bf..c9f90b4a9 100644 --- a/Server/src/main/content/global/skill/farming/Patch.kt +++ b/Server/src/main/content/global/skill/farming/Patch.kt @@ -123,6 +123,9 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl log(this::class.java, Log.DEBUG, "Patch for ${player.username} at varbit ${patch.varbit} with plantable ${plantable?.name ?: "none"} was set to diseased at stage $currentGrowthStage, which isn't valid.") return (state and (0x80.inv())) } + else if (state in listOf(0, 1, 2, 3)){ + // we're weedy (or an empty plot) as normal just continue + } else { log (this::class.java, Log.ERR, "Patch for ${player.username} at varbit ${patch.varbit} with plantable ${plantable?.name ?: "none"} was set to state $state at growth stage $currentGrowthStage, which isn't valid. We're not sure why this is happening.") } @@ -134,6 +137,13 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl return compost != CompostType.NONE } + /** + * Returns true if the patch is fully grown. + * + * Note: This returns true if the patch is fully weedy. + * Use `plantable == null` to check if a patch does + * not have anything planted. + */ fun isGrown(): Boolean{ return currentGrowthStage == (plantable?.stages ?: 0) } @@ -276,18 +286,18 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl return } - diseaseMod = when(compost){ + // This is so a cheat can force disease + diseaseMod = if (diseaseMod < 0) -128 else when(compost){ CompostType.NONE -> 0 CompostType.COMPOST -> 8 CompostType.SUPERCOMPOST -> 13 } - if(patch != FarmingPatch.TROLL_STRONGHOLD_HERB && RandomFunction.random(128) <= (17 - diseaseMod) && !isWatered && !isGrown() && !protectionPaid && !isFlowerProtected() && patch.type != PatchType.EVIL_TURNIP_PATCH ){ - //bush, tree, fruit tree, herb and cactus can not disease on stage 1(0) of growth. - if(!((patch.type == PatchType.BUSH_PATCH || patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || patch.type == PatchType.CACTUS_PATCH || patch.type == PatchType.HERB_PATCH) && currentGrowthStage == 0)) { - isDiseased = true - return - } + if(patch != FarmingPatch.TROLL_STRONGHOLD_HERB && RandomFunction.random(128) <= (17 - diseaseMod) && !isWatered && !isGrown() && !protectionPaid && !isFlowerProtected() && patch.type != PatchType.EVIL_TURNIP_PATCH && currentGrowthStage != 0){ + isDiseased = true + // If we manually set disease mod reset it back to 0 so that crops can naturally grow after being treated/accidentally attempted to disease when they cannot be + if (diseaseMod < 0) diseaseMod = 0 + return } if((patch.type == PatchType.FRUIT_TREE_PATCH || patch.type == PatchType.TREE_PATCH || patch.type == PatchType.BUSH_PATCH || patch.type == PatchType.CACTUS_PATCH) && plantable != null && plantable?.stages == currentGrowthStage + 1){ @@ -376,7 +386,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl FarmingPatch.CATHERBY_ALLOTMENT_S,FarmingPatch.CATHERBY_ALLOTMENT_N -> FarmingPatch.CATHERBY_FLOWER_C FarmingPatch.PORT_PHAS_ALLOTMENT_SE,FarmingPatch.PORT_PHAS_ALLOTMENT_NW -> FarmingPatch.PORT_PHAS_FLOWER_C else -> return false - }.getPatchFor(player) + }.getPatchFor(player, false) return (fpatch.plantable != null && (fpatch.plantable == plantable?.protectionFlower || fpatch.plantable == Plantable.forItemID(Items.WHITE_LILY_SEED_14589)) diff --git a/Server/src/main/content/global/skill/farming/PatchRaker.kt b/Server/src/main/content/global/skill/farming/PatchRaker.kt index 27bc3d8fa..10af95489 100644 --- a/Server/src/main/content/global/skill/farming/PatchRaker.kt +++ b/Server/src/main/content/global/skill/farming/PatchRaker.kt @@ -15,7 +15,7 @@ object PatchRaker { val p = patch.getPatchFor(player) val patchName = p.patch.type.displayName() var firstRake = true - if (p.isEmptyAndWeeded()) { + if (!p.isWeedy()) { sendMessage(player, "This $patchName doesn't need weeding right now.") return } diff --git a/Server/src/main/content/global/skill/farming/Plantable.kt b/Server/src/main/content/global/skill/farming/Plantable.kt index c77d22b6e..83c016c64 100644 --- a/Server/src/main/content/global/skill/farming/Plantable.kt +++ b/Server/src/main/content/global/skill/farming/Plantable.kt @@ -3,88 +3,88 @@ package content.global.skill.farming import core.game.node.item.Item import org.rs09.consts.Items -enum class Plantable(val itemID: Int, val value: Int, val stages: Int, val plantingXP: Double, val harvestXP: Double, val checkHealthXP: Double, val requiredLevel: Int, val applicablePatch: PatchType, val harvestItem: Int, val protectionItem: Item? = null,val protectionFlower: Plantable? = null) { +enum class Plantable(val itemID: Int, val displayName: String, val value: Int, val stages: Int, val plantingXP: Double, val harvestXP: Double, val checkHealthXP: Double, val requiredLevel: Int, val applicablePatch: PatchType, val harvestItem: Int, val protectionItem: Item? = null, val protectionFlower: Plantable? = null) { - //Flowers - MARIGOLD_SEED(5096,8,4,8.5,47.0,0.0,2,PatchType.FLOWER_PATCH,Items.MARIGOLDS_6010), - ROSEMARY_SEED(5097,13,4,12.0,66.5,0.0,11,PatchType.FLOWER_PATCH, Items.ROSEMARY_6014), - NASTURTIUM_SEED(5098,18,4,19.5,111.0,0.0,24,PatchType.FLOWER_PATCH,Items.NASTURTIUMS_6012), - WOAD_SEED(5099,23,4,20.5,115.5,0.0,25,PatchType.FLOWER_PATCH,Items.WOAD_LEAF_1793), - LIMPWURT_SEED(5100,28,4,21.5,120.0,0.0,26,PatchType.FLOWER_PATCH,Items.LIMPWURT_ROOT_225), - WHITE_LILY_SEED(14589,37,4,42.0,250.0,0.0,52,PatchType.FLOWER_PATCH,Items.WHITE_LILY_14583), + // Flowers + MARIGOLD_SEED(Items.MARIGOLD_SEED_5096,"marigold seed",8,4,8.5,47.0,0.0,2,PatchType.FLOWER_PATCH,Items.MARIGOLDS_6010), + ROSEMARY_SEED(Items.ROSEMARY_SEED_5097,"rosemary seed",13,4,12.0,66.5,0.0,11,PatchType.FLOWER_PATCH, Items.ROSEMARY_6014), + NASTURTIUM_SEED(Items.NASTURTIUM_SEED_5098,"nasturtium seed",18,4,19.5,111.0,0.0,24,PatchType.FLOWER_PATCH,Items.NASTURTIUMS_6012), + WOAD_SEED(Items.WOAD_SEED_5099,"woad seed",23,4,20.5,115.5,0.0,25,PatchType.FLOWER_PATCH,Items.WOAD_LEAF_1793), + LIMPWURT_SEED(Items.LIMPWURT_SEED_5100,"limpwurt seed",28,4,21.5,120.0,0.0,26,PatchType.FLOWER_PATCH,Items.LIMPWURT_ROOT_225), + WHITE_LILY_SEED(Items.WHITE_LILY_SEED_14589,"white lily seed",37,4,42.0,250.0,0.0,52,PatchType.FLOWER_PATCH,Items.WHITE_LILY_14583), - //Flower(Technically) - SCARECROW(6059,33,3,0.0,0.0,0.0,23,PatchType.FLOWER_PATCH,Items.SCARECROW_6059), + // Flower (technically) + SCARECROW(Items.SCARECROW_6059,"scarecrow",33,3,0.0,0.0,0.0,23,PatchType.FLOWER_PATCH,Items.SCARECROW_6059), - //Allotments - POTATO_SEED(5318, 6, 4, 8.0, 9.0, 0.0, 1, PatchType.ALLOTMENT, Items.POTATO_1942,Item(Items.COMPOST_6032,2),MARIGOLD_SEED), - ONION_SEED(5319, 13, 4, 9.5, 10.5,0.0, 5, PatchType.ALLOTMENT,Items.ONION_1957,Item(Items.POTATOES10_5438),MARIGOLD_SEED), - CABBAGE_SEED(5324, 20, 4, 10.0, 11.5, 0.0,7, PatchType.ALLOTMENT,Items.CABBAGE_1965,Item(Items.ONIONS10_5458),ROSEMARY_SEED), - TOMATO_SEED(5322,27,4,12.5,14.0,0.0,12,PatchType.ALLOTMENT,Items.TOMATO_1982,Item(Items.CABBAGES10_5478,2),MARIGOLD_SEED), - SWEETCORN_SEED(5320,34,6,17.0,19.0,0.0,20,PatchType.ALLOTMENT,Items.SWEETCORN_5986,Item(Items.JUTE_FIBRE_5931,10),SCARECROW), - STRAWBERRY_SEED(5323,43,6,26.0,29.0,0.0,31,PatchType.ALLOTMENT,Items.STRAWBERRY_5504,Item(Items.APPLES5_5386)), - WATERMELON_SEED(5321,52,8,48.5,54.5,0.0,47,PatchType.ALLOTMENT,Items.WATERMELON_5982,Item(Items.CURRY_LEAF_5970,10),NASTURTIUM_SEED), + // Allotments + POTATO_SEED(Items.POTATO_SEED_5318, "potato seed", 6, 4, 8.0, 9.0, 0.0, 1, PatchType.ALLOTMENT, Items.POTATO_1942,Item(Items.COMPOST_6032,2),MARIGOLD_SEED), + ONION_SEED(Items.ONION_SEED_5319, "onion seed", 13, 4, 9.5, 10.5,0.0, 5, PatchType.ALLOTMENT,Items.ONION_1957,Item(Items.POTATOES10_5438),MARIGOLD_SEED), + CABBAGE_SEED(Items.CABBAGE_SEED_5324, "cabbage seed", 20, 4, 10.0, 11.5, 0.0,7, PatchType.ALLOTMENT,Items.CABBAGE_1965,Item(Items.ONIONS10_5458),ROSEMARY_SEED), + TOMATO_SEED(Items.TOMATO_SEED_5322,"tomato seed",27,4,12.5,14.0,0.0,12,PatchType.ALLOTMENT,Items.TOMATO_1982,Item(Items.CABBAGES10_5478,2),MARIGOLD_SEED), + SWEETCORN_SEED(Items.SWEETCORN_SEED_5320,"sweetcorn seed",34,6,17.0,19.0,0.0,20,PatchType.ALLOTMENT,Items.SWEETCORN_5986,Item(Items.JUTE_FIBRE_5931,10),SCARECROW), + STRAWBERRY_SEED(Items.STRAWBERRY_SEED_5323,"strawberry seed",43,6,26.0,29.0,0.0,31,PatchType.ALLOTMENT,Items.STRAWBERRY_5504,Item(Items.APPLES5_5386)), + WATERMELON_SEED(Items.WATERMELON_SEED_5321,"watermelon seed",52,8,48.5,54.5,0.0,47,PatchType.ALLOTMENT,Items.WATERMELON_5982,Item(Items.CURRY_LEAF_5970,10),NASTURTIUM_SEED), - //Hops - BARLEY_SEED(5305,49,4,8.5,9.5,0.0,3,PatchType.HOPS_PATCH,Items.BARLEY_6006,Item(Items.COMPOST_6032,3)), - HAMMERSTONE_SEED(5307,4,4,9.0,10.0,0.0,4,PatchType.HOPS_PATCH,Items.HAMMERSTONE_HOPS_5994,Item(Items.MARIGOLDS_6010)), - ASGARNIAN_SEED(5308,11,5,10.9,12.0,0.0,8,PatchType.HOPS_PATCH,Items.ASGARNIAN_HOPS_5996,Item(Items.ONIONS10_5458)), - JUTE_SEED(5306,56,5,13.0,14.5,0.0,13,PatchType.HOPS_PATCH,Items.JUTE_FIBRE_5931,Item(Items.BARLEY_MALT_6008,6)), - YANILLIAN_SEED(5309,19,6,14.5,16.0,0.0,16,PatchType.HOPS_PATCH,Items.YANILLIAN_HOPS_5998,Item(Items.TOMATOES5_5968)), - KRANDORIAN_SEED(5310,28,7,17.5,19.5,0.0,21,PatchType.HOPS_PATCH,Items.KRANDORIAN_HOPS_6000,Item(Items.CABBAGES10_5478,3)), - WILDBLOOD_SEED(5311,38,8,23.0,26.0,0.0,28,PatchType.HOPS_PATCH,Items.WILDBLOOD_HOPS_6002,Item(Items.NASTURTIUMS_6012)), + // Hops + BARLEY_SEED(Items.BARLEY_SEED_5305,"barley seed",49,4,8.5,9.5,0.0,3,PatchType.HOPS_PATCH,Items.BARLEY_6006,Item(Items.COMPOST_6032,3)), + HAMMERSTONE_SEED(Items.HAMMERSTONE_SEED_5307,"Hammerstone hop seed",4,4,9.0,10.0,0.0,4,PatchType.HOPS_PATCH,Items.HAMMERSTONE_HOPS_5994,Item(Items.MARIGOLDS_6010)), + ASGARNIAN_SEED(Items.ASGARNIAN_SEED_5308,"Asgarnian hop seed",11,5,10.9,12.0,0.0,8,PatchType.HOPS_PATCH,Items.ASGARNIAN_HOPS_5996,Item(Items.ONIONS10_5458)), + JUTE_SEED(Items.JUTE_SEED_5306,"jute plant seed",56,5,13.0,14.5,0.0,13,PatchType.HOPS_PATCH,Items.JUTE_FIBRE_5931,Item(Items.BARLEY_MALT_6008,6)), + YANILLIAN_SEED(Items.YANILLIAN_SEED_5309,"Yanillian hop seed",19,6,14.5,16.0,0.0,16,PatchType.HOPS_PATCH,Items.YANILLIAN_HOPS_5998,Item(Items.TOMATOES5_5968)), + KRANDORIAN_SEED(Items.KRANDORIAN_SEED_5310,"Krandorian hop seed",28,7,17.5,19.5,0.0,21,PatchType.HOPS_PATCH,Items.KRANDORIAN_HOPS_6000,Item(Items.CABBAGES10_5478,3)), + WILDBLOOD_SEED(Items.WILDBLOOD_SEED_5311,"Wildblood hop seed",38,8,23.0,26.0,0.0,28,PatchType.HOPS_PATCH,Items.WILDBLOOD_HOPS_6002,Item(Items.NASTURTIUMS_6012)), - //Trees - OAK_SAPLING(5370,8,4,14.0,0.0,467.3,15,PatchType.TREE_PATCH,Items.OAK_ROOTS_6043,Item(Items.TOMATOES5_5968)), - WILLOW_SAPLING(5371,15,6,25.0,0.0,1456.5,30,PatchType.TREE_PATCH,Items.WILLOW_ROOTS_6045,Item(Items.APPLES5_5386)), - MAPLE_SAPLING(5372,24,8,45.0,0.0,3403.4,45,PatchType.TREE_PATCH,Items.MAPLE_ROOTS_6047,Item(Items.ORANGES5_5396)), - YEW_SAPLING(5373,35,10,81.0,0.0,7069.9,60,PatchType.TREE_PATCH,Items.YEW_ROOTS_6049,Item(Items.CACTUS_SPINE_6016,10)), - MAGIC_SAPLING(5374,48,12,145.5,0.0,13768.3,75,PatchType.TREE_PATCH,Items.MAGIC_ROOTS_6051,Item(Items.COCONUT_5974,25)), + // Trees + OAK_SAPLING(Items.OAK_SAPLING_5370,"oak sapling",8,4,14.0,0.0,467.3,15,PatchType.TREE_PATCH,Items.OAK_ROOTS_6043,Item(Items.TOMATOES5_5968)), + WILLOW_SAPLING(Items.WILLOW_SAPLING_5371,"willow sapling",15,6,25.0,0.0,1456.5,30,PatchType.TREE_PATCH,Items.WILLOW_ROOTS_6045,Item(Items.APPLES5_5386)), + MAPLE_SAPLING(Items.MAPLE_SAPLING_5372,"maple sapling",24,8,45.0,0.0,3403.4,45,PatchType.TREE_PATCH,Items.MAPLE_ROOTS_6047,Item(Items.ORANGES5_5396)), + YEW_SAPLING(Items.YEW_SAPLING_5373,"yew sapling",35,10,81.0,0.0,7069.9,60,PatchType.TREE_PATCH,Items.YEW_ROOTS_6049,Item(Items.CACTUS_SPINE_6016,10)), + MAGIC_SAPLING(Items.MAGIC_SAPLING_5374,"magic Tree sapling",48,12,145.5,0.0,13768.3,75,PatchType.TREE_PATCH,Items.MAGIC_ROOTS_6051,Item(Items.COCONUT_5974,25)), - //Fruit Trees - APPLE_SAPLING(5496,8,6,22.0,8.5,1199.5,27,PatchType.FRUIT_TREE_PATCH,Items.COOKING_APPLE_1955,Item(Items.SWEETCORN_5986,9)), - BANANA_SAPLING(5497,35,6,28.0,10.5,1750.5,33,PatchType.FRUIT_TREE_PATCH,Items.BANANA_1963,Item(Items.APPLES5_5386,4)), - ORANGE_SAPLING(5498,72,6,35.5,13.5,2470.2,39,PatchType.FRUIT_TREE_PATCH,Items.ORANGE_2108,Item(Items.STRAWBERRIES5_5406,3)), - CURRY_SAPLING(5499,99,6,40.0,15.0,2906.9,42,PatchType.FRUIT_TREE_PATCH,Items.CURRY_LEAF_5970,Item(Items.BANANAS5_5416,5)), - PINEAPPLE_SAPLING(5500,136,6,57.0,21.5,4605.7,51,PatchType.FRUIT_TREE_PATCH,Items.PINEAPPLE_2114,Item(Items.WATERMELON_5982,10)), - PAPAYA_SAPLING(5501,163,6,72.0,27.0,6146.4,57,PatchType.FRUIT_TREE_PATCH,Items.PAPAYA_FRUIT_5972,Item(Items.PINEAPPLE_2114,10)), - PALM_SAPLING(5502,200,6,110.5,41.5,10150.1,68,PatchType.FRUIT_TREE_PATCH,Items.COCONUT_5974,Item(Items.PAPAYA_FRUIT_5972,15)), + // Fruit Trees + APPLE_SAPLING(Items.APPLE_SAPLING_5496,"apple tree sapling",8,6,22.0,8.5,1199.5,27,PatchType.FRUIT_TREE_PATCH,Items.COOKING_APPLE_1955,Item(Items.SWEETCORN_5986,9)), + BANANA_SAPLING(Items.BANANA_SAPLING_5497,"banana tree sapling",35,6,28.0,10.5,1750.5,33,PatchType.FRUIT_TREE_PATCH,Items.BANANA_1963,Item(Items.APPLES5_5386,4)), + ORANGE_SAPLING(Items.ORANGE_SAPLING_5498,"orange tree sapling",72,6,35.5,13.5,2470.2,39,PatchType.FRUIT_TREE_PATCH,Items.ORANGE_2108,Item(Items.STRAWBERRIES5_5406,3)), + CURRY_SAPLING(Items.CURRY_SAPLING_5499,"curry tree sapling",99,6,40.0,15.0,2906.9,42,PatchType.FRUIT_TREE_PATCH,Items.CURRY_LEAF_5970,Item(Items.BANANAS5_5416,5)), + PINEAPPLE_SAPLING(Items.PINEAPPLE_SAPLING_5500,"pineapple plant",136,6,57.0,21.5,4605.7,51,PatchType.FRUIT_TREE_PATCH,Items.PINEAPPLE_2114,Item(Items.WATERMELON_5982,10)), + PAPAYA_SAPLING(Items.PAPAYA_SAPLING_5501,"papaya tree sapling",163,6,72.0,27.0,6146.4,57,PatchType.FRUIT_TREE_PATCH,Items.PAPAYA_FRUIT_5972,Item(Items.PINEAPPLE_2114,10)), + PALM_SAPLING(Items.PALM_SAPLING_5502,"palm tree sapling",200,6,110.5,41.5,10150.1,68,PatchType.FRUIT_TREE_PATCH,Items.COCONUT_5974,Item(Items.PAPAYA_FRUIT_5972,15)), - //Bushes - REDBERRY_SEED(5101,5,5,11.5,4.5,64.0,10,PatchType.BUSH_PATCH,Items.REDBERRIES_1951,Item(Items.CABBAGES10_5478,4)), - CADAVABERRY_SEED(5102,15,6,18.0,7.0,102.5,22,PatchType.BUSH_PATCH,Items.CADAVA_BERRIES_753,Item(Items.TOMATOES5_5968,3)), - DWELLBERRY_SEED(5103,26,27,31.5,12.0,177.5,36,PatchType.BUSH_PATCH,Items.DWELLBERRIES_2126,Item(Items.STRAWBERRIES5_5406,3)), - JANGERBERRY_SEED(5104,38,8,50.5,19.0,284.5,48,PatchType.BUSH_PATCH,Items.JANGERBERRIES_247,Item(Items.WATERMELON_5982,6)), - WHITEBERRY_SEED(5105,51,8,78.0,29.0,437.5,59,PatchType.BUSH_PATCH,Items.WHITE_BERRIES_239,null), - POISON_IVY_SEED(5106,197,8,120.0,45.0,675.0,70,PatchType.BUSH_PATCH,Items.POISON_IVY_BERRIES_6018,null), + // Bushes + REDBERRY_SEED(Items.REDBERRY_SEED_5101,"redberry bush seed",5,5,11.5,4.5,64.0,10,PatchType.BUSH_PATCH,Items.REDBERRIES_1951,Item(Items.CABBAGES10_5478,4)), + CADAVABERRY_SEED(Items.CADAVABERRY_SEED_5102,"cadavaberry bush seed",15,6,18.0,7.0,102.5,22,PatchType.BUSH_PATCH,Items.CADAVA_BERRIES_753,Item(Items.TOMATOES5_5968,3)), + DWELLBERRY_SEED(Items.DWELLBERRY_SEED_5103,"dwellberry bush seed",26,27,31.5,12.0,177.5,36,PatchType.BUSH_PATCH,Items.DWELLBERRIES_2126,Item(Items.STRAWBERRIES5_5406,3)), + JANGERBERRY_SEED(Items.JANGERBERRY_SEED_5104,"jangerberry bush seed",38,8,50.5,19.0,284.5,48,PatchType.BUSH_PATCH,Items.JANGERBERRIES_247,Item(Items.WATERMELON_5982,6)), + WHITEBERRY_SEED(Items.WHITEBERRY_SEED_5105,"whiteberry bush seed",51,8,78.0,29.0,437.5,59,PatchType.BUSH_PATCH,Items.WHITE_BERRIES_239,null), + POISON_IVY_SEED(Items.POISON_IVY_SEED_5106,"poison ivy bush seed",197,8,120.0,45.0,675.0,70,PatchType.BUSH_PATCH,Items.POISON_IVY_BERRIES_6018,null), - //Herbs - GUAM_SEED(5291,4,4,11.0,12.5,0.0,9,PatchType.HERB_PATCH,Items.GRIMY_GUAM_199), - MARRENTILL_SEED(5292,11,4,13.5,15.0,0.0,14,PatchType.HERB_PATCH,Items.GRIMY_MARRENTILL_201), - TARROMIN_SEED(5293,18,4,16.0,18.0,0.0,19,PatchType.HERB_PATCH,Items.GRIMY_TARROMIN_203), - HARRALANDER_SEED(5294,25,4,21.5,24.0,0.0,26,PatchType.HERB_PATCH,Items.GRIMY_HARRALANDER_205), - RANARR_SEED(5295,32,4,27.0,30.5,0.0,32,PatchType.HERB_PATCH,Items.GRIMY_RANARR_207), - AVANTOE_SEED(5298,39,4,54.5,61.5,0.0,50,PatchType.HERB_PATCH,Items.GRIMY_AVANTOE_211), - TOADFLAX_SEED(5296,46,4,34.0,38.5,0.0,38,PatchType.HERB_PATCH,Items.GRIMY_TOADFLAX_3049), - IRIT_SEED(5297,53,4,43.0,48.5,0.0,44,PatchType.HERB_PATCH,Items.GRIMY_IRIT_209), - KWUARM_SEED(5299,68,4,69.0,78.0,0.0,56,PatchType.HERB_PATCH,Items.GRIMY_KWUARM_213), - SNAPDRAGON_SEED(5300,75,4,87.5,98.5,0.0,62,PatchType.HERB_PATCH,Items.GRIMY_SNAPDRAGON_3051), - CADANTINE_SEED(5301,82,4,106.5,120.0,0.0,67,PatchType.HERB_PATCH,Items.GRIMY_CADANTINE_215), - LANTADYME_SEED(5302,89,4,134.5,151.5,0.0,73,PatchType.HERB_PATCH,Items.GRIMY_LANTADYME_2485), - DWARF_WEED_SEED(5303,96,4,170.5,192.0,0.0,79,PatchType.HERB_PATCH,Items.GRIMY_DWARF_WEED_217), - TORSTOL_SEED(5304,103,4,199.5,224.5,0.0,85,PatchType.HERB_PATCH,Items.GRIMY_TORSTOL_219), - GOUT_TUBER(6311,192,4,105.0,45.0,0.0,29,PatchType.HERB_PATCH,Items.GOUTWEED_3261), - SPIRIT_WEED_SEED(12176, 204, 4, 32.0, 36.0, 0.0, 36, PatchType.HERB_PATCH, Items.GRIMY_SPIRIT_WEED_12174), + // Herbs + GUAM_SEED(Items.GUAM_SEED_5291,"guam seed",4,4,11.0,12.5,0.0,9,PatchType.HERB_PATCH,Items.GRIMY_GUAM_199), + MARRENTILL_SEED(Items.MARRENTILL_SEED_5292,"marrentill seed",11,4,13.5,15.0,0.0,14,PatchType.HERB_PATCH,Items.GRIMY_MARRENTILL_201), + TARROMIN_SEED(Items.TARROMIN_SEED_5293,"tarromin seed",18,4,16.0,18.0,0.0,19,PatchType.HERB_PATCH,Items.GRIMY_TARROMIN_203), + HARRALANDER_SEED(Items.HARRALANDER_SEED_5294,"harralander seed",25,4,21.5,24.0,0.0,26,PatchType.HERB_PATCH,Items.GRIMY_HARRALANDER_205), + RANARR_SEED(Items.RANARR_SEED_5295,"ranarr seed",32,4,27.0,30.5,0.0,32,PatchType.HERB_PATCH,Items.GRIMY_RANARR_207), + AVANTOE_SEED(Items.AVANTOE_SEED_5298,"avantoe seed",39,4,54.5,61.5,0.0,50,PatchType.HERB_PATCH,Items.GRIMY_AVANTOE_211), + TOADFLAX_SEED(Items.TOADFLAX_SEED_5296,"toadflax seed",46,4,34.0,38.5,0.0,38,PatchType.HERB_PATCH,Items.GRIMY_TOADFLAX_3049), + IRIT_SEED(Items.IRIT_SEED_5297,"irit seed",53,4,43.0,48.5,0.0,44,PatchType.HERB_PATCH,Items.GRIMY_IRIT_209), + KWUARM_SEED(Items.KWUARM_SEED_5299,"kwuarm seed",68,4,69.0,78.0,0.0,56,PatchType.HERB_PATCH,Items.GRIMY_KWUARM_213), + SNAPDRAGON_SEED(Items.SNAPDRAGON_SEED_5300,"snapdragon seed",75,4,87.5,98.5,0.0,62,PatchType.HERB_PATCH,Items.GRIMY_SNAPDRAGON_3051), + CADANTINE_SEED(Items.CADANTINE_SEED_5301,"cadantine seed",82,4,106.5,120.0,0.0,67,PatchType.HERB_PATCH,Items.GRIMY_CADANTINE_215), + LANTADYME_SEED(Items.LANTADYME_SEED_5302,"lantadyme seed",89,4,134.5,151.5,0.0,73,PatchType.HERB_PATCH,Items.GRIMY_LANTADYME_2485), + DWARF_WEED_SEED(Items.DWARF_WEED_SEED_5303,"dwarf weed seed",96,4,170.5,192.0,0.0,79,PatchType.HERB_PATCH,Items.GRIMY_DWARF_WEED_217), + TORSTOL_SEED(Items.TORSTOL_SEED_5304,"torstol seed",103,4,199.5,224.5,0.0,85,PatchType.HERB_PATCH,Items.GRIMY_TORSTOL_219), + GOUT_TUBER(Items.GOUT_TUBER_6311,"gout tuber",192,4,105.0,45.0,0.0,29,PatchType.HERB_PATCH,Items.GOUTWEED_3261), + SPIRIT_WEED_SEED(Items.SPIRIT_WEED_SEED_12176,"spirit weed seed", 204, 4, 32.0, 36.0, 0.0, 36, PatchType.HERB_PATCH, Items.GRIMY_SPIRIT_WEED_12174), - //Other - BELLADONNA_SEED(5281, 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA_PATCH, Items.CAVE_NIGHTSHADE_2398), - MUSHROOM_SPORE(Items.MUSHROOM_SPORE_5282, 6, 7, 61.5, 57.7, 0.0, 53, PatchType.MUSHROOM_PATCH, Items.MUSHROOM_6004), - CACTUS_SEED(Items.CACTUS_SEED_5280, 8, 7, 66.5, 25.0, 374.0, 55, PatchType.CACTUS_PATCH, Items.CACTUS_SPINE_6016), - EVIL_TURNIP_SEED(Items.EVIL_TURNIP_SEED_12148, 4, 1, 41.0, 46.0, 0.0, 42, PatchType.EVIL_TURNIP_PATCH, Items.EVIL_TURNIP_12134) + // Special + BELLADONNA_SEED(Items.BELLADONNA_SEED_5281, "belladonna seed", 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA_PATCH, Items.CAVE_NIGHTSHADE_2398), + MUSHROOM_SPORE(Items.MUSHROOM_SPORE_5282, "mushroom spore", 6, 7, 61.5, 57.7, 0.0, 53, PatchType.MUSHROOM_PATCH, Items.MUSHROOM_6004), + CACTUS_SEED(Items.CACTUS_SEED_5280, "cactus seed", 8, 7, 66.5, 25.0, 374.0, 55, PatchType.CACTUS_PATCH, Items.CACTUS_SPINE_6016), + EVIL_TURNIP_SEED(Items.EVIL_TURNIP_SEED_12148, "evil turnip seed", 4, 1, 41.0, 46.0, 0.0, 42, PatchType.EVIL_TURNIP_PATCH, Items.EVIL_TURNIP_12134) ; - constructor(itemID: Int, value: Int, stages: Int, plantingXP: Double, harvestXP: Double, checkHealthXP: Double, requiredLevel: Int, applicablePatch: PatchType, harvestItem: Int, protectionFlower: Plantable) - : this(itemID,value,stages,plantingXP,harvestXP,checkHealthXP,requiredLevel,applicablePatch,harvestItem,null,protectionFlower) + constructor(itemID: Int, displayName: String, value: Int, stages: Int, plantingXP: Double, harvestXP: Double, checkHealthXP: Double, requiredLevel: Int, applicablePatch: PatchType, harvestItem: Int, protectionFlower: Plantable) + : this(itemID,displayName,value,stages,plantingXP,harvestXP,checkHealthXP,requiredLevel,applicablePatch,harvestItem,null,protectionFlower) companion object { @JvmField val plantables = values().map { it.itemID to it }.toMap() diff --git a/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt b/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt index 980d20b07..29e0d719d 100644 --- a/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt +++ b/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt @@ -69,7 +69,7 @@ class ToolLeprechaunInterface : InterfaceListener { setHasMagicSecateurs(player,false) } } else { - sendMessage(player, "You already have one of those stored.") + sendMessage(player, "You cannot store more than one pair of secateurs in here.") } } 22 -> { @@ -80,7 +80,7 @@ class ToolLeprechaunInterface : InterfaceListener { removeItem(player, can) setWateringCan(player,can) } else { - sendMessage(player, "You already have one of those stored.") + sendMessage(player, "You cannot store more than one watering can in here.") } } 23 -> doDeposit(player, Items.GARDENING_TROWEL_5325, ::setHasGardeningTrowel, ::hasGardeningTrowel) @@ -119,7 +119,15 @@ class ToolLeprechaunInterface : InterfaceListener { depositMethod.invoke(player, true) removeItem(player, item) } else { - sendMessage(player, "You already have one of those stored.") + val itemName = when (item) { + // secateurs and watering cans are handled separately + Items.RAKE_5341 -> "rake" + Items.SEED_DIBBER_5343 -> "dibber" + Items.SPADE_952 -> "spade" + Items.GARDENING_TROWEL_5325 -> "trowel" + else -> getItemName(item).lowercase() + } + sendMessage(player, "You cannot store more than one $itemName in here.") } } diff --git a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt index d71a7c409..26f8658fa 100644 --- a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt +++ b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt @@ -5,7 +5,6 @@ import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.game.system.task.Pulse -import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -21,11 +20,14 @@ class UseWithPatchHandler : InteractionListener { val SECATEURS = Items.SECATEURS_5329 val MAGIC_SECATEURS = Items.MAGIC_SECATEURS_7409 val TROWEL = Items.GARDENING_TROWEL_5325 - val pourBucketAnim = Animation(2283) - val wateringCanAnim = Animation(2293) - val plantCureAnim = Animation(2288) - val secateursTreeAnim = Animation(2277) - val magicSecateursTreeAnim = Animation(3340) + val spadeDigAnim = getAnimation(830) + val trowelDigAnim = getAnimation(2272) + val pourBucketAnim = getAnimation(2283) + val seedDibberAnim = getAnimation(2291) + val wateringCanAnim = getAnimation(2293) + val plantCureAnim = getAnimation(2288) + val secateursTreeAnim = getAnimation(2277) + val magicSecateursTreeAnim = getAnimation(3340) @JvmField val allowedNodes = ArrayList() @@ -46,7 +48,7 @@ class UseWithPatchHandler : InteractionListener { RAKE -> PatchRaker.rake(player,patch) SEED_DIBBER -> sendMessage(player, "I should plant a seed, not the seed dibber.") SPADE -> { - val anim = getAnimation(830) + val anim = spadeDigAnim val p = patch.getPatchFor(player) if (p.isDead) { sendMessage(player, "You start digging the farming patch...") @@ -112,7 +114,7 @@ class UseWithPatchHandler : InteractionListener { return@onUseWith true } - val anim = Animation(2272) + val anim = trowelDigAnim submitIndividualPulse(player, object : Pulse(anim.duration) { override fun pulse(): Boolean { @@ -156,15 +158,21 @@ class UseWithPatchHandler : InteractionListener { Items.WATERING_CAN_5331,Items.WATERING_CAN1_5333,Items.WATERING_CAN2_5334,Items.WATERING_CAN3_5335,Items.WATERING_CAN4_5336,Items.WATERING_CAN5_5337,Items.WATERING_CAN6_5338,Items.WATERING_CAN7_5339,Items.WATERING_CAN8_5340 -> { val p = patch.getPatchFor(player) val t = p.patch.type - if (p.isWatered || p.isEmptyAndWeeded() || p.isGrown() || p.plantable == Plantable.SCARECROW) { - sendMessage(player, "This patch doesn't need watering.") - } else if (t == PatchType.ALLOTMENT || t == PatchType.FLOWER_PATCH || t == PatchType.HOPS_PATCH) { + if (t == PatchType.ALLOTMENT || t == PatchType.FLOWER_PATCH || t == PatchType.HOPS_PATCH) { submitIndividualPulse(player, object : Pulse() { override fun pulse(): Boolean { - if (p.isWeedy()) { + if (p.isWeedy() || p.isEmptyAndWeeded()) { sendMessage(player, "You should grow something first.") return true } + if (p.isWatered || p.isGrown() || p.plantable == Plantable.SCARECROW) { + sendMessage(player, "This patch doesn't need watering.") + return true + } + if (p.isDiseased || p.isDead) { + sendMessage(player, "Water isn't going to cure that!") + return true + } if (usedItem.id == Items.WATERING_CAN_5331) { sendMessage(player, "You need to fill the watering can first.") return true @@ -178,6 +186,8 @@ class UseWithPatchHandler : InteractionListener { return true } }) + } else { + sendMessage(player, "This patch doesn't need watering.") } } @@ -212,9 +222,9 @@ class UseWithPatchHandler : InteractionListener { val plantable = Plantable.forItemID(usedItem.id) ?: return@onUseWith false if (plantable.applicablePatch != patch.type) { - val seedNamePlural = StringUtils.plusS(plantable.name.replace("_", " ").lowercase()) + val plantableNamePlural = StringUtils.plusS(plantable.displayName) val patchType = if (plantable.applicablePatch == PatchType.ALLOTMENT) "a vegetable patch" else prependArticle(plantable.applicablePatch.displayName()) - sendMessage(player, "You can only plant $seedNamePlural in $patchType.") + sendMessage(player, "You can only plant $plantableNamePlural in $patchType.") return@onUseWith true } @@ -232,37 +242,40 @@ class UseWithPatchHandler : InteractionListener { return@onUseWith true } - val plantItem = - if (patch.type == PatchType.ALLOTMENT) Item(plantable.itemID,3) else if (patch.type == PatchType.HOPS_PATCH) { - if (plantable == Plantable.JUTE_SEED) Item(plantable.itemID,3) else Item(plantable.itemID,4) - } else { - Item(plantable.itemID,1) - } - - if (patch.type == PatchType.ALLOTMENT) { - if (!player.inventory.containsItem(plantItem)) { - sendMessage(player, "You need 3 seeds to plant an allotment patch.") - return@onUseWith true - } + val plantItem = when (patch.type) { + PatchType.ALLOTMENT -> Item(plantable.itemID, 3) + PatchType.HOPS_PATCH -> if (plantable == Plantable.JUTE_SEED) Item(plantable.itemID, 3) else Item(plantable.itemID, 4) + else -> Item(plantable.itemID,1) } - if (patch.type != PatchType.FRUIT_TREE_PATCH && patch.type != PatchType.TREE_PATCH) { - if (!inInventory(player, Items.SEED_DIBBER_5343)) { - sendMessage(player, "You need a seed dibber to plant that.") - return@onUseWith true - } - } else { - if (!inInventory(player, Items.SPADE_952) && plantable != Plantable.SCARECROW) { - sendMessage(player, "You need a spade to plant that.") - return@onUseWith true - } + + if (!player.inventory.containsItem(plantItem)) { + val seedPlural = if (plantItem.amount == 1) "seed" else "seeds" + sendMessage(player, "You need ${plantItem.amount} $seedPlural to plant ${prependArticle(patch.type.displayName())}.") + return@onUseWith true + } + + val requiredItem = when (patch.type) { + PatchType.TREE_PATCH, PatchType.FRUIT_TREE_PATCH -> Items.SPADE_952 + PatchType.FLOWER_PATCH -> if (plantable == Plantable.SCARECROW) null else Items.SEED_DIBBER_5343 + else -> Items.SEED_DIBBER_5343 + } + if (requiredItem != null && !inInventory(player, requiredItem)) { + sendMessage(player, "You need ${prependArticle(requiredItem.asItem().name.lowercase())} to plant that.") + return@onUseWith true } player.lock() if (removeItem(player, plantItem)) { - if (plantable != Plantable.SCARECROW) { - animate(player, 2291) - playAudio(player, Sounds.FARMING_DIBBING_2432) + when (requiredItem) { + Items.SPADE_952 -> { + animate(player, spadeDigAnim) + playAudio(player, Sounds.DIGSPADE_1470) + } + Items.SEED_DIBBER_5343 -> { + animate(player, seedDibberAnim) + playAudio(player, Sounds.FARMING_DIBBING_2432) + } } - val delay = if (plantable == Plantable.SCARECROW) 0 else 3 + val delay = if (patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || plantable == Plantable.SCARECROW) 0 else 3 submitIndividualPulse(player, object : Pulse(delay) { override fun pulse(): Boolean { if (plantable == Plantable.JUTE_SEED && patch == FarmingPatch.MCGRUBOR_HOPS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 0, 7)) { @@ -275,8 +288,11 @@ class UseWithPatchHandler : InteractionListener { addItem(player, Items.PLANT_POT_5350) } - val itemAmount = if (plantItem.amount == 1) "a" else plantItem.amount - val itemName = if (plantItem.amount == 1) getItemName(plantItem.id).lowercase() else StringUtils.plusS(getItemName(plantItem.id).lowercase()) + val itemAmount = + if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) "the" + else if (plantItem.amount == 1) "a" + else plantItem.amount + val itemName = if (plantItem.amount == 1) plantable.displayName else StringUtils.plusS(plantable.displayName) val patchName = p.patch.type.displayName() if (plantable == Plantable.SCARECROW) { sendMessage(player, "You place the scarecrow in the $patchName.") diff --git a/Server/src/main/content/global/skill/farming/timers/CropGrowth.kt b/Server/src/main/content/global/skill/farming/timers/CropGrowth.kt index ae3765a99..074e5ae43 100644 --- a/Server/src/main/content/global/skill/farming/timers/CropGrowth.kt +++ b/Server/src/main/content/global/skill/farming/timers/CropGrowth.kt @@ -58,12 +58,18 @@ class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) { for ((_, patch) in patchMap) { val type = patch.patch.type val shouldPlayCatchup = !patch.isGrown() || (type == PatchType.BUSH_PATCH && patch.getFruitOrBerryCount() < 4) || (type == PatchType.FRUIT_TREE_PATCH && patch.getFruitOrBerryCount() < 6) - if(shouldPlayCatchup && patch.plantable != null && !patch.isDead){ - var stagesToSimulate = if (!patch.isGrown()) patch.plantable!!.stages - patch.currentGrowthStage else 0 - if (type == PatchType.BUSH_PATCH) - stagesToSimulate += Math.min(4, 4 - patch.getFruitOrBerryCount()) - if (type == PatchType.FRUIT_TREE_PATCH) - stagesToSimulate += Math.min(6, 6 - patch.getFruitOrBerryCount()) + if (shouldPlayCatchup && !patch.isDead) { + var stagesToSimulate = if (!patch.isGrown()) { + if (patch.isWeedy() || patch.isEmptyAndWeeded()) patch.currentGrowthStage % 4 + else patch.plantable!!.stages - patch.currentGrowthStage + } else 0 + + if (patch.plantable != null) { + if (type == PatchType.BUSH_PATCH) + stagesToSimulate += Math.min(4, 4 - patch.getFruitOrBerryCount()) + if (type == PatchType.FRUIT_TREE_PATCH) + stagesToSimulate += Math.min(6, 6 - patch.getFruitOrBerryCount()) + } val nowTime = System.currentTimeMillis() var simulatedTime = patch.nextGrowth @@ -77,8 +83,8 @@ class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) { } } - fun getPatch(patch: FarmingPatch): Patch { - return patchMap[patch] ?: (Patch(player,patch).also { patchMap[patch] = it }) + fun getPatch(patch: FarmingPatch, addPatch: Boolean ): Patch { + return patchMap[patch] ?: (Patch(player,patch).also { if (addPatch) patchMap[patch] = it }) } fun getPatches(): MutableCollection{ diff --git a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java index 70bd09d38..bdb54f1fe 100644 --- a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java +++ b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java @@ -204,7 +204,7 @@ public class WoodcuttingSkillPulse extends Pulse { if (resource.isFarming()) { FarmingPatch fPatch = FarmingPatch.forObject(node.asScenery()); if(fPatch != null) { - Patch patch = fPatch.getPatchFor(player); + Patch patch = fPatch.getPatchFor(player, true); patch.setCurrentState(patch.getCurrentState() + 1); } return true; diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 6ed1cfebc..40e27939a 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -320,30 +320,38 @@ class LunarListeners : SpellListener("lunar"), Commands { } // Level 66 - fun curePlant(player: Player, obj: Scenery){ + fun curePlant(player: Player, obj: Scenery) { + if (CompostBins.forObject(obj) != null) { + sendMessage(player, "Bins don't often get diseased.") + return + } val fPatch = FarmingPatch.forObject(obj) - if(fPatch == null){ - sendMessage(player, "You attempt to cast Cure Plant on ${obj.definition.name}!") - sendMessage(player, "Nothing interesting happens.") + if (fPatch == null) { + sendMessage(player, "Umm... this spell won't cure that!") return } val patch = fPatch.getPatchFor(player) - if(!patch.isDiseased && !patch.isWeedy() && !patch.isEmptyAndWeeded()){ - sendMessage(player, "It is growing just fine.") - return - } - if(patch.isWeedy()){ + if (patch.isWeedy()) { sendMessage(player, "The weeds are healthy enough already.") return } - if(patch.isDead){ - sendMessage(player, "It says 'Cure' not 'Resurrect'. Although death may arise from disease, it is not in itself a disease and hence cannot be cured. So there.") + if (patch.isEmptyAndWeeded()) { + sendMessage(player, "There's nothing there to cure.") return } - if(patch.isGrown()){ + if (patch.isGrown()) { sendMessage(player, "That's not diseased.") return } + if (patch.isDead) { + sendMessage(player, "It says 'Cure' not 'Resurrect'. Although death may arise from disease, it is not in itself a disease and hence cannot be cured. So there.") + return + } + if (!patch.isDiseased) { + sendMessage(player, "It is growing just fine.") + return + } + patch.cureDisease() removeRunes(player) addXP(player,60.0) diff --git a/Server/src/main/content/global/skill/summoning/familiar/HydraNPC.java b/Server/src/main/content/global/skill/summoning/familiar/HydraNPC.java index 1cc985a30..04ba4c6bc 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/HydraNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/HydraNPC.java @@ -43,7 +43,7 @@ public class HydraNPC extends Familiar { Scenery scenery = (Scenery)node; FarmingPatch farmingPatch = FarmingPatch.forObject(scenery); if(farmingPatch != null) { - Patch patch = farmingPatch.getPatchFor(owner); + Patch patch = farmingPatch.getPatchFor(owner, true); patch.regrowIfTreeStump(); return true; } diff --git a/Server/src/main/core/game/dialogue/DialogueFile.kt b/Server/src/main/core/game/dialogue/DialogueFile.kt index 92beaf0a6..226c962f2 100644 --- a/Server/src/main/core/game/dialogue/DialogueFile.kt +++ b/Server/src/main/core/game/dialogue/DialogueFile.kt @@ -108,8 +108,8 @@ abstract class DialogueFile { interpreter!!.sendDialogues(entity, expression, *messages) } - open fun options(vararg options: String?) { - interpreter!!.sendOptions("Select an Option", *options) + open fun options(vararg options: String?, title: String = "Select an Option") { + interpreter!!.sendOptions(title, *options) } /** @@ -151,7 +151,7 @@ abstract class DialogueFile { player?.dialogueInterpreter?.sendDialogue(*messages) } - fun showTopics(vararg topics: Topic<*>): Boolean { + fun showTopics(vararg topics: Topic<*>, title: String = "Select an Option"): Boolean { val validTopics = ArrayList() topics.filter { if(it is IfTopic) it.showCondition else true }.forEach { topic -> interpreter!!.activeTopics.add(topic) @@ -172,7 +172,7 @@ abstract class DialogueFile { interpreter!!.activeTopics.clear() return false } - else { options(*validTopics.toTypedArray()) + else { options(*validTopics.toTypedArray(), title = title) return false } } diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index fb7b7b544..6911212e1 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -532,6 +532,24 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ } define("finishbins", Privilege.ADMIN, "", "Finishes any in-progress compost bins."){ player, _ -> + val bins = getOrStartTimer(player).getBins() + for (bin in bins) { + if (!bin.isFinished && bin.isClosed) bin.finish() + } + } + + define("resetbins", Privilege.ADMIN, "", "Resets the player's compost bins to their initial states."){ player, _ -> + val bins = getOrStartTimer(player).getBins() + for (bin in bins) bin.reset() + } + + define("diseasecrops", Privilege.ADMIN, "", "Disease all crops"){ player, _ -> + val state = getOrStartTimer(player) + for (patch in state.getPatches()){ + patch.diseaseMod = -128 + patch.nextGrowth = System.currentTimeMillis() + 1 + } + state.run(player) } define("addcredits", Privilege.ADMIN){ player, _ -> From 1c9fbc79aa9a2e78ab82372932a9e4d9043efde8 Mon Sep 17 00:00:00 2001 From: GregF Date: Mon, 7 Oct 2024 11:24:01 +0000 Subject: [PATCH 028/306] Fixed up wordwrap for debugging unhandled interactions --- Server/src/main/core/game/interaction/UseWithHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/interaction/UseWithHandler.java b/Server/src/main/core/game/interaction/UseWithHandler.java index c38a5e6bc..4c5a6f414 100644 --- a/Server/src/main/core/game/interaction/UseWithHandler.java +++ b/Server/src/main/core/game/interaction/UseWithHandler.java @@ -134,7 +134,9 @@ public abstract class UseWithHandler implements Plugin { event.getPlayer().getPulseManager().run(new MovementPulse(event.getPlayer(), event.getUsedWith()) { @Override public boolean pulse() { - event.getPlayer().debug("Unhandled use with interaction: item used: " + event.getUsed() + " with: " + event.getUsedWith()); + event.getPlayer().debug("Unhandled use with interaction:"); + event.getPlayer().debug("Used: " + event.getUsed()); + event.getPlayer().debug("With: " + event.getUsedWith()); event.getPlayer().getPacketDispatch().sendMessage("Nothing interesting happens."); return true; } From ba1e190cdb41fdeb15e0c5cc3a3fcbf8355873cc Mon Sep 17 00:00:00 2001 From: Oliver Fawcett Date: Mon, 7 Oct 2024 11:26:03 +0000 Subject: [PATCH 029/306] Typo fixes for dialogue in enter the abyss and dragon slayer --- .../skill/runecrafting/abyss/ZamorakMageDialogue.java | 10 +++++----- .../misthalin/varrock/dialogue/surok/AbyssalBook.kt | 2 +- .../quest/dragonslayer/GuildmasterDialogue.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java b/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java index 1b46aa4e0..dab5eee1d 100644 --- a/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java +++ b/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java @@ -190,7 +190,7 @@ public final class ZamorakMageDialogue extends DialoguePlugin { stage++; break; case 201: - npc("And there is an ubundant supply of this 'essence' there", "you say?"); + npc("And there is an abundant supply of this 'essence' there", "you say?"); stage++; break; case 202: @@ -299,7 +299,7 @@ public final class ZamorakMageDialogue extends DialoguePlugin { switch (stage) { case 0: if (!player.hasItem(ORBS[0]) && !player.getInventory().containsItem(ORBS[1])) { - player("Uh...", "No...", "I kinda lost that orb thingy that you have me."); + player("Uh...", "No...", "I kinda lost that orb thingy that you gave me."); stage++; break; } @@ -313,14 +313,14 @@ public final class ZamorakMageDialogue extends DialoguePlugin { break; case 1: player.getInventory().add(ORBS[0], player); - npc("What?", "Incompetent fool. Take this.", "And do not make me refret allying myself with you."); + npc("What?", "Incompetent fool. Take this.", "And do not make me regret allying myself with you."); stage++; break; case 2: end(); break; case 3: - npc("I assume the task to be self-explainatory.", "What is it you wish to know?"); + npc("I assume the task to be self-explanatory.", "What is it you wish to know?"); stage++; break; case 4: @@ -328,7 +328,7 @@ public final class ZamorakMageDialogue extends DialoguePlugin { stage++; break; case 5: - npc("All I wish for you to do is to teleport to this 'rune", "essence' location from three different locations wile", "carrying the scrying orb I gave you.", "It will collect the data as you teleport."); + npc("All I wish for you to do is to teleport to this 'rune", "essence' location from three different locations while", "carrying the scrying orb I gave you.", "It will collect the data as you teleport."); stage++; break; case 6: diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/surok/AbyssalBook.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/surok/AbyssalBook.kt index 76d8eefb3..677934f19 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/surok/AbyssalBook.kt +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/surok/AbyssalBook.kt @@ -144,7 +144,7 @@ class AbyssalBook : InteractionListener { BookLine("- if the barriers between", 57), BookLine("these dimensions are", 58), BookLine("sufficiently weakened,", 59), - BookLine("there ma exist the", 60), + BookLine("there may exist the", 60), BookLine("possibility of an alternative", 61), BookLine("method to proceed", 62), BookLine("with Operation:", 63), diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java index c96f8361a..c71367bc4 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java @@ -225,7 +225,7 @@ public final class GuildmasterDialogue extends DialoguePlugin { stage = 112; break; case 112: - npc("Then, of course, you'll need to find a captain willy to", "sail to Crandor, and I'm not sure where you'd find one", "of them!"); + npc("Then, of course, you'll need to find a captain willing to", "sail to Crandor, and I'm not sure where you'd find one", "of them!"); stage = 113; break; case 113: @@ -286,7 +286,7 @@ public final class GuildmasterDialogue extends DialoguePlugin { handleDescription(buttonId); break; case 2: - player("I talked to Oziach and he have me a quest."); + player("I talked to Oziach and he gave me a quest."); stage = 3; break; } @@ -332,7 +332,7 @@ public final class GuildmasterDialogue extends DialoguePlugin { stage = 14; break; case 14: - npc("Some refuegees managed to escape in fishing boats.", "They landed on the coast, north of Rimmington, and", "set up camp but the dragon followed them and burned", "the camp to the ground."); + npc("Some refugees managed to escape in fishing boats.", "They landed on the coast, north of Rimmington, and", "set up camp but the dragon followed them and burned", "the camp to the ground."); stage = 15; break; case 15: From f11149ebe2b35b3b528e71addd5dd3b19263b5af Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Mon, 7 Oct 2024 11:30:02 +0000 Subject: [PATCH 030/306] Corrected quest log for Creatures of Fenkenstrain Corrected quest log for Troll Stronghold Corrected quest log for The Dig Site Corrected quest log for Witch's House Corrected quest log for Scorpion Catcher Corrected quest log for Wolf Whistle Corrected quest log for Nature Spirit Corrected quest log for What Lies Below Populated NPCs in Lucien's Camp (Next to Wildy Chaos Temple hut) (Inaccessible) Populated NPCs in Black knight catacombs (WGS) (Inaccessible) Populated NPCs in 1st level of Pollnivneach Slayer Dungeon (Smoking Kills) (Accessible) --- Server/data/configs/npc_configs.json | 26 ++- Server/data/configs/npc_spawns.json | 96 ++++++++ .../quest/trollstronghold/TrollStronghold.kt | 6 +- .../asgarnia/taverley/quest/WolfWhistle.java | 141 +++++++++--- .../quest/witchshouse/WitchsHouse.java | 37 ++-- .../quest/sheepherder/SheepHerder.java | 78 +++++-- .../quest/scorpioncatcher/ScorpionCatcher.kt | 128 ++++++----- .../digsite/quest/thedigsite/TheDigSite.kt | 82 ++++--- .../varrock/dialogue/SinkethsDiary.kt | 4 +- .../varrock/quest/allfiredup/AllFiredUp.kt | 10 +- .../quest/whatliesbelow/WhatLiesBelow.java | 131 ++++++----- .../CreatureOfFenkenstrain.kt | 21 +- .../quest/naturespirit/NatureSpiritQuest.kt | 207 +++++++++++++----- .../game/global/action/SpecialLadders.java | 5 + 14 files changed, 672 insertions(+), 300 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 01db7199f..410e5e31f 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -68209,6 +68209,28 @@ "range_level": "38", "attack_level": "28" }, + { + "examine": "Not the best of vocalists.", + "combat_style": "1", + "melee_animation": "9449", + "range_animation": "9382", + "combat_audio": "284,286,285", + "magic_level": "65", + "respawn_delay": "60", + "defence_animation": "9451", + "weakness": "0", + "magic_animation": "9382", + "death_animation": "9450", + "name": "Mighty banshee", + "defence_level": "65", + "safespot": null, + "lifepoints": "85", + "strength_level": "65", + "id": "7786", + "aggressive": "true", + "range_level": "0", + "attack_level": "65" + }, { "examine": "A big, scary hand! ", "melee_animation": "1802", @@ -72229,9 +72251,9 @@ "id": "796" }, { - "examine": "The hat is a dead give away.", "name": "Wizard Cromperty", - "id": "2328" + "id": "2328", + "examine": "The hat is a dead give away." }, { "examine": "An intelligent-looking shop owner.", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 72660d047..25a67f84e 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -11739,6 +11739,30 @@ "npc_id": "7780", "loc_data": "{3358,2993,0,1,0}-" }, + { + "npc_id": "7786", + "loc_data": "{3348,9388,0,1,0}-{3350,9393,0,1,0}-{3350,9400,0,1,0}-{3350,9406,0,1,0}-{3351,9380,0,1,0}-{3352,9374,0,1,0}-{3354,9387,0,1,0}-{3358,9378,0,1,0}-{3358,9396,0,1,0}-{3358,9406,0,1,0}-{3365,9381,0,1,0}-{3365,9387,0,1,0}-{3365,9402,0,1,0}-{3369,9390,0,1,0}-{3350,9412,0,1,0}-{3351,9420,0,1,0}-{3356,9414,0,1,0}-{3358,9421,0,1,0}-{3364,9424,0,1,0}-{3365,9416,0,1,0}-" + }, + { + "npc_id": "7787", + "loc_data": "{3301,4413,0,1,0}-{3302,4394,0,1,0}-{3304,4397,0,1,0}-{3306,4410,0,1,0}-{3307,4383,0,1,0}-{3307,4397,0,1,0}-{3308,4407,0,1,0}-{3310,4383,0,1,0}-{3310,4386,0,1,0}-{3310,4398,0,1,0}-{3311,4407,0,1,0}-{3312,4380,0,1,0}-{3313,4401,0,1,0}-{3314,4411,0,1,0}-{3316,4376,0,1,0}-{3316,4382,0,1,0}-{3316,4387,0,1,0}-{3316,4397,0,1,0}-{3316,4401,0,1,0}-{3316,4405,0,1,0}-{3317,4391,0,1,0}-{3318,4412,0,1,0}-{3319,4373,0,1,0}-{3319,4407,0,1,0}-{3321,4385,0,1,0}-{3321,4398,0,1,0}-{3322,4412,0,1,0}-{3323,4402,0,1,0}-{3324,4394,0,1,0}-{3324,4397,0,1,0}-{3325,4410,0,1,0}-" + }, + { + "npc_id": "7801", + "loc_data": "{3283,4346,0,1,0}-{3308,4349,0,1,0}-{3293,4375,0,1,0}-{3303,4363,0,1,0}-" + }, + { + "npc_id": "7802", + "loc_data": "{3288,4350,0,1,0}-{3296,4340,0,1,0}-{3288,4361,0,1,0}-{3310,4355,0,1,0}-" + }, + { + "npc_id": "7803", + "loc_data": "{3297,4347,0,1,0}-{3315,4346,0,1,0}-{3282,4357,0,1,0}-{3303,4369,0,1,0}-" + }, + { + "npc_id": "7804", + "loc_data": "{3279,4350,0,1,0}-{3294,4353,0,1,0}-{3294,4366,0,1,0}-" + }, { "npc_id": "7823", "loc_data": "{3161,9547,0,0,3}-{3164,9556,0,0,4}-{3162,9574,0,0,3}-{3198,9554,0,0,7}-{3198,9572,0,0,1}-{3215,9560,0,0,1}-{3216,9588,0,0,1}-" @@ -11891,6 +11915,26 @@ "npc_id": "8275", "loc_data": "{2869,2982,1,1,5}-" }, + { + "npc_id": "8312", + "loc_data": "{3016,9974,1,1,0}-{3021,9940,1,1,0}-{3023,9940,1,1,0}-{3024,9959,1,1,0}-{3027,9960,1,1,0}-{3043,9967,1,1,0}-{3023,9992,1,1,0}-{3016,10021,2,1,0}-{3028,10013,2,1,0}-{3029,10028,2,1,0}-{3038,10005,2,1,0}-{3044,10001,2,1,0}-{3045,9993,2,1,0}-{3045,9999,2,1,0}-{3047,10000,2,1,0}-{3052,10009,2,1,0}-{3054,10001,2,1,0}-{3056,10006,2,1,0}-{3032,10090,1,1,0}-{3040,10096,1,1,0}-{3048,10095,1,1,0}-" + }, + { + "npc_id": "8316", + "loc_data": "{3017,9972,1,1,0}-{3025,9962,1,1,0}-{3030,9943,1,1,0}-{3033,9941,1,1,0}-{3034,9950,1,1,0}-{3035,9950,1,1,0}-{3036,9940,1,1,0}-{3038,9939,1,1,0}-{3045,9968,1,1,0}-{3058,9952,1,1,0}-{3063,9952,1,1,0}-{3025,9995,1,1,0}-{3027,10029,2,1,0}-{3051,10006,2,1,0}-{3052,10002,2,1,0}-{3054,10005,2,1,0}-{3027,10101,1,1,0}-{3039,10100,1,1,0}-{3054,10097,1,1,0}-" + }, + { + "npc_id": "8320", + "loc_data": "{3014,9971,1,1,0}-{3016,9969,1,1,0}-{3028,9942,1,1,0}-{3029,9943,1,1,0}-{3030,9951,1,1,0}-{3033,9950,1,1,0}-{3045,9965,1,1,0}-{3061,9953,1,1,0}-{3062,9953,1,1,0}-{3030,9995,1,1,0}-{3016,10023,2,1,0}-{3029,10014,2,1,0}-{3029,10030,2,1,0}-{3036,10005,2,1,0}-{3042,9994,2,1,0}-{3047,10005,2,1,0}-{3049,10002,2,1,0}-{3053,9998,2,1,0}-{3031,10100,1,1,0}-{3044,10098,1,1,0}-{3049,10102,1,1,0}-" + }, + { + "npc_id": "8324", + "loc_data": "{2911,3811,0,1,0}-{2911,3812,0,1,0}-{2911,3813,0,1,0}-{2925,3821,0,1,0}-{2925,3822,0,1,0}-{2925,3823,0,1,0}-{2929,3798,0,1,0}-{2936,3790,0,1,0}-{2936,3810,0,1,0}-{2939,3823,0,1,0}-{2949,3819,1,1,0}-{2949,3822,1,1,0}-{2955,3822,1,1,0}-{2957,3822,1,1,0}-{3016,9977,1,1,0}-{3021,9939,1,1,0}-{3024,9954,1,1,0}-{3025,9943,1,1,0}-{3025,9954,1,1,0}-{3026,9966,1,1,0}-{3032,9952,1,1,0}-{3039,9954,1,1,0}-{3044,9967,1,1,0}-{3044,9971,1,1,0}-{3057,9936,1,1,0}-{3059,9953,1,1,0}-{3041,9975,2,1,0}-{3043,9975,2,1,0}-{3045,9975,2,1,0}-{3016,10022,2,1,0}-{3017,10039,2,1,0}-{3027,10028,2,1,0}-{3029,10013,2,1,0}-{3036,10038,2,1,0}-{3037,10006,2,1,0}-{3041,10024,2,1,0}-{3043,10032,2,1,0}-{3057,10002,2,1,0}-{3058,10021,2,1,0}-{3065,10006,2,1,0}-{3027,10092,1,1,0}-{3035,10097,1,1,0}-{3051,10099,1,1,0}-{3427,5102,0,1,0}-{3428,5099,0,1,0}-{3428,5102,0,1,0}-{3430,5099,0,1,0}-" + }, + { + "npc_id": "8328", + "loc_data": "{3055,10103,1,1,0}-" + }, { "npc_id": "8349", "loc_data": "{2589,5735,0,1,0}-{2589,5713,0,1,0}-{2610,5709,0,1,0}-{2613,5732,0,1,0}-" @@ -11899,6 +11943,58 @@ "npc_id": "8358", "loc_data": "{2601,5710,0,1,0}-{2603,5737,0,1,0}-" }, + { + "npc_id": "8380", + "loc_data": "{2907,3806,0,1,0}-" + }, + { + "npc_id": "8381", + "loc_data": "{2910,3805,0,1,0}-" + }, + { + "npc_id": "8382", + "loc_data": "{2912,3812,0,1,0}-{2923,3823,0,1,0}-" + }, + { + "npc_id": "8383", + "loc_data": "{2908,3809,0,1,0}-{2919,3823,0,1,0}-" + }, + { + "npc_id": "8384", + "loc_data": "{2922,3827,0,1,0}-" + }, + { + "npc_id": "8385", + "loc_data": "{2924,3825,0,1,0}-" + }, + { + "npc_id": "8386", + "loc_data": "{2921,3824,0,1,0}-" + }, + { + "npc_id": "8387", + "loc_data": "{2934,3786,0,1,0}-" + }, + { + "npc_id": "8388", + "loc_data": "{2935,3784,0,1,0}-{2940,3827,0,1,0}-" + }, + { + "npc_id": "8389", + "loc_data": "{2937,3785,0,1,0}-" + }, + { + "npc_id": "8390", + "loc_data": "{2935,3781,0,1,0}-{2939,3829,0,1,0}-" + }, + { + "npc_id": "8391", + "loc_data": "{2937,3780,0,1,0}-{2940,3833,0,1,0}-" + }, + { + "npc_id": "8392", + "loc_data": "{2938,3782,0,1,0}-{2938,3831,0,1,0}-" + }, { "npc_id": "8536", "loc_data": "{2654,5600,0,1,3}-{2650,5600,0,0,3}-{2662,5593,0,0,3}-{2653,5590,0,0,3}-{2644,5592,0,0,3}-{2644,5601,0,0,3}-{2654,5604,0,0,3}-{2663,5606,0,0,3}-{2670,5597,0,0,3}-{2657,5589,0,0,3}-" diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt index 37ce90253..1a3e1657b 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt @@ -63,8 +63,10 @@ class TrollStronghold : Quest("Troll Stronghold",128, 127, 1, 317, 0, 1, 50) { } else if (stage >= 3) { line(player, "I have accepted the !!Troll Champion's?? challenge.", line++) } - if (stage in 5..7) { - line++ + line++ + if (stage >= 7) { + line(player, "I found my way into the Troll Stronghold", line++, true) + } else if (stage >= 5) { line(player, "I have to find a way to get into the !!Troll Stronghold??", line++) } line++ diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java index a9aeecf48..04b8a788f 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java @@ -5,6 +5,7 @@ import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import org.rs09.consts.Items; import static core.api.ContentAPIKt.*; @@ -31,32 +32,120 @@ public class WolfWhistle extends Quest { @Override public void drawJournal(Player player, int stage) { super.drawJournal(player, stage); - switch (stage) { - case 0: - line(player, BLUE + "I can begin this quest by talking to " + RED + "Pikkupstix" + BLUE + ", who lives in", 4+ 7); - line(player, RED + "Taverley.", 5+ 7); - break; - case 10: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.", 4+ 7); - break; - case 20: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.



It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.", 4+ 7); - break; - case 30: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.

It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.



I have spoken to Pikkupstix, who has promised to teach me

the secrets of Summoning if I can help dismiss the giant

wolpertinger. To do this, I need to bring him 2 lots of wolf

bones.

" + (player.getInventory().containsItem(WOLF_BONES) ? "" : "") + "I need to get 2 lots of wolf bones.", 4+ 7); - break; - case 40: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.

It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.



I have spoken to Pikkupstix, who has promised to teach me

the secrets of Summoning if I can help dismiss the giant

wolpertinger. To do this, I need to bring him 2 lots of wolf

bones.

I have given Pikkupstix all of the items he requested.



Pikkupstix has given me some gold charms, spirit shards

and pouches, with which to make a spirit wolf pouch and

some Howl scrolls. I will then be able to use them to dismiss

the giant wolpertinger.

I need to open the trapdoor with the trapdoor key that I

have been given. ", 4+ 7); - break; - case 50: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.

It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.



I have spoken to Pikkupstix, who has promised to teach me

the secrets of Summoning if I can help dismiss the giant

wolpertinger. To do this, I need to bring him 2 lots of wolf

bones.



Pikkupstix has given me some gold charms, spirit shards

and pouches, with which to make a spirit wolf pouch and

some Howl scrolls. I will then be able to use them to dismiss

the giant wolpertinger.

I have infused the 2 spirit wolf pouches, but I need to

transform one of them into scrolls at the obelisk.", 4+ 7); - break; - case 60: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.

It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.



I have spoken to Pikkupstix, who has promised to teach me

the secrets of Summoning if I can help dismiss the giant

wolpertinger. To do this, I need to bring him 2 lots of wolf

bones.



Pikkupstix has given me some gold charms, spirit shards

and pouches, with which to make a spirit wolf pouch and

some Howl scrolls. I will then be able to use them to dismiss

the giant wolpertinger.

I have infused the 2 spirit wolf pouches, but I need to

transform one of them into scrolls at the obelisk.

I have dismissed the giant wolpertinger.", 4+ 7); - break; - case 100: - line(player, "Having spoken to Pikkupstix, it seems that all I have to do

is get rid of the little rabbit upstairs in his house.

It appears that I have underestimated the rabbit in this

case; it is some huge rabbit-wolf-monster-bird-thing. I

think I should speak to Pikkupstix to find out what is going

on.



I have spoken to Pikkupstix, who has promised to teach me

the secrets of Summoning if I can help dismiss the giant

wolpertinger. To do this, I need to bring him 2 lots of wolf

bones.



Pikkupstix has given me some gold charms, spirit shards

and pouches, with which to make a spirit wolf pouch and

some Howl scrolls. I will then be able to use them to dismiss

the giant wolpertinger.

I have infused the 2 spirit wolf pouches, but I need to

transform one of them into scrolls at the obelisk.

I have dismissed the giant wolpertinger.



QUEST COMPLETE!", 4+ 7); - break; + var line = 12; + + if(stage == 0){ + line(player, "I can begin this quest by talking to !!Pikkupstix??, who lives in", line++, false); + line(player, "!!Taverly??.", line++, false); + } else { + if (stage >= 10) { + line(player, "Having spoken to !!Pikkupstix??, it seems that all I have to do", line++, stage >= 20); + line(player, "is get rid of the !!little rabbit upstairs in his house??.", line++, stage >= 20); + line++; + } + if (stage >= 20) { + line(player, "It appears that I have underestimated the rabbit in this", line++, stage >= 30); + line(player, "case; it is some !!huge rabbit-wolf-monster-bird-thing??. I", line++, stage >= 30); + line(player, "think I should speak to !!Pikkupstix?? to find out what is going", line++, stage >= 30); + line(player, "on.", line++, stage >= 30); + line++; + } + // Clicking on the ladder - sendMessage("There is no reason to go up there and face that thing again.") + if (stage >= 30) { + line(player, "I have spoken to !!Pikkupstix??, who has promised to teach me ", line++, stage >= 40); + line(player, "the secrets of !!Summoning?? if I can help dismiss the !!giant??", line++, stage >= 40); + line(player, "!!wolpertinger??. To do this, I need to bring him !!2 lots of wolf??", line++, stage >= 40); + line(player, "!!bones??.", line++, stage >= 40); + + if (stage == 30) { + line(player, "!!I need to get 2 lots of wolf bones.??", line++, inInventory(player, Items.WOLF_BONES_2859, 2)); + } else { + line(player, "I have given Pikkupstix all of the items he requested.", line++, true); + line++; + } + } + if (stage >= 40) { + line(player, "Pikkupstix has given me some !!gold charms??, !!spirit shards??", line++, stage >= 50); + line(player, "and !!pouches??, with which to make a !!spirit wolf pouch?? and", line++, stage >= 50); + line(player, "some !!Howl scrolls??. I will then be able to use them to dismiss", line++, stage >= 50); + line(player, "the !!giant wolpertinger??.", line++, stage >= 50); + } + if (stage == 40 && inInventory(player, Items.TRAPDOOR_KEY_12528, 1)) { + line(player, "I need to open the !!trapdoor?? with the !!trapdoor key?? that I", line++, false); + line(player, "have been given.", line++, false); + } else if (stage >= 50 || player.getAttribute("has-key", false)) { + line(player, "I have unlocked the trapdoor.", line++, true); + } + + // This part is a shitshow. + if (stage >= 50 || (stage >= 40 && (inInventory(player, Items.SPIRIT_WOLF_POUCH_12047, 1) || inInventory(player, Items.HOWL_SCROLL_12425, 1)))) { + line(player, "I need to go into Pikkupstix's !!cellar?? and !!infuse a pouch?? at", line++, stage >= 50); + line(player, "the obelisk, using the items I have been given.", line++, stage >= 50); + line++; + line(player, "I have infused the spirit wolf pouch and made some Howl", line++, stage >= 50); + line(player, "scrolls. I should speak with !!Pikkupstix?? about how to use", line++, stage >= 50); + line(player, "them.", line++, stage >= 50); + line++; + } else if (stage >= 40 && inInventory(player, Items.SPIRIT_WOLF_POUCH_12047, 2)) { + line(player, "I have infused the 2 spirit wolf pouches, but I need to", line++, false); + line(player, "transform one of them into scrolls at the obelisk.", line++, false); + } else if (stage >= 40 && player.getAttribute("has-key", false)) { + line(player, "I need to go into Pikkupstix's !!cellar?? and !!infuse a pouch?? at", line++); + line(player, "the obelisk, using the items I have been given.", line++); + line(player, "!!I need to bring 2 lots of wolf bones.??", line++, inInventory(player, Items.WOLF_BONES_2859, 2)); + line(player, "!!I need to bring the pouches.??", line++, inInventory(player, Items.POUCH_12155, 2)); + line(player, "!!I need to bring the gold charms.??", line++, inInventory(player, Items.GOLD_CHARM_12158, 2)); + line(player, "!!I need to bring the spirit shards.??", line++, inInventory(player, Items.SPIRIT_SHARDS_12183, 14)); + } + + if (stage >= 50) { + line(player, "I have been told how to use the spirit wolf pouch and Howl", line++, stage >= 60); + line(player, "scrolls. I should go back upstairs and confront the !!giant??", line++, stage >= 60); + line(player, "!!wolpertinger??.", line++, stage >= 60); + line++; + } + if (stage == 50) { // Does not stay. + if (inInventory(player, Items.SPIRIT_WOLF_POUCH_12047, 1)) { + line(player, "I have the spirit wolf pouch on me.", line++, false); + } else { + line(player, "!!I have lost the spirit wolf pouch.??", line++, false); + } + if (inInventory(player, Items.HOWL_SCROLL_12425, 1)) { + line(player, "I have the Howl scroll on me.", line++, false); + } else { + line(player, "!!I have lost the Howl scroll.??", line++, false); + } + } + + if (stage >= 60) { + // Technically, there should be an extra stage speaking to Pikkupstix here, but it is not available. + line(player, "I have banished the giant !!wolpertinger??. I should speak with", line++, true); + line(player, "!!Pikkupstix?? to get my reward.", line++, true); + line++; + if (player.getSkills().getLevel(Skills.SUMMONING) >= player.getSkills().getStaticLevel(Skills.SUMMONING) || stage >= 100) { + line(player, "I am feeling drained of Summoning skill points and need to", line++, true); + line(player, "recharge at the !!obelisk??.", line++, true); + line++; + line(player, "I have banished the giant !!wolpertinger?? and refreshed my", line++, stage >= 100); + line(player, "Summoning skill points. I should speak with !!Pikkupstix?? to", line++, stage >= 100); + line(player, "get my reward.", line++, stage >= 100); + line++; + } else { + line(player, "I am feeling drained of Summoning skill points and need to", line++); + line(player, "recharge at the !!obelisk??.", line++); + line++; + } + } + + if (stage >= 100) { + line(player, "I have been given access to the secrets of Summoning.", line++, true); + line(player,"QUEST COMPLETE!", line++); + line(player, "!!Reward:??", line++); + line(player, "1 Quest Point,", line++); + line(player, "access to the Summoning skill", line++); + line(player, "275 gold charms", line++); + line(player, "and 276 Summoning XP", line++); + } } } diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java index d4bd61017..cafc82acc 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java @@ -25,25 +25,24 @@ public class WitchsHouse extends Quest { @Override public void drawJournal(Player player, int stage) { super.drawJournal(player, stage); - switch (getStage(player)) { - case 0: - line(player, "I can start this quest by speaking to the little boy", 4+ 7); - line(player, "standing by the long garden just north of Taverley", 5+ 7); - line(player, "I must be able to defeat a level 53 enemy.", 6+ 7); - break; - case 10: - line(player, "A small boy has kicked his ball over the fence into the", 4+ 7); - line(player, "nearby garden, and I have agreed to retrieve it for him.", 5+ 7); - line(player, "I should find a way into the garden where the ball is.", 6+ 7); - break; - case 100: - line(player, "A small boy has kicked his ball over the fence into the", 4+ 7); - line(player, "nearby garden, and I have agreed to retrieve it for him.", 5+ 7); - line(player, "After puzzling through the strangely elaborate security", 6+ 7); - line(player, "system, and defeating a very strange monster, I returned", 7+ 7); - line(player, "the child's ball to him, and he thanked me for my help.", 8+ 7); - line(player, "QUEST COMPLETE!", 10+ 7); - break; + var line = 12; + if(stage == 0){ + line(player, "I can start this quest by speaking to the !!little boy??", line++); + line(player, "standing by the long garden just !!north of Taverly??.", line++); + line(player, "I must be able to defeat a !!level 53 enemy??.", line++); + } else { + line(player, "A small boy kicked his ball over the fence into the nearby", line++, true); + line(player, "garden, and I have agreed to retrieve it for him.", line++, true); + if (stage == 10) { + line(player, "I should find a way into the !!garden?? where the !!ball?? is.", line++); + } + if (stage >= 100) { + line(player, "After puzzling through the strangely elaborate security", line++, true); + line(player, "system, and defeating a very strange monster, I returned", line++, true); + line(player, "the child's ball to him, and he thanked me for my help.", line++, true); + line++; + line(player,"QUEST COMPLETE!", line); + } } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java index f7a28c03b..9562c3a4f 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java +++ b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java @@ -40,34 +40,66 @@ public class SheepHerder extends Quest { @Override public void drawJournal(Player player, int stage) { boolean hasGear = (player.getInventory().containsItem(PLAGUE_BOTTOM) && player.getInventory().containsItem(PLAGUE_TOP) || (player.getEquipment().containsItem(PLAGUE_BOTTOM) && player.getEquipment().containsItem(PLAGUE_TOP))) || stage >= 20; - int line = 11; + int line = 12; boolean sheepDead = player.getAttribute("sheep_herder:all_dead",false); super.drawJournal(player, stage); - if(stage < 10){ - line(player,"I can start this quest by speaking to !!Councillor Halgrive??",line++); - line(player, "near to the !!Zoo?? in !!East Ardougne.??",line++); + if(stage == 0){ + line(player,"I can start this quest by speaking to !!Councillor Halgrive??", line++); + line(player, "near to the !!Zoo?? in !!East Ardougne??.", line++); } else { - switch(stage){ - case 10: - line(player, "!!Councillor Halgrive?? said I should speak to !!Doctor Orbon?? about", line++, hasGear); - line(player, "Getting some protective gear.", line++, hasGear); - line(player, "I need to !!locate the diseased sheep?? and corral them !!into the pin??", line++,sheepDead); - line(player, "After which, I need to !!poison them?? and !!incinerate their bones.??", line++,sheepDead); - if(sheepDead) { - line(player,"I should inform !!Councillor Halgrive?? that I have taken care of the problem.",line++); + line(player,"Councillor Halgrive asked me to dispose of four plague", line++, true); + line(player,"bearing sheep just north of Ardougne and I accepted.", line++, true); + line(player,"He gave me some poisoned sheep feed to do this.", line++, true); + if(hasGear) { + line(player, "I bought some protective clothing from Dr. Orbon in the", line++, true); + line(player, "chapel north of Ardougne Zoo. I could now kill the sheep.", line++, true); + } else { + line(player, "!!Councillor Halgrive?? said I should speak to !!Doctor Orbon??", line++); + line(player, "about getting some protective gear.", line++); + } + if(stage == 10) { + // This is not authentic. +// line(player, "I need to !!locate the diseased sheep?? and corral them !!into the pen??", line++,sheepDead); +// line(player, "After which, I need to !!poison them?? and !!incinerate their bones.??", line++,sheepDead); + line++; + if (sheepDead) { + line(player, "I equipped a prod and then I used it to to herd the diseased", line++, true); + line(player, "sheep to a pen where I could safely kill them and", line++, true); + line(player, "incinerate their bones.", line++, true); + line(player,"I should return to !!Councillor Halgrive?? to collect the reward", line++); + line(player,"he has promised me for my hard work.", line++); + } else { + if (player.getAttribute("sheep_herder:red_dead", false)) { + line(player, "I have killed the first sheep and incinerated its bones.", line++, true); } else { - line(player, "I still need:", line++); - line(player, "A !!Red Sheep??", line++, player.getAttribute("sheep_herder:red_dead", false)); - line(player, "A !!Blue Sheep??", line++, player.getAttribute("sheep_herder:blue_dead", false)); - line(player, "A !!Green Sheep??", line++, player.getAttribute("sheep_herder:green_dead", false)); - line(player, "A !!Yellow Sheep??", line++, player.getAttribute("sheep_herder:yellow_dead", false)); + line(player, "I must find the first sheep and herd it to the special pen.", line++); } - break; - case 100: - line(player,"I helped Councillor Halgrive by putting down",line++,true); - line(player,"plague-bearing sheep.",line++,true); - line(player,"%%QUEST COMPLETE!&&",line++); - break; + if (player.getAttribute("sheep_herder:green_dead", false)) { + line(player, "I have killed the second sheep and incinerated its bones.", line++, true); + } else { + line(player, "I must find the second sheep and herd it to the special", line++); + line(player, "pen.", line++); + } + if (player.getAttribute("sheep_herder:blue_dead", false)) { + line(player, "I have killed the third sheep and incinerated its bones.", line++, true); + } else { + line(player, "I must find the third sheep and herd it to the special pen.", line++); + } + if (player.getAttribute("sheep_herder:yellow_dead", false)) { + line(player, "I have killed the fourth sheep and incinerated its bones.", line++, true); + } else { + line(player, "I must find the fourth sheep and herd it to the special pen.", line++); + } + } + } + + if(stage >= 100) { + line(player, "I equipped a prod to herd the diseased sheep and then I", line++, true); + line(player, "used it to incinerate all four plagued sheep.", line++, true); + line(player, "I returned to let Councillor Halgrive know that the plagued", line++, true); + line(player, "sheep were no more and claimed my reward.", line++, true); + line++; + line(player, "%%QUEST COMPLETE!&&", line++, false); } } } diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt index 0cfea665d..a2692b439 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt @@ -29,20 +29,7 @@ class ScorpionCatcher : Quest("Scorpion Catcher", 108, 107, 1, 76, 0, 1, 6) { override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) - var ln = 11 - - /** - * Just draw this if the quest is done - */ - if (stage == QUEST_STATE_DONE) { - ln++ - line(player, "I helped !!Thormac?? get his scorpions back.", ln++) - line(player, "Now he can upgrade my battlestaffs into mystic staffs.", ln) - ln++ - ln++ - line(player, "QUEST COMPLETE!", ln) - return - } + var ln = 12 val caughtTaverly = player!!.getAttribute(ATTRIBUTE_TAVERLY, false) val caughtBarb = player.getAttribute(ATTRIBUTE_BARB, false) @@ -54,51 +41,92 @@ class ScorpionCatcher : Quest("Scorpion Catcher", 108, 107, 1, 76, 0, 1, 6) { ln++ //blank line line(player, "Requirements:", ln++) line(player, "Level 31 Prayer", ln, player.skills.staticLevels[Skills.PRAYER] >= 31) - } - else { - line(player, "Speak to Thormac.", ln++, true) - ln++ + } else { + line(player, "I've spoken to Thormac in the Sorcerer's Tower south-west", ln++, true) + line(player, "of Catherby. He's lost his pet Kharid Scorpions and needs", ln++, true) + line(player, "my help to find them.", ln++, true) - if (stage == QUEST_STATE_TALK_SEERS) { - line(player, "I've spoken to !!Thormac?? in the !!Sorcerer's Tower?? south-west of !!Catherby.??", ln++) - line(player, "He's lost his pet !!Kharid Scorpions?? and needs my help to find them.", ln++) - // Todo check this line - line(player, "He's told me to ask a !!Seer?? for help.", ln) + // 10 -> 20 + if (stage >= QUEST_STATE_DARK_PLACE) { + ln++ + line(player, "I've spoken to a Seer and been given the location of one", ln++, true) + line(player, "of the Kharid Scorpions.", ln++, true) + } else if (stage >= QUEST_STATE_TALK_SEERS) { + ln++ + line(player, "I need to go to the !!Seers' Village?? and talk to the !!Seer??", ln++) + line(player, "about the lost !!Kharid Scorpions??.", ln++) } - else { - // todo check this line - line(player, "I talked to a Seer. He told me where I should look.", ln++, caughtTaverly) + + // 20 -> 20 + 1st Scorpion + if (stage >= QUEST_STATE_DARK_PLACE && caughtTaverly || stage >= QUEST_STATE_OTHER_SCORPIONS) { ln++ - line(player, "The first !!Kharid Scorpion?? is in a secret room near some", ln++, caughtTaverly) - line(player, "nasty spiders with two coffins nearby.", ln++, caughtTaverly) + line(player, "The first Kharid Scorpion is in a secret room near some", ln++, true) + line(player, "nasty spiders with two coffins nearby.", ln++, true) + } else if (stage >= QUEST_STATE_DARK_PLACE) { ln++ - if (stage == QUEST_STATE_DARK_PLACE && caughtTaverly){ - // Todo check this line - line(player, "I should go back to the Seer and ask about the other scorpions.", ln++) - } + line(player, "The first !!Kharid Scorpion?? is in a secret room near some", ln++) + line(player, "!!nasty spiders?? with two !!coffins?? nearby.", ln++) + // Jan 21, 2010 version has a slightly updated but similar location. +// line(player, "The first !!Kharid Scorpion?? is in a !!dark place between a lake??", ln++) +// line(player, "and a !!holy island??. It will be close when you enter.", ln++) + ln++ + line(player, "I'll need to talk to a !!Seer?? again one I've caught the first", ln++) + line(player, "!!Kharid Scorpion??.", ln++) + } - if (stage >= QUEST_STATE_OTHER_SCORPIONS){ - val barb_strike = caughtBarb || (stage == QUEST_STATE_PEKSA_HELP) - line(player, "The second !!Kharid Scorpion?? has been in a !!village of??", ln++, barb_strike) - line(player, "!!uncivilised-looking warriors in the east.?? It's been picked up", ln++, barb_strike) - line(player, "by some sort of !!merchant??", ln++, barb_strike) + // 20 + 1st Scorpion -> 30 + if (stage >= QUEST_STATE_OTHER_SCORPIONS) { + // This line disappears when the you talk to the Seer again. + } else if (stage >= QUEST_STATE_DARK_PLACE && caughtTaverly){ + // Todo check this line + ln++ + line(player, "I should go back to the Seer and ask about the other", ln++) + line(player, "scorpions.", ln++) + } + + // 30 -> 40 + if (stage >= QUEST_STATE_OTHER_SCORPIONS){ + ln++ + val barb_strike = caughtBarb || (stage == QUEST_STATE_PEKSA_HELP) + line(player, "The second !!Kharid Scorpion?? has been in a !!village of??", ln++, barb_strike || stage == QUEST_STATE_DONE) + line(player, "!!uncivilised-looking warriors in the east??. It's been picked up", ln++, barb_strike || stage == QUEST_STATE_DONE) + line(player, "by some sort of !!merchant??.", ln++, barb_strike || stage == QUEST_STATE_DONE) + // Jan 21, 2010 version has a slightly updated but similar location. +// line(player, "The second !!Kharid Scorpion?? was once in a !!village two??", ln++, barb_strike || stage == QUEST_STATE_DONE) +// line(player, "!!canoe trips from lumbridge??. A !!shopkeeper?? there picked it up.", ln++, barb_strike || stage == QUEST_STATE_DONE) + if (stage == QUEST_STATE_PEKSA_HELP){ + // todo check this block ln++ - if (stage == QUEST_STATE_PEKSA_HELP){ - // todo check this block - line(player, "I spoke with !!Peksa?? who said he sent it to his brother", ln++, caughtBarb) - line(player, "at the !!Barbarian outpost.??", ln++, caughtBarb) - ln++ - } - - line(player, "The third !!Kharid Scorpion?? is in some sort of !!upstairs room??", ln++, caughtMonk) - line(player, "with !!brown clothing on a table??", ln++, caughtMonk) + line(player, "I spoke with !!Peksa?? who said he sent it to his brother", ln++, caughtBarb) + line(player, "at the !!Barbarian outpost.??", ln++, caughtBarb) } + ln++ + line(player, "The third !!Kharid Scorpion?? is in some sort of !!upstairs room??", ln++, caughtMonk || stage == QUEST_STATE_DONE) + line(player, "with !!brown clothing on a table??.", ln++, caughtMonk || stage == QUEST_STATE_DONE) + // Jan 21, 2010 version has a slightly updated but similar location. +// line(player, "The third !!Kharid Scorpion?? is in an !!upstairs room?? with !!brown??", ln++, caughtMonk || stage == QUEST_STATE_DONE) +// line(player, "!!clothing on a table?? The clothing is adorned with a golden", ln++, caughtMonk || stage == QUEST_STATE_DONE) +// line(player, "four-pointed star. You should start looking where monks", ln++, caughtMonk || stage == QUEST_STATE_DONE) +// line(player, "reside.", ln++, caughtMonk || stage == QUEST_STATE_DONE) + } - if (caughtBarb && caughtTaverly && caughtMonk && stage >= QUEST_STATE_OTHER_SCORPIONS){ - ln++ - line(player, "I should tell !!Thormac?? I have all of his scorpions.", ln) - } + // 40 -> 100 + if (stage == QUEST_STATE_DONE) { + // This line disappears when you complete the quest. + } else if (caughtBarb && caughtTaverly && caughtMonk && stage >= QUEST_STATE_OTHER_SCORPIONS){ + ln++ + line(player, "I need to take the !!Kharid Scorpions?? to !!Thormac??.", ln) + } + // 100 + if (stage == QUEST_STATE_DONE) { + ln++ + line(player, "I've spoken to Thormac and he thanked me for finding his", ln++, true) + line(player, "pet Kharid Scorpions.", ln++, true) + ln++ + ln++ + line(player, "QUEST COMPLETE!", ln) + return } } diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt index a368c031d..8e15ec769 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt @@ -136,23 +136,23 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { line(player, "the exams.", line++) } if (stage >= 4 || getAttribute(player, attributeStudentBrownExam1Talked, false)) { - line(player, "I need to speak to the student in the brown top about the", line++, true) + line(player, "I need to speak to the student in the orange top about the", line++, true) line(player, "exams.", line++, true) } else if (stage >= 3) { - line(player, "I need to speak to the student in the brown top about the", line++) + line(player, "I need to speak to the student in the orange top about the", line++) line(player, "exams.", line++) } if (stage >= 4 || getAttribute(player, attributeStudentGreenExam1ObtainAnswer, false)) { line(player, "I have agreed to help the student in the green top.", line++, true) - line(player, "He has lost his animal skull and thinks he may have", line++, true) - line(player, "dropped it around the site. I need to find it and return", line++, true) - line(player, "it to him. Maybe one of the workmen has picked it up?", line++, true) + line(player, "He has lost his Animal Skull and thinks he may have", line++, true) + line(player, "dropped it around the digsite. I need to find it and return it", line++, true) + line(player, "to him. Maybe one of the workmen has picked it up?", line++, true) } else if (stage >= 3 && getAttribute(player, attributeStudentGreenExam1Talked, false)) { line(player, "I have agreed to help the student in the green top.", line++) - line(player, "He has lost his animal skull and thinks he may have", line++) - line(player, "dropped it around the site. I need to find it and return", line++) - line(player, "it to him. Maybe one of the workmen has picked it up?", line++) + line(player, "He has lost his !!Animal Skull?? and thinks he may have", line++) + line(player, "dropped it around the digsite. I need to find it and return it", line++) + line(player, "to him. Maybe one of the workmen has picked it up?", line++) } if (stage >= 4) { line(player, "I should talk to him to see if he can help with my exams.", line++, true) @@ -166,38 +166,36 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { if (stage >= 4 || getAttribute(player, attributeStudentPurpleExam1ObtainAnswer, false)) { line(player, "I have agreed to help the student in the purple skirt.", line++, true) - line(player, "She has lost her lucky teddy bear mascot and thinks she", line++, true) - line(player, "may have dropped it by the strange relic at the centre of", line++, true) - line(player, "the campus, maybe in a bush. I need to find it and return", line++, true) - line(player, "it to her.", line++, true) + line(player, "She has lost her Lucky Mascot and thinks she may have", line++, true) + line(player, "dropped it around the large urns on the digsite. I need to", line++, true) + line(player, "find it and return it to her.", line++, true) } else if (stage >= 3 && getAttribute(player, attributeStudentPurpleExam1Talked, false)) { line(player, "I have agreed to help the student in the purple skirt.", line++) - line(player, "She has lost her lucky teddy bear mascot and thinks she", line++) - line(player, "may have dropped it by the strange relic at the centre of", line++) - line(player, "the campus, maybe in a bush. I need to find it and return", line++) - line(player, "it to her.", line++) + line(player, "She has lost her !!Lucky Mascot?? and thinks she may have", line++) + line(player, "dropped it around the large urns on the digsite. I need to", line++) + line(player, "find it and return it to her.", line++) } if (stage >= 4) { line(player, "I should talk to her to see if she can help with my exams.", line++, true) - line(player, "She gave me an answer to one of the questions on the first", line++, true) - line(player, "exam.", line++, true) + line(player, "She gave me an answer to one of the questions on the", line++, true) + line(player, "first exam.", line++, true) } else if (stage >= 3 && getAttribute(player, attributeStudentPurpleExam1ObtainAnswer, false)) { line(player, "I should talk to her to see if she can help with my exams.", line++) - line(player, "She gave me an answer to one of the questions on the first", line++) - line(player, "exam.", line++) + line(player, "She gave me an answer to one of the questions on the", line++) + line(player, "first exam.", line++) } if (stage >= 4 || getAttribute(player, attributeStudentBrownExam1ObtainAnswer, false)) { - line(player, "I have agreed to help the student in the brown top.", line++, true) - line(player, "He has lost his special cup and thinks he may have dropped", line++, true) - line(player, "it while he was near the panning site, possibly in the", line++, true) - line(player, "water. I need to find it and return it.", line++, true) + line(player, "I have agreed to help the student in the orange top.", line++, true) + line(player, "He has lost his Special Cup and thinks he may have", line++, true) + line(player, "dropped it around the tents near the panning site. I need", line++, true) + line(player, "to find it and return it.", line++, true) } else if (stage >= 3 && getAttribute(player, attributeStudentBrownExam1Talked, false)) { - line(player, "I have agreed to help the student in the brown top.", line++) - line(player, "He has lost his special cup and thinks he may have dropped", line++) - line(player, "it while he was near the panning site, possibly in the", line++) - line(player, "water. I need to find it and return it.", line++) + line(player, "I have agreed to help the student in the orange top.", line++) + line(player, "He has lost his !!Special Cup?? and thinks he may have", line++) + line(player, "dropped it around the tents near the panning site. I need", line++) + line(player, "to find it and return it.", line++) } if (stage >= 4) { line(player, "I should talk to him to see if he can help with my exams.", line++, true) @@ -226,11 +224,11 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { } if (stage >= 5) { - line(player, "I need to study for my second exam. Perhaps the students", line++, true) - line(player, "on the site can help?", line++, true) + line(player, "I need to study for my second exam. Perhaps the three", line++, true) + line(player, "students on the digsite can help me again?", line++, true) } else if (stage >= 4) { - line(player, "I need to study for my second exam. Perhaps the students", line++) - line(player, "on the site can help?", line++) + line(player, "I need to study for my second exam. Perhaps the three", line++) + line(player, "students on the digsite can help me again?", line++) } if (stage >= 5 || getAttribute(player, attributeStudentGreenExam2ObtainAnswer, false)) { line(player, "I need to speak to the student in the green top about the", line++, true) @@ -241,16 +239,16 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { } if (stage >= 5 || getAttribute(player, attributeStudentPurpleExam2ObtainAnswer, false)) { line(player, "I need to speak to the student in the purple skirt about", line++, true) - line(player, "the exams. 2 ", line++, true) + line(player, "the exams.", line++, true) } else if (stage >= 4) { line(player, "I need to speak to the student in the purple skirt about", line++) line(player, "the exams.", line++) } if (stage >= 5 || getAttribute(player, attributeStudentBrownExam2ObtainAnswer, false)) { - line(player, "I need to speak to the student in the brown top about the", line++, true) + line(player, "I need to speak to the student in the orange top about the", line++, true) line(player, "exams.", line++, true) } else if (stage >= 4) { - line(player, "I need to speak to the student in the brown top about the", line++) + line(player, "I need to speak to the student in the orange top about the", line++) line(player, "exams.", line++) } if (stage >= 5) { @@ -269,11 +267,11 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { } if (stage >= 6) { - line(player, "I need to study for my third exam. Perhaps the students", line++, true) - line(player, "on the site can help?", line++, true) + line(player, "I should research for my third exam. Perhaps the students", line++, true) + line(player, "can help me again?", line++, true) } else if (stage >= 5) { - line(player, "I need to study for my third exam. Perhaps the students", line++) - line(player, "on the site can help?", line++) + line(player, "I should research for my third exam. Perhaps the students", line++) + line(player, "can help me again?", line++) } if (stage >= 6 || getAttribute(player, attributeStudentGreenExam3ObtainAnswer, false)) { line(player, "I need to speak to the student in the green top about the", line++, true) @@ -284,7 +282,7 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { } if (stage >= 6 || getAttribute(player, attributeStudentPurpleExam3Talked, false)) { line(player, "I need to speak to the student in the purple skirt about", line++, true) - line(player, "the exams. 3", line++, true) + line(player, "the exams.", line++, true) } else if (stage >= 5) { line(player, "I need to speak to the student in the purple skirt about", line++) line(player, "the exams.", line++) @@ -295,10 +293,10 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { line(player, "I need to bring her an Opal.", line++) } if (stage >= 6 || getAttribute(player, attributeStudentBrownExam3ObtainAnswer, false)) { - line(player, "I need to speak to the student in the brown top about the", line++, true) + line(player, "I need to speak to the student in the orange top about the", line++, true) line(player, "exams.", line++, true) } else if (stage >= 5) { - line(player, "I need to speak to the student in the brown top about the", line++) + line(player, "I need to speak to the student in the orange top about the", line++) line(player, "exams.", line++) } if (stage >= 6) { diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/SinkethsDiary.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/SinkethsDiary.kt index 57b98c3e2..79a1f59cc 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/SinkethsDiary.kt +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/SinkethsDiary.kt @@ -10,8 +10,8 @@ import core.game.interaction.InteractionListener import core.game.node.entity.player.Player import org.rs09.consts.Items -class SinkethsDiary - : InteractionListener { +// This is not formatted well. See _-88E9n9jWA +class SinkethsDiary : InteractionListener { // Obtainable during the What Lies Below quest. companion object { private val TITLE = "Sin'keth's diary" diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt index 2ec8f69a3..b97a4fd07 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt @@ -111,12 +111,10 @@ class AllFiredUp : Quest("All Fired Up", 157, 156, 1){ line(player, "restore a beacon to its blazing state. I've tended the", line++, true) line(player, "beacon near Blaze and have reported back to him.", line++, true) } else if (stage == 80) { - line(player, "!!Blaze?? has now asked me to maintain the nearby !!beacon??.", line++, false) - line(player, "To maintain the !!beacon??, I need to add !!five logs?? of the same", line++, false) - line(player, "type.", line++, false) - line(player, "I've placed five logs on the !!beacon?? to restore it to its", line++, false) - line(player, "blazing state. Now that it's blazing brightly, perhaps I should", line++, false) - line(player, "speak with Blaze.", line++, false) + line(player, "!!Blaze?? has explained how to maintain a beacon. When the", line++, false) + line(player, "fire begins to die out, !!five more logs?? can be added to", line++, false) + line(player, "restore a beacon to its blazing state.", line++, false) + line(player, "!!Blaze?? has asked me to maintain the !!beacon?? nearest him.", line++, false) } if (stage > 90) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java index b31d5b058..6f53a36fc 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java @@ -78,16 +78,6 @@ public class WhatLiesBelow extends Quest { */ public static final Item BEACON_RING = new Item(Items.BEACON_RING_11014); - /** - * The requirement messages. - */ - private static final String[] REQS = new String[] { - "Have level 35 Runecrafting.", - "Be able to defeat a level 47 enemy.", - "I need to have completed the Rune Mysteries quest.", - "Have a Mining level of 42 to use the Chaos Tunnel." - }; - /** * The requirements. */ @@ -109,36 +99,81 @@ public class WhatLiesBelow extends Quest { @Override public void drawJournal(Player player, int stage) { super.drawJournal(player, stage); - switch (stage) { - case 0: - line(player, "I can start this quest by speaking to Rat Burgiss on theroad south of Varrock.Before I begin I will need to:" + getReqMessage(player), 11); - break; - case 10: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.I need to kill outlaws west of Varrock so that I can collect 5 of Rat's papers.", 11); - break; - case 20: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.I need to kill outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magisin Varrock.", 11); - break; - case 30: - case 40: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also needto find or buy an empty bowl.", 11); - break; - case 50: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to take the glowing wand I have created back to Surok in Varrockwith an empty bowl.I need to deliver Surok's letter to Rat who is waiting for me southof Varrock. I should speak to Rat again; he is waiting for me south of Varrock", 11); - break; - case 60: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to take the glowing wand I have created back to Surok in Varrockwith an empty bowl.I need to deliver Surok's letter to Rat who is waiting for me southof Varrock.I should speak to Rat again; he is waiting for me south of VarrockI need to speak to Zaff of Zaff's Staffs in Varrock.", 11); - break; - case 70: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to take the glowing wand I have created back to Surok in Varrockwith an empty bowl.I need to deliver Surok's letter to Rat who is waiting for me southof Varrock.I should speak to Rat again; he is waiting for me south of VarrockI need to speak to Zaff of Zaff's Staffs in Varrock.I need to tell Surok in Varrock that he is under arrest.", 11); - break; - case 80: - case 90: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to take the glowing wand I have created back to Surok in Varrockwith an empty bowl.I need to deliver Surok's letter to Rat who is waiting for me southof Varrock.I should speak to Rat again; he is waiting for me south of VarrockI need to speak to Zaff of Zaff's Staffs in Varrock.I need to tell Surok in Varrock that he is under arrest.I need to defeat King Roald in Varrock so that Zaff can remove themind-control spell.I need to tell Rat what has happened; he is waiting for mesouth of Varrock.", 11); - break; - case 100: - line(player, "Rat, a trader in Varrock, has asked me to help him with a task.Surok, a Wizard in Varrock, has asked me to complete a task for him.I need to kill the outlaws west of Varrock so that I can collect5 of Rat's papers.I have delivered Rat's folder to him. Perhaps Ishould speak to him again.I need to deliver Rat's letter to Surok Magis in Varrock. I need to talk to Surok about thesecret he has for me.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to infuse the metal wand with chaos runes at the Chaos Altar.I also need to find or buy an empty bowl.I need to take the glowing wand I have created back to Surok in Varrockwith an empty bowl.I need to deliver Surok's letter to Rat who is waiting for me southof Varrock.I should speak to Rat again; he is waiting for me south of VarrockI need to speak to Zaff of Zaff's Staffs in Varrock.I need to tell Surok in Varrock that he is under arrest.I need to defeat King Roald in Varrock so that Zaff can remove themind-control spell.I need to tell Rat what has happened; he is waiting for mesouth of Varrock.QUEST COMPLETE!I have been given information about the Chaos Tunnel.Zaff has given me the Beacon Ring.", 11); - break; + var line = 12; + + if(stage == 0){ + line(player, "I can start this quest by speaking to !!Rat Burgiss?? on the", line++); + line(player, "road south of !!Varrock??.", line++); + line(player, "Before I begin I will need to:", line++); + line(player, "Have level 35 !!Runecrafting??.", line++, getStatLevel(player, Skills.RUNECRAFTING) >= 35); + line(player, "Be able to defeat a !!level 47 enemy??.", line++); + line(player, "I need to have completed the !!Rune Mysteries?? quest.", line++, isQuestComplete(player, "Rune Mysteries")); + line(player, "Have a !!Mining?? level of 42 to use the !!Chaos Tunnel??.", line++, getStatLevel(player, Skills.MINING) >= 42); + } else { + // These are somehow at the top with different stage when crossed out. + if (stage >= 10) { + line(player, "!!Rat??, a trader in Varrock, has asked me to help him with a", line++, stage >= 30); + line(player, "task.", line++, stage >= 30); + } + if (stage >= 30) { + line(player, "!!Surok??, a Wizard in Varrock, has asked me to complete a", line++, stage >= 50); + line(player, "task for him.", line++, stage >= 50); + } + // End + + if (stage >= 10) { + line(player, "I need to kill !!outlaws?? west of Varrock so that I can collect 5", line++, stage >= 20); + line(player, "of Rat's !!papers??.", line++, stage >= 20); + if (inInventory(player, Items.FULL_FOLDER_11007, 1)) { + line(player, "I should take the !!full folder?? back to Rat.", line++); + } + } + if (stage >= 20) { + line(player, "I have delivered Rat's folder to him. Perhaps I should", line++, stage >= 30); + line(player, "should speak to him again.", line++, stage >= 30); + // Should be separated stages + line(player, "I need to deliver !!Rat's?? letter to !!Surok Magis?? in !!Varrock??.", line++, stage >= 30); + // Should be separated stages + line(player, "I need to talk to !!Surok?? about the secret he has for me.", line++, stage >= 30); + } + if (stage >= 30) { + line(player, "I need to infuse the !!metal wand?? with !!chaos runes?? at the", line++, stage >= 50); + line(player, "!!Chaos Altar??. I also need to find or buy an empty !!bowl??.", line++, stage >= 50); + } + if (stage >= 50) { + line(player, "I need to take the !!glowing wand?? I have created back to", line++, true); + line(player, "!!Surok?? in Varrock along with an empty !!bowl??.", line++, true); + // Should be separated stages + line(player, "I need to deliver !!Surok's letter?? to !!Rat?? who is waiting for me", line++, true); + line(player, "south of Varrock.", line++, true); + // Should be separated stages + line(player, "I should speak to !!Rat?? again; he is waiting for me south of", line++, stage >= 60); + line(player, "Varrock.", line++, stage >= 60); + } + if (stage >= 60) { + line(player, "I need to speak to !!Zaff?? of !!Zaff's Staffs?? in Varrock.", line++, stage >= 70); + } + if (stage >= 70) { + line(player, "I need to tell !!Surok?? in Varrock that he is under arrest.", line++, stage >= 80); + } + if (stage >= 80) { + line(player, "I need to defeat !!King Roald?? in Varrock so that !!Zaff?? can", line++, true); + line(player, "remove the mind-control spell.", line++, true); + // Should be separated stages + line(player, "I need to tell !!Rat?? what has happened; he is waiting for me", line++, stage >= 100); + line(player, "south of Varrock.", line++, stage >= 100); + } + if (stage >= 100) { + line++; + line++; + line(player,"QUEST COMPLETE!", line++); + line++; + line(player, "I have been given information about the !!Chaos Tunnel??.", line++); + line(player, "Zaff has given me the !!Beacon Ring??.", line++); + line++; + line(player, "I have also been given !!8,000 Runecrafting XP, 2000??.", line++); + line(player, "!!Defence XP?? and !!1 Quest Point??.", line++); + } } } @@ -161,22 +196,6 @@ public class WhatLiesBelow extends Quest { player.getQuestRepository().syncronizeTab(player); } - /** - * Gets the req message. - * @return the message. - */ - public String getReqMessage(Player player) { - hasRequirements(player); - String s = ""; - for (int i = 0; i < requirements.length; i++) { - String l = REQS[i]; - if (requirements[i]) { - l = l.replace("", "").replace("", "").trim(); - } - s += (requirements[i] ? "" : "") + l + ""; - } - return s; - } @Override public boolean hasRequirements(Player player) { diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt index 3e3b3137b..4b35fb36b 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt @@ -67,12 +67,13 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, } else if (stage >= 1) { line(player, "I should go up to the castle and speak to !!Dr Fenkenstrain??", line++, false) } - line++ if (stage >= 3) { - line(player, "I gave a torso, some arms and legs, and a head to Fenkenstrain,", line++, true) - line(player, "who then wanted a needle and 5 lots of thread, so that he could", line++, true) - line(player, "sew the bodyparts together and create his creature.", line++, true) + line(player, "I gave a torso, some arms and legs, and a head to", line++, true) + line(player, "Fenkenstrain, who then wanted a needle and 5 lots of", line++, true) + line(player, "thread, so that he could sew the bodyparts together and", line++, true) + line(player, "create his creature.", line++, true) } else if (stage >= 2) { + line++ line(player, "I need to find these body parts for !!Fenkenstrain??:", line++, false) line(player, "a pair of !!arms??", line++, false) line(player, "a pair legs !!legs??", line++, false) @@ -84,7 +85,6 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line(player, "elsewhere, so perhaps I should look at the graves in the", line++, false) line(player, "local area", line++, false) } - line++ if (stage >= 4) { line(player, "I brought Fenkenstrain a needle and 5 quantities of", line++, true) line(player, "thread.", line++, true) @@ -92,15 +92,13 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line(player, "I need to bring !!Fenkenstrain?? a !!needle?? and !!5 quantities??", line++, false) line(player, "!!of thread??.", line++, false) } - line++ if (stage >= 5) { line(player, "I repaired the lightning conductor, and Fenkenstrain", line++, true) line(player, "brought the Creature to life.", line++, true) } else if (stage >= 4) { - line(player, "I need to repair the !!lightning conductor?? on the", line++, false) - line(player, "!!balcony?? above.", line++, false) + line(player, "!!Fenkenstrain?? has ordered me to repair the lightning", line++, false) + line(player, "conductor.", line++, false) } - line++ if (stage == 5) { line(player, "!!Fenkenstrain?? wants to talk to me.", line++, false) line++ @@ -115,10 +113,9 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line(player, "The !!Creature?? went on a rampage, and !!Fenkenstrain?? wants", line++, false) line(player, "me to go up the !!Tower?? to destroy it.", line++, false) } - line++ if (stage >= 8) { - line(player, "I stole Fenkenstrain's Ring of Charos, and he released me from", line++, true) - line(player, "his service.", line++, true) + line(player, "I stole Fenkenstrain's Ring of Charos, and he released", line++, true) + line(player, "me from his service.", line++, true) } else if (stage >= 7) { line(player, "I must find a way to stop Fenkenstrain's experiments.", line++, false) } diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt index 026a4c04e..152254698 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt @@ -16,92 +16,179 @@ class NatureSpiritQuest : Quest("Nature Spirit", 95, 94, 2, 307, 0, 1, 110 ) { override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) player ?: return - var line = 11 + var line = 12 if(stage == 0){ - line(player, "I can start this quest by speaking to !!Drezel?? in the !!temple of Saradomin??.", line++) - } else { - if(stage >= 10){ - line(player, "After talking to Drezel in the temple of Saradomin I've",line++, true) - line(player,"agreed to look for a Druid called Filliman Tarlock.", line++, true) + line(player, "I can start this quest by speaking to !!Drezel?? in the temple.", line++) + line(player, /* The "to" is [sic] */"to !!Saradomin?? at the mouth of the river !!Salve??.", line++) + line(player, "I first need to complete :", line++) + line(player, "!!The Restless Ghost.??", line++, isQuestComplete(player, "The Restless Ghost")) + line(player, "!!Priest in Peril.??", line++, isQuestComplete(player, "Priest in Peril")) + if (isQuestComplete(player, "The Restless Ghost") && isQuestComplete(player, "Priest in Peril")) { + line(player, "I've completed all the quest requirements.", line++) } + line(player, "In order to complete this quest !!level 18 crafting?? would be", line++, getStatLevel(player, Skills.CRAFTING) >= 18) + line(player, "an advantage.", line++, getStatLevel(player, Skills.CRAFTING) >= 18) + if (getStatLevel(player, Skills.CRAFTING) >= 18) { + line(player, "I have a suitable crafting level for this quest.", line++) + } + if (isQuestComplete(player, "The Restless Ghost") && isQuestComplete(player, "Priest in Peril") && getStatLevel(player, Skills.CRAFTING) >= 18) { + line(player, "I have all the requirements for this quest.", line++) + } + } else if (stage < 100) { + line(player, "After talking to Drezel in the temple of Saradomin I've", line++, true) + line(player, "agreed to look for a Druid called Filliman Tarlock.", line++, true) - if(stage == 10){ - line(player, "I need to look for !!Filliman Tarlock?? in the !!Swamps?? of Mort",line++) + if (stage >= 15) { + line(player, "I've found a spirit in the swamp which I think might be", line++, true) + line(player, "Filliman Tarlock.", line++, true) + } else if (stage >= 10) { + line(player, "I need to look for !!Filliman Tarlock?? in the !!Swamps?? of Mort", line++) line(player, "Myre. I should be wary of !!Ghasts??.", line++) } - if(stage == 15){ - line(player, "I located a !!spirit?? in the swamp. I believe he's", line++, false) - line(player, "!!Filliman Tarlock?? but I can't understand him.",line++, false) + if (stage >= 20) { + line(player, "I've communicated with Fillman using the amulet of", line++, true) + line(player, "ghostspeak.", line++, true) + } else if (stage >= 15) { + // Questionable + line(player, "I located a !!spirit?? in the swamp. I believe he's", line++) + line(player, "!!Filliman Tarlock?? but I can't understand him.", line++) } - if(stage == 20){ - line(player, "I located !!Filliman Tarlock?? in the swamp. I believe he's",line++) - line(player, "dead but he doesn't believe me. I need to convince him.", line++) + if (stage >= 25) { + line(player, "I managed to convince Fillman that he's a ghost.", line++, true) + } else if (stage >= 20) { + line(player, "I think I need to convince this poor fellow !!Tarlock?? that he's", line++) + line(player, "actually !!dead??!", line++) } - if(stage >= 25){ - line(player, "I located Filliman Tarlock in the swamp and managed to",line++,true) - line(player, "convince him that he is in fact a ghost. ", line++, true) + if (stage >= 30) { + line(player, "Fillman is looking for his journal to help him plan what his", line++, true) + line(player, "next step is.", line++, true) + line(player, "I've given Filliman his journal. I wonder what he plans to do", line++, true) + line(player, "now?", line++, true) + } else if (stage >= 25){ + line(player, "Fillman is looking for his !!journal?? to help him plan what his", line++, true) + line(player, "next step is.", line++, true) + // Questionable +// line(player, "Filliman needs his !!journal?? to figure out what to do",line++) +// line(player, "next. He mentioned something about a !!knot??.", line++) } - if(stage == 25){ - line(player, "Filliman needs his !!journal?? to figure out what to do",line++) - line(player, "next. He mentioned something about a !!knot??.", line++) + if (stage >= 35) { + line(player, "I've agreed to help Fillman become a nature spirit.", line++, true) + line(player, "I need to find 'something from nature', 'something of", line++, true) + line(player, "faith' and 'something of the spirit-to-become freely", line++, true) + line(player, "given'.", line++, true) + } else if (stage >= 30) { + // Derived by squinting hard + line(player, "!!Filliman?? might need !!my help?? with his !!plan??.", line++) + // Questionable +// line(player, "I should speak to !!Filliman Tarlock?? to see what I can", line++) +// line(player, "do to help.", line++) } - if(stage >= 30){ - line(player, "I recovered Filliman's journal for him.", line++, true) + if (stage >= 40) { + line(player, "Filliman gave me a 'bloom' spell to cast in the swamp.", line++, true) + line(player, "With the bloom spell I can collect 'Something of nature.'", line++, true) + line(player, "I've been blessed at the temple by Drezel.", line++, true) + } else if (stage >= 35) { + line(player, "!!Filliman?? gave me a '!!bloom??' spell but I need to be !!blessed?? at", line++) + line(player, "the !!temple?? before I can cast it. I am supposed to collect", line++) + line(player, "'!!something from nature??'.", line++) } - if(stage == 30) { - line(player, "I should speak to !!Filliman Tarlock?? to see what I can",line++) - line(player, "do to help.", line++) + if (stage >= 45) { + // Disappears. + } else if (stage >= 40) { + line(player, "I should return to !!Filliman?? to see what I need to do.", line++) } - if(stage >= 40){ - line(player, "I've gone and gotten blessed by Drezel.", line++, true) + if (stage in 45 until 55){ + if (NSUtils.hasPlacedFungus(player)) { + line(player, "I've cast the bloom spell in the swamp.", line++, true) + line(player, "I collected a Mort Myre Fungi.", line++, true) + line(player, "I think I have collected 'something of nature'.", line++, true) + } else if (inInventory(player, Items.MORT_MYRE_FUNGUS_2970)) { + line(player, "I've cast the bloom spell in the swamp.", line++, true) + line(player, "I collected a Mort Myre Fungi.", line++, true) + line(player, "I have a !!Mort Myre Fungi??, I hope this is what !!Fillman??",line++) + line(player, "wanted.",line++) + } else { + // Questionable +// if(stage == 50){ +// line(player, "I know for a fact the fungus is !!something of Nature??.", line++, false) +// } + line(player, "I need to collect '!!something of nature??'.", line++) + } + + // Just stand on the damn thing. + line(player, "I need to find '!!something with faith??'.",line++, false) + + if (NSUtils.hasPlacedCard(player)) { + line(player, "The spell scroll was absorbed into the spirit stone I think I", line++, true) + line(player, "have collected 'something of spirit-to-become freely", line++, true) + line(player, "given.'", line++, true) + } else { + line(player, "I need to find :",line++) + line(player, "'!!something of the spirit-to-be freely given??.'", line++) + } } - if(stage >= 35) { - line(player, "I've agreed to help Filliman become a Nature Spirit.",line++, true) + if (stage >= 55) { + line(player, "I managed to get all the required items that Fillman asked.", line++, true) + line(player, "for. He says that he can cast the spell now which will", line++, true) + line(player, "transform him into a Nature Spirit.", line++, true) } - if(stage == 35){ - line(player, "The first thing Filliman needs me to do is go and get",line++) - line(player, "blessed by !!Drezel?? in the temple of Saradomin.",line++) + if (stage >= 60) { + line(player, "I entered Fillimans grotto as he asked me to.", line++, true) // no apostrophe is sic + line(player, "Filliman has turned into a nature spirit, it was an", line++, true) + line(player, "impressive transformation!", line++, true) + line(player, "Filliman says he can help me to defeat the ghasts.", line++, true) + } else if (stage >= 55) { + // Questionable + line(player, "!!Filliman?? has asked me to enter his !!grotto??.", line++) } - if (stage == 40){ - line(player, "I should return to !!Filliman?? to see what I need to do.", line++, false) + if (stage >= 70) { + line(player, "Filliman has blessed the silver sickle for me.", line++, true) + // --- Should be separate stage, but we don't have it. + // line(player, "I need to use the !!sickle?? to make the swamp bloom.", line++) + line(player, "I cast the bloom spell in the swamp.", line++, true) + // --- Should be separate stage, but we don't have it. + // line(player, "I need to collect some !!bloomed items?? from the swamp", line++) + // line(player, "and put them into a druid pouch.", line++) + line(player, "I collected some bloomed items from the swamp an put", line++, true) + line(player, "them into a druid pouch.", line++, true) + } else if (stage >= 60) { + // Questionable + line(player, "I need to bring a silver sickle for !!Filliman?? to bless.", line++) } - - if(stage in 45 until 55){ - line(player, "In order to help Filliman I need to find 3 things:", line++, false) - line(player, "Something of !!Faith??.",line++, false) - line(player, "Something of !!Nature??.", line++, stage >= 50) - line(player, "Something of the !!spirit-to-be freely given??.", line++, false) - } - - if(stage == 50){ - line(player, "I know for a fact the fungus is !!something of Nature??.", line++, false) - } - - if(stage >= 55){ - line(player, "I've helped Filliman complete the spell.", line++, true) - } - - if(stage == 55){ - line(player, "Filliman has asked me to meet him back inside the !!grotto??.", line++, false) - } - - if(stage == 75){ - line(player, "I need to go and kill !!3 Ghasts?? for Filliman.", line++, false) - } - - if(stage >= 100){ - line(player,"%%QUEST COMPLETE!&&",line++) + // We don't have this stage. +// if (stage >= 80) { +// line(player, "The druid pouch made a ghast appear which I attacked and", line++, true) +// line(player, "killed.", line++, true) +// line(player, "I've killed two ghasts now.", line++, true) +// line(player, "I've killed three ghasts now.", line++, true) +// line(player, "I should tell !!Filliman?? that I've killed the !!three ghasts??.", line++, true) +// } else + if (stage >= 75){ + line(player, "!!Filliman?? asked me to kill !!three Ghasts??.", line++, false) } + } else { + // The final text is a summary of the quest. + line(player, "Drezel, a priest of Saradomin, asked me to look for the", line++, true) + line(player, "druid Filliman Tarlock in the swamps of Mort Myre. However", line++, true) + line(player, "Filliman had been slain and appeared as a ghost. After", line++, true) + line(player, "persuading Filliman that he was in fact dead I helped him to", line++, true) + line(player, "make a transformation into a Nature Spirit.", line++, true) + line++ + line(player, "In return for this help Filliman blessed a silver sickle and", line++, true) + line(player, "showed me how to defeat the ghasts of Mort Myre.", line++, true) + line(player, "He also gave me some kill experience in crafting,", line++, true) + line(player, "hitpoints and defence.", line++, true) + line(player, "%%QUEST COMPLETE!&&",line++) } } diff --git a/Server/src/main/core/game/global/action/SpecialLadders.java b/Server/src/main/core/game/global/action/SpecialLadders.java index 278f84f91..96636a068 100644 --- a/Server/src/main/core/game/global/action/SpecialLadders.java +++ b/Server/src/main/core/game/global/action/SpecialLadders.java @@ -25,6 +25,11 @@ public enum SpecialLadders implements LadderAchievementCheck { JATIZSO_SHOUT_TOWER_UP(Location.create(2373, 3800, 2),Location.create(2374, 3800, 0)), JATIZSO_SHOUT_TOWER_DOWN(Location.create(2373, 3800, 0),Location.create(2374, 3800, 2)), + // sendMessage(player, "You descend into the somewhat smoky depths of the well, to the accompaniment of") + // sendMessage(player, "eery wails.") https://youtu.be/x8abdpkJ6ZA + POLLNIVNEACH_SLAYER_DUNGEON_UP(Location.create(3358,2971,0), Location.create(3359,9354,0)), + // sendMessage(player, "You nimbly climb up the bucket rope, emerging into Pollnivneach's bustling square.") https://youtu.be/LVwbmCNjlzQ + POLLNIVNEACH_SLAYER_DUNGEON_DOWN(Location.create(3358,9352,0), Location.create(3358,2970,0)), ALKHARID_ZEKE_UP(Location.create(3284,3186,0), Location.create(3284,3190,1)), ALKHARID_ZEKE_DOWN(Location.create(3284,3190,1), Location.create(3284,3186,0)), ALKHARID_CRAFTING_UP(Location.create(3311,3187,0),Location.create(3314,3187,1)), From 7d32e77860265ccf6d382681716adefdf214a642 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Tue, 8 Oct 2024 06:39:25 +0000 Subject: [PATCH 031/306] Removed unnecessary server console debug prints --- .../main/content/global/skill/agility/WildernessCourse.kt | 6 ------ Server/src/main/core/game/dialogue/DialogueBuilder.kt | 2 +- Server/src/main/core/game/system/timer/impl/Poison.kt | 2 -- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Server/src/main/content/global/skill/agility/WildernessCourse.kt b/Server/src/main/content/global/skill/agility/WildernessCourse.kt index ab6644421..00f08cf31 100644 --- a/Server/src/main/content/global/skill/agility/WildernessCourse.kt +++ b/Server/src/main/content/global/skill/agility/WildernessCourse.kt @@ -116,25 +116,19 @@ class WildernessCourse when (counter++) { 0 -> { AgilityHandler.forceWalk(player, -1, Location.create(x, 3937, 0), Location.create(x, 3940, 0), Animation.create(10580), 15, 0.0, null, 1) //10 - println("1") player.teleporter.send(Location.create(3004, 3947, 0), TeleportManager.TeleportType.INSTANT, TeleportManager.WILDY_TELEPORT) - println("tele") counter++ AgilityHandler.forceWalk(player, 0, Location.create(x, 3948, 0), Location.create(x, 3950, 0), Animation.create(10579), 20, 12.5, null, 5) //20 - println("3") return true } 2 -> { player.teleporter.send(Location.create(3004, 3947, 0), TeleportManager.TeleportType.INSTANT, TeleportManager.WILDY_TELEPORT) - println("tele") counter++ AgilityHandler.forceWalk(player, 0, Location.create(x, 3948, 0), Location.create(x, 3950, 0), Animation.create(10579), 20, 12.5, null, 5) - println("3") return true } 3 -> { AgilityHandler.forceWalk(player, 0, Location.create(x, 3948, 0), Location.create(x, 3950, 0), Animation.create(10579), 20, 12.5, null, 5) - println("3") return true } } diff --git a/Server/src/main/core/game/dialogue/DialogueBuilder.kt b/Server/src/main/core/game/dialogue/DialogueBuilder.kt index 9d3107406..cdf781cb9 100644 --- a/Server/src/main/core/game/dialogue/DialogueBuilder.kt +++ b/Server/src/main/core/game/dialogue/DialogueBuilder.kt @@ -5,7 +5,7 @@ import core.game.node.entity.player.Player import core.tools.END_DIALOGUE import java.util.regex.Pattern -val DEBUG_DIALOGUE = true +val DEBUG_DIALOGUE = false val NUMBER_PATTERN1 = Pattern.compile("^(\\d+) \\[label", Pattern.MULTILINE) val NUMBER_PATTERN2 = Pattern.compile("(\\d+) -> (\\d+)") diff --git a/Server/src/main/core/game/system/timer/impl/Poison.kt b/Server/src/main/core/game/system/timer/impl/Poison.kt index 2f4c58cf9..6f87d40a9 100644 --- a/Server/src/main/core/game/system/timer/impl/Poison.kt +++ b/Server/src/main/core/game/system/timer/impl/Poison.kt @@ -62,8 +62,6 @@ class Poison : PersistTimer (30, "poison", flags = arrayOf(TimerFlag.ClearOnDeat override fun getTimer (vararg args: Any) : RSTimer { val timer = Poison() - for (arg in args) - println(arg) timer.damageSource = args[0] as? Entity ?: return timer timer.severity = args[1] as? Int ?: return timer return timer From 01b5e59250e851782feea8a3b865320bab5773f6 Mon Sep 17 00:00:00 2001 From: "Tobias H." Date: Tue, 8 Oct 2024 06:57:51 +0000 Subject: [PATCH 032/306] Fixed missing space in pottery messages --- .../content/global/skill/crafting/pottery/FirePotteryPulse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/crafting/pottery/FirePotteryPulse.java b/Server/src/main/content/global/skill/crafting/pottery/FirePotteryPulse.java index e7af471ef..e4cf4ec71 100644 --- a/Server/src/main/content/global/skill/crafting/pottery/FirePotteryPulse.java +++ b/Server/src/main/content/global/skill/crafting/pottery/FirePotteryPulse.java @@ -56,7 +56,7 @@ public final class FirePotteryPulse extends SkillPulse { return false; } if (!player.getInventory().containsItem(pottery.getUnfinished())) { - player.getPacketDispatch().sendMessage("You need a " + pottery.name().toLowerCase() + "in order to do this."); + player.getPacketDispatch().sendMessage("You need a " + pottery.name().toLowerCase() + " in order to do this."); return false; } return true; From 034c05f5126b35cb708b41e408c7d6b917ed68b9 Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Tue, 8 Oct 2024 07:19:23 +0000 Subject: [PATCH 033/306] Fixed Mystic Lava staff not counting as earth runes --- .../src/main/core/game/node/entity/combat/spell/MagicStaff.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicStaff.java b/Server/src/main/core/game/node/entity/combat/spell/MagicStaff.java index 103a63264..6664e721b 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicStaff.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicStaff.java @@ -27,7 +27,7 @@ public enum MagicStaff { /** * Represents the earth rune staves. */ - EARTH_RUNE(557, 3053, 3055, 3056, 1385, 1399, 1407, 557, 6563, 6562); + EARTH_RUNE(557, 3053, 3054, 3055, 3056, 1385, 1399, 1407, 557, 6563, 6562); /** * The magic staves mapping. From 59075798ea58677019b15a3807c632406fd6cd14 Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 10 Oct 2024 07:08:57 +0000 Subject: [PATCH 034/306] Adventure bot improvements Adjusted max pulse count for bots from 50 -> 75 Adjusted max skill baseline by +4 for adventure bots to 69 Added 500 lines of unique Added 45000 bot names Added recovery methods for bots that get stuck Added multiple random number functions to help add more variance Added function to handle checking if a bot is near/in a Bank Added function to handle getting a new city Added function to add variability to locations given to bots Added function to check if other players/bots are nearby Added function to handle bots banking their inventories if a bank booth is nearby Improved random number parameters Improved how bots are spawned & added variance to spawn location Improved how bots interact & handle the Grand Exchange location Improved how bots handle starting in Lumbridge Fixed bots referencing themselves in dialogue Fixed bots talking when they are by themselves Fixed multiple cases where bots would get stuck in a state Fixed multiple logic errors Fixed issues with bots banking but not switching states --- Server/data/botdata/bot_dialogue.json | 545 +- Server/data/botdata/botnames.txt | 32971 +++++++++++++++- .../main/content/global/bots/Adventurer.kt | 519 +- .../main/core/game/bots/CombatBotAssembler.kt | 6 +- .../main/core/game/bots/GeneralBotCreator.kt | 2 +- Server/src/main/core/game/bots/ScriptAPI.kt | 47 +- .../src/main/core/game/world/ImmerseWorld.kt | 34 +- 7 files changed, 33854 insertions(+), 270 deletions(-) diff --git a/Server/data/botdata/bot_dialogue.json b/Server/data/botdata/bot_dialogue.json index e79ac6ee9..c225b117e 100644 --- a/Server/data/botdata/bot_dialogue.json +++ b/Server/data/botdata/bot_dialogue.json @@ -301,7 +301,7 @@ "Always check announcments", "We thrivin", "Ship @name", - "Dont forget to vote 2009Scape!", + "Dont forget to vote 2009scape!", "Kermit is too legit 2 quit", "Out here on the range we are having fun", "I am hank steel", @@ -367,33 +367,16 @@ "May Guthix bring you balance.", "May Guthix bring you balance.", "May Guthix bring you balance.", - "Thy death was not in vain, for it brought some balance to the world. May Guthix bring you rest.", - "May you walk the path, and never fall, for Guthix walks beside thee on thy journey. May Guthix bring you peace.", - "All things must end, as all begin; Only Guthix knows the role thou must play. May Guthix bring you balance.", - "In life, in death, in joy, in sorrow: May thine experience show thee balance. May Guthix bring you balance.", - "Thou must do as thou must, no matter what. Thine actions bring balance to this world. May Guthix bring you balance.", - "The river flows, the sun ignites, May you stand with Guthix in thy fights. May Guthix bring you balance.", "A journey of a single step, May take thee over a thousand miles. May Guthix bring you balance.", "Zamorak give me strength!", "Zamorak give me strength!", "Zamorak give me strength!", - "May your bloodthirst never be sated, and may all your battles be glorious. Zamorak bring you strength.", - "There is no opinion that cannot be proven true...by crushing those who choose to disagree with it. Zamorak give me strength!", - "Battles are not lost and won; They simply remove the weak from the equation. Zamorak give me strength!", - "Those who fight, then run away, shame Zamorak with their cowardice. Zamorak give me strength!", - "Battle is by those who choose to disagree with it. Zamorak give me strength!", - "Strike fast, strike hard, strike true: The strength of Zamorak will be with you. Zamorak give me strength!", "The weak deserve to die, so the strong may flourish. This is the creed of Zamorak.", "This is Saradomin's wisdom.", "This is Saradomin's wisdom.", "This is Saradomin's wisdom.", "Go in peace in the name of Saradomin; may his glory shine upon you like the sun.", "Thy cause was false, thy skills did lack; See you in Lumbridge when you get back.", - "Protect your self, protect your friends. Mine is the glory that never ends. This is Saradomin's wisdom.", - "The darkness in life may be avoided, by the light of wisdom shining. This is Saradomin's wisdom.", - "Show love to your friends, and mercy to your enemies, and know that the wisdom of Saradomin will follow. This is Saradomin's wisdom.", - "A fight begun, when the cause is just, will prevail over all others. This is Saradomin's wisdom.", - "The currency of goodness is honour; It retains its value through scarcity. This is Saradomin's wisdom.", "For Camelot!", "Firmly grasp it!", "My legs!", @@ -496,21 +479,525 @@ "Shlisshalpshlaap", "Somebody call for an exterminator?", "Decisive action. Should work.", - "R E A D Y T O R A I S E S O M E H E L L", "Darkness overpowering.", "Got any questions about propane? Or propane accessories?", "When someone asks me if I am a god, I say Y E S!!!", "You run out of Marines?", - "Goliath Online", - "I'm escaping to the one place that hasn't been corrupted by Capitalism. Lunar Isle!", "Selling wildy protection, 100k gp", - "Can't we get you on Mastermind, @name? Next contestant - @name from Lumbridge. Special subject - the bleedin' obvious.", - "Oh, you're German! I'm sorry, I thought there was something wrong with you.", + "Can't we get you on Mastermind, @name?", "Listen, don't mention the war! I mentioned it once, but I think I got away with it all right.", "Cunnilingus and psychiatry brought us to this.", - "Oh, poor baby. What do you want, a Brimstail's Sampler?", - "There's an old TzHarrian saying, you fuck up once, you lose two teeth.", - "The lineup consisted simply of six hydrocoptic marzelvanes so fitted to the ambifacient lunar waneshaft that sidefumbling was prevented." + "Ah, the Wilderness... where dreams of riches meet a swift demise.", + "Who needs a quest guide? I've got the whole wiki memorized.", + "Buying GF 10k coins. Must have at least 70 Agility.", + "I swear, the goblins in Goblin Village have it out for me.", + "Why do wizards always hang out in towers? Is it a zoning thing?", + "I'm training my Construction skill. My house is gonna be lit!", + "The GE is like the stock market, but with dragon bones.", + "Why do we need a cabbage patch in Draynor? Seriously.", + "I've been mining rune essence for hours. My pickaxe hates me.", + "@name hit 99 Cooking. Time to open a gourmet restaurant in Varrock.", + "I'm convinced the @name is actually a time-traveling wizard.", + "Anyone up for a Castle Wars match? I need that decorative armor.", + "Accidentally clicked Attack on a guard. Now I'm a wanted criminal.", + "Why do we even have a Duel Arena? It's just a fancy boxing ring.", + "I've got a stack of burnt lobsters. Anyone want to buy them?", + "Greetings, @name! Looking for a quest?", + "Just got a rare drop! The RNG gods are smiling upon me!", + "Anyone need help with a boss fight? I've got my dragon dagger ready.", + "Buying feathers! Will pay top price!", + "The Lumbridge cows are my favorite training spot.", + "Who needs a teleport? I've got my magic runes stocked.", + "@name hit 99 Woodcutting. Time to chop some yews!", + "Anyone seen the Wise Old Man lately? I owe him a visit.", + "Selling lobsters! Freshly caught from Catherby.", + "Swear, the Wilderness is scarier than my nightmares.", + "Looking for a clan to join. Any takers?", + "I'm an ironman, so no trading for me!", + "Anyone up for a Castle Wars match?", + "The Grand Exchange prices are crashing. Panic sell!", + "Who else remembers the Falador Massacre?", + "I'm saving up for a party hat. Wish me luck!", + "Barrows runs are my addiction. Those crypts are spooky.", + "I'm convinced the Wise Old Man is secretly Zamorak.", + "I'm a completionist, so I'm grinding out all the achievements.", + "The music in this game is surprisingly epic.", + "Tried to trade with a tree... It didn't go well.", + "My bank is like a black hole. Items disappear forever.", + "I'm convinced the Wise Old Man is just a confused tourist.", + "My character's fashion sense? Let's just say it's 'unique.'", + "Challenged a cow to a dance-off. It won.", + "Why does the Lumbridge Guide always look so lost?", + "I'm training Agility, but my real-life agility is zero.", + "Tried to fish in the desert. Sandfish are elusive.", + "The Grand Exchange is like a chaotic stock market.", + "I'm a master at clicking 'Continue' during quests.", + "I'm convinced the chickens are plotting world domination.", + "I'm a woodcutter, but I've never seen a talking tree.", + "I'm a vegetarian, except when it comes to killing dragons.", + "Why do wizards wear pointy hats? Is it a fashion statement?", + "Challenged a guard to a staring contest. He won.", + "I'm collecting cabbage. It's a noble pursuit.", + "Accidentally set my cat on fire. It's now a firecat.", + "I'm convinced the Wise Old Man is secretly a time traveler.", + "I'm a quest completionist, but I still can't find my keys.", + "I'm convinced the ducks are spying on us.", + "I'm a pro at avoiding the Lumbridge swamp. Too many frogs.", + "Hey, can someone lend me 10k? I promise I'll pay it back... eventually.", + "Why do I always find the one square where the random event spawns?", + "I'm training Prayer by burying bones. It's like a spiritual workout.", + "The Wise Old Man's fashion sense is questionable.", + "I'm convinced the ducks are secretly plotting world domination.", + "Why do wizards wear pointy hats? Is it a dress code?", + "I'm collecting cabbage. It's a noble pursuit, really.", + "I'm a vegetarian, except when it comes to killing dragons.", + "Why does the Lumbridge Guide always look so lost?", + "Training Agility, but my real-life agility is zero.", + "I'm convinced the Wise Old Man is secretly a time traveler.", + "Tried to mine air. It's an untapped resource.", + "I'm a quest completionist, but I still can't find my keys.", + "Challenged a guard to a staring contest. He won.", + "I'm saving up for a party hat. Priorities, you know?", + "Why do goblins drop coins? Do they moonlight as accountants?", + "I'm convinced the chickens are plotting something.", + "Clicked 'Attack' on a chicken. Now I'm a poultry murderer.", + "My character's fashion sense? Let's just say it's 'unique.'", + "Do you know where I can find the entrance to the Taverley Dungeon?", + "Hey, anyone here familiar with the Barrows? I need some tips.", + "Is there a bank nearby? My inventory is overflowing with loot", + "I'm clueless about clue scrolls", + "Where's the best spot to catch sharks? I'm aiming for 99 Fishing.", + "Is there a shortcut to the Karamja Volcano?", + "Can someone explain the mechanics of the Jad fight in the Fight Caves?", + "I'm stuck on the Elemental Workshop quest. Any hints?", + "Where can I find a loom to spin flax into bowstrings?", + "What's the best gear setup for killing dragons? I want that visage drop!", + "I'm trying to unlock the fairy rings", + "How do I recharge my amulet of glory?", + "Why do goblins drop coins?", + "The Grand Exchange is like the stock market", + "My real-life agility is more like a lumbering tortoise.", + "The Wise Old Man's fashion sense is like Woahs", + "I challenged a cow to a dance off, surprisingly smooth mooves.", + "Why does the Lumbridge Guide always look lost?", + "I'm convinced the ducks in Lumbridge are plotting world domination!", + "I accidentally ate my prayer potion I'm blessed with heartburn", + "I'm a vegetarian, except when it comes to slaying dragons.", + "Why do wizards wear pointy hats? Is it a magical dress code?", + "I'm a quest completionist, but I still can't find my keys in real life.", + "I challenged a guard to a staring contest. He won.", + "I'm saving up for a party hat. Priorities, ya know?", + "What's the deal with the Wilderness?", + "I'm convinced the chickens are secretly plotting world domination!", + "Accidentally clicked 'Attack' on a guard. Now I'm on a watchlist.", + "My character's fashion sense? Let's just say it's 'unique'", + "Lobsters heal my soul", + "Trimmed armor or bust!", + "Wilderness: Where friendships go to die", + "Buying gf 10k", + "Dancing for coins at Lumbridge", + "Wearing full rune like a boss", + "Teleporting to Camelot for quests", + "Fishing for hours at Catherby", + "PKing with a rune 2h", + "World 1 Falador Park parties", + "Staking my bank at the Duel Arena", + "Dying to Elvarg's fiery breath sums up my life", + "Got the Quest cape finally on my main!", + "Wearing a party hat with pride", + "Castle Wars: Red vs Blue", + "Trading in Varrock Square", + "Barrows runs for that sweet loot", + "Spending hours in Pest Control is life", + "Killing cows for leather armor is a good start", + "Farming herbs in Ardougne can be good money", + "Clan chat drama LOL", + "Mining rune essence endlessly", + "Agility courses: A love-hate relationship", + "Dueling for honor.... and GP", + "Buying runes from Aubury is decent money", + "Chasing the Easter Bunny like a scam", + "Wearing a skillcape with pride", + "Fletching yew longbows for profit", + "Going to implings in Puro-Puro", + "Castle Wars barricade wars", + "Dropping party hats at drop parties like pennies", + "Killing lesser demons in Karamja is part of my holy conquest", + "@name lures noobs into the Wilderness", + "Farming ranarrs for cash", + "Getting lost in the Underground Pass", + "Selling coal at the Grand Exchange", + "Fighting the Kalphite Queen", + "Picking flax in Seers' Village", + "Begging for free stuff in Lumbridge", + "Smithing rune platebodies for profit", + "Logging out in Lumbridge Castle", + "Hey @name, how do I get to the Grand Exchange?", + "Veteran here! @name, what's your favorite quest?", + "@name, how do I make money fast?", + "Hey @name, what's the best combat style for bossing?", + "@name, always carry an emergency teleport!", + "New player here! @name, what's the Wilderness like?", + "Hey @name, how do I join a clan?", + "@name, prioritize Prayer levels!", + "@name, what's the best way to train Agility?", + "Hey @name, what's your favorite minigame?", + "@name, never trust a PKer in Lumbridge!", + "@name, how do I get a fire cape?", + "Hey @name, what's the fastest way to level up Magic?", + "@name, try the Barrows tunnels!", + "@name, what's the deal with Pest Control?", + "Hey @name, how do I unlock the Fairy Rings?", + "@name, remember the old random events?", + "@name, should I train Strength or Attack first?", + "Hey @name, what's your favorite skillcape?", + "@name, can't do the Fight Caves!", + "@name, how do I get a pet?", + "Hey @name, what's the best food for boss fights?", + "@name, Castle Wars or Clan Wars?", + "@name, what's a clue scroll?", + "Hey @name, how do I defeat Jad?", + "@name, use Protect from Melee at KBD!", + "@name, should I train Ranged or Magic?", + "Hey @name, what's the best way to level up Crafting?", + "@name, don't forget your anti-dragon shield!", + "@name, what's the Stronghold of Security?", + "Hey @name, how do I access the Legends' Guild?", + "@name, remember the old PvP worlds?", + "@name, how do I get a dragon defender?", + "Hey @name, what's the best way to level up Herblore?", + "@name, always carry a charged amulet of glory!", + "@name, should I train Fishing or Cooking?", + "Hey @name, how do I defeat the Chaos Elemental?", + "@name, try the TzHaar Fight Pit!", + "@name, what's the best way to level up Smithing?", + "Hey @name, what's your favorite Slayer master?", + "@name, use the Ardougne cloak teleports!", + "@name, what's the Legends' Quest about?", + "Hey @name, how do I unlock the Ancient Magicks?", + "@name, remember the old Pest Control boats?", + "@name, what's the best way to level up Construction?", + "Hey @name, what's the fastest way to level up Prayer?", + "@name, the old Duel Arena stakes!", + "@name, what's the Warriors' Guild?", + "Hey @name, how do I defeat the Kalphite Queen?", + "@name, use the fairy ring code BIP!", + "@name, should I train Attack or Defense first?", + "Hey @name, what's the best way to level up Thieving?", + "@name, don't forget your charged glory amulet!", + "@name, what's the Legends' Cape?", + "Hey @name, how do I access the Heroes' Guild?", + "@name, remember the old Pest Control void gear?", + "@name, how do I get a firemaking skillcape?", + "Buying gf 10k", + "Trimming armor for free!", + "Wanna join my clan? We're called The Mighty Cabbages'!", + "I'll meet you at the Falador Party Room!", + "Dancing for coins in Varrock Square!", + "Remember when the Wilderness was dangerous?", + "I got a rune scimitar drop from Lesser Demons!", + "Lumbridge Swamp is haunted!", + "Anyone up for Castle Wars?", + "I miss the old random events!", + "World 2 is the trading hub!", + "I'm going to train my Agility at the Gnome Stronghold!", + "I just got 99 Cooking!", + "Fishing lobsters at Catherby is life!", + "The Legends' Guild is so exclusive!", + "Who needs a quest guide? I'll figure it out!", + "I'm mining rune essence for hours!", + "Barrows armor looks sick!", + "I'm stuck in the Underground Pass!", + "The Stronghold of Security taught me about account security!", + "I'm going to farm herbs in Ardougne!", + "I'm getting my fire cape!", + "I love the music in RuneScape!", + "I'm alching my maple longbows!", + "I'm doing the Recipe for Disaster subquests!", + "I'm going to train my combat stats at the Rock Crabs!", + "I'm going for the Quest Cape!", + "I'm going to mine pure essence!", + "I'm hunting chinchompas in the Feldip Hills!", + "I'm going to train my Woodcutting at Seers' Village!", + "I'm going to fish sharks at the Fishing Guild!", + "I'm going to train my Thieving at Ardougne Knights!", + "I'm going to hunt implings in Puro-Puro!", + "I'm going to train my Hunter at the Falconry!", + "I'm smithing rune platebodies!", + "I'm going to train my Farming at the Tree Gnome Stronghold!", + "I'm going to hunt red chinchompas in the Wilderness!", + "I'm doing the Underground Pass quest!", + "I'm going to fish monkfish in Piscatoris!", + "Meet me in Varrock, @name, for an epic trade", + "@name, join my clan; we'll conquer the Wilderness together!", + "Beware the dragons, @name, they're fiercer than you think", + "Crafting runes with @name, the best mage in Gielinor", + "Fishing lobsters with @name, the sea's no match for us", + "@name, your swordsmanship at Duel Arena is unmatched!", + "Questing through dark caves, @name always leads the way", + "Share your wisdom, @name, how'd you master those spells?", + "Legends speak of @name bravery at the God Wars", + "Need more arrows, @name? I've got plenty to spare", + "Cooking's a breeze when @name around, no burnt lobsters!", + "Mining together, @name and I strike gold every time", + "@name, let's barter; your herbs for my potions?", + "Training agility with @name, leaping like graceful gazelles", + "Heard @name got the best magic beans in town", + "Fletching bows with @name, aiming for perfection", + "Smithing with @name, our anvils never cool down", + "Adventuring with @name, every quest is a thrill", + "Battling demons, @name courage inspires us all", + "Slaying dragons, @name the hero we need", + "Gathering at Falador, @name party room is legendary", + "Hunting chinchompas, @name traps are always full", + "Farming's fun with @name, our crops never fail", + "Brewing potions, @name mixtures are magical", + "Casting spells with @name, we're invincible", + "Building fires, @name flames warm the coldest nights", + "Sailing to Pest Control, @name our fearless captain", + "Trading runes, @name deals are the fairest", + "Exploring dungeons, @name the light in the darkness", + "Charging orbs with @name, our energy knows no bounds", + "Dancing in Draynor, @name moves are enchanting", + "Playing Gnomeball, @name the star player", + "Harvesting willows, @name axe swings true", + "Enchanting jewelry, @name touch turns copper to gold", + "Summoning familiars, @name spirit wolf leads the pack", + "Thieving from stalls, @name hands are lightning-fast", + "Crafting runes, @name essence never runs dry", + "Fishing at Catherby, @name catch feeds us all", + "Cooking feasts, @name dishes delight the gods", + "Mining runite, @name pickaxe strikes rich veins", + "Bartering at Grand Exchange, @name a trading master", + "Training prayer, @name piety moves mountains", + "Fighting revenants, @name valor shines bright", + "Building homes, @name construction is flawless", + "Hunting imps, @name net is always full", + "Brewing ale, @name tavern is the town's favorite", + "Casting high alchemy, @name turns junk into treasure", + "Sailing to Karamja, @name adventures are legendary", + "Forging alliances, @name charisma unites clans", + "Defeating bosses, @name name echoes in legends", + "Are you mewing @name???", + "Check out that gyatt @name", + "Bruhhhhh @name got that rizz", + "@name rizzing up the bots", + "Ironman? More like copperboy LOL", + "What that gyatt do @name", + "He's got the zoomies!", + "@name likes pickles and dipped in mayo", + "Lmaaooooooo", + "Bruh she said she loved me...", + "I caught @name rizzing a mewing teacher", + "What that mouth do bb", + "Ayo tf he say", + "Ayo", + "Ayo @name a freak lowkey", + "Ayo tf", + "@name catch me outside howbout that", + "Wasssssuuuuppppppp", + "Knock knock @name", + "Oh boy howdy do i have a surprise for you", + "Noooooo", + "What do you mean I haven't done anything wtf", + "Redrocket redrocket!!!", + "I made 20,000 crochet sock puppets for ceikry", + "Come on @name", + "Are we rading tonight @name?", + "Why would he say that", + "Penguins are technically reptiles", + "Brb smell something burning", + "Need pest control partner, you handle the portals, i will afk", + "Bruhhhh the skibiddi rizz in my gyatt makes my mewing sesh rough", + "@name jajajajaja", + "Wait, I can't raid tonight @name", + "Brb, pizza's here. Hope they ask why I'm a grown man dressed like an elf", + "Sorry, gotta go AFK. My dog just ate my gaming headset.", + "Brb, my grandma just fell down the stairs", + "Hold on, the baby's crying, aka @name", + "Oops, spilled my drink", + "Guys, I need to log off, my plants are staging a revolt for not watering them", + "AFK a sec, my neighbor's llama is in my backyard again", + "My pizza rolls are ready", + "Lost track of time, i'm late for my own wedding", + "Sorry, can't hear you over the sound of my laundry", + "Turn HDR off in windows @name", + "Www. no one cares .com", + "Hey @name www dot stfu dot com", + "Like pitching a tent in a pair of britches", + "Mad as a bag of ferrets", + "I dont think beavers built the hoover dam", + "How do beavers get the concrete for dams?", + "@name show me the way", + "@name onwards brutha", + "@name eats fried rat tails", + "@name is a rat", + "Why are there so many people farming right now", + "@name fuck the police", + "@name says the like pickles on their hotdogs", + "Fuck the guards, free woah in varrock prison", + "Ayo fuck u mean", + "Woop woop thats da sound of the beast", + "How are you the way that you are", + "She sells seashells by the sea shore", + "@name certified rat", + "@name buys skimmed milk", + "Got milk?", + "Are you JSON because i want you to get array from me", + "@name likes string manipulation", + "@name sells legos", + "JUST DO IT", + "Why are there so many motherfucking options", + "Just hit the fucking auto hide thing", + "Just play", + "Hell no this shit is fuzzy as balls", + "@name is fuzzy as balls", + "Turn your brightness up @name", + "On my pc it runs perfectly", + "I know why mine seems a little jumpy", + "Stream the window not the monitor", + "Discords a bitch", + "Why are there so many handsome people at the ge like @name", + "I'll make you squeel of fortune", + "You will get it in due time @name", + "I was one turn away", + "It do be pipe time @name", + "Sometimes i like to cover myself in vaseline and pretend i'm a slug", + "Woah is a greased pig", + "Sometimes i dig holes in my backyard and pretend i'm a carrot", + "It's pipe time @name", + "If i am not pipe timing i am programming", + "Yes i have thigh high socks, no you cannot have them", + "I scream when i wear my programming socks", + "Anyone wanna buy @name's bathwater?", + "Anyone wanna buy my used socks?", + "@name be getting bags", + "What the fuck is this", + "Hi i noticed you haven't taken a break in hours @name", + "I really am seething rn", + "I am so fucking tilted", + "Go back to your fucking frogs", + "Life is simple as frog farmer", + "A q p", + "Oooooh that's a first", + "Been a minute @name", + "Hey @name", + "Oh shit it's @name", + "Hey @name wyd today?", + "Ayo @name", + "Wyd @name", + "Wbu @name?", + "Good fuck em, that's what they get", + "Deathknight lookin rat ass mf @name", + "@name sucks slugs", + "Brb gotta take a shit", + "@name will brb went to take a shit", + "Tell me when he is coming", + "This guy is being incredibly based", + "@name is based af", + "Taking l's all day today @name", + "That sucks massive dongus", + "Ah i was about to type that", + "Where is stormwind?", + "How do i buy gold", + "@name sells gold", + "@name is a gold digger", + "Ayo @name wanna buy some frog legs?", + "Brb fucking burnt my pizza rolls", + "I swear @name if you need roll again", + "@name you are a hunter you don't need plate armor", + "Dragonriding is satisfying", + "There's an old TzHarrian saying, you fuck up once, you lose two teeth", + "FUCK", + "@name i am ready when you are", + "Anyone selling logs?", + "That is hilarious @name", + "Alright @name", + "I need to go get my quest cape", + "500 barrows runs dry", + "Back to back to back barrows items, easy game", + "@name did you know them?", + "@name sucks eggs", + "@name eats snails", + "Who is that?", + "I've gotta go in 20 minutes", + "Bonk", + "Gtg in 30 minutes", + "They left 50 minutes ago", + "I think it's just gonna be us", + "Who is that?", + "Stop following me", + "@name stop following me", + "I think @name is watching me", + "@name wouldn't let me get a hit in at clan wars", + "Clan wars and chill?", + "Quick mewing sesh", + "Don't you stickbug me", + "Get stick bugged", + "Wtf why are you a dragon", + "Fun fact, woah eats eggs whole like a snake", + "Ceikys there's a rare over there", + "Where is goldshire?", + "How long have you played @name?", + "Wanna quest?", + "TROGDORRRRRR", + "Fuck this shit i'm out", + "Wait till you get your first 99", + "How is that even possible", + "That's the max", + "@name is trying to max", + "Complesionist cape?", + "How can you increase your run speed?", + "@name where is barrows?", + "@name where are rune rocks?", + "@name where is yanille?", + "@name how long have you played for?", + "Yes these quotes were hand typed", + "Kermit was here", + "World of Warcraft died after Wrath", + "Ceikry needs to add talent trees", + "How do you get to the wilderness?", + "Anyone tryna lure @name?", + "@name tried to lure me", + "@name bots all the time", + "Anyone want chicken tendies", + "Brb foods ready", + "Brb", + "Gotta go get food", + "Anyone else from northern alaska?", + "Fishing 4 gp", + "Looking for gf", + "Anyone wanna be my discord kitten?", + "Selling discord kittens", + "@name is a discord kitten", + "Add me on discord", + "Are you in the 09discord", + "Where are you going @name?", + "Idk what i am going to cook today", + "What should i eat tonight", + "He is in the cave", + "Don't forget to save game before logging out", + "American horror story died after season 1", + "Prequels are better than the sequels", + "Disney star wars is the best star wars", + "Halo 5 sucked", + "Selling xbox live gold and 1600 microsoft points for 50k gp", + "Buying gf 25gp and a bucket", + "@name i heard evilwaffles bots", + "@name hopefully ceikry doesn't find out about evilwaffles", + "Honk honk", + "Where is the road to mordor?", + "Golem lookin ass bitch", + "@name rat looking mf", + "@name uses sand paper to wipe", + "@name said Woah is cute", + "You need 25 of 40 to do that", + "Over 1000 unique lines of dialogue", + "What should i get to eat", + "Ge be poppin today", + "Where all the woahs at", + "Ayo woahscam got that gyatt", + "That is one i haven't seen before" ], "halloween": [ "Trick or treat!!!", @@ -521,9 +1008,9 @@ "Costume party at my P O H!! Follow me!", "Trick, then!", "Brrrainssssssss...", - "'Cause this is thriller, thriller night, and no one's gonna save you from the beast about to strike!", - "This is Hallowe'en, this is Hallowe'en, pumpkins scream in the dead of night!", - "This is Hallowe'en, everybody make a scene, Trick or treat till the neighbors gonna die of fright!", + "'Cause this is thriller, thriller night!", + "This is Hallowe'en, this is Hallowe'en!", + "This is Hallowe'en, everybody make a scene!", "In this town we call home, everyone hail to the pumpkin song!", "Watch out for Skeleton Jack!", "The headless-what-man? Horse? Never heard of those.", diff --git a/Server/data/botdata/botnames.txt b/Server/data/botdata/botnames.txt index 3024122cc..22c5715a8 100644 --- a/Server/data/botdata/botnames.txt +++ b/Server/data/botdata/botnames.txt @@ -1,766 +1,1992 @@ +-Kevo +0 S O +0 4 1 1 +0 4 7 +0 HBK 0 +0 Khan 0 +0 LM +0 Quest Ptz +0 Undead 532 +0 hits +0 s m a n +0-0000000000 +00 zarour 00 +000eggs +004 n +007 Double O +007Banshee +00eeeee58 +00eeeeeHC +00oo00oo00z +010elpibexx0 014ankh 01690 +017Lucas 01Ares +01eon +01ogre 020893 024elyograG +02RS +02homestar +031 +0315 0416347345 +054 +055027584 +05miller5 05venom04 +06 59 0600 +06sz +07 Account +07 Adept +07 Ashley +07 Clinton +07 Ezra +07 Gizzy +07 Main +07 Nihilist +07 Officer +07 Rz +07 Sicario +07 T Bone +07 iron +07 kiero X +07 nice jake +070623 +07Ashley +07Ben +07Geno +07Jack +07Lax +07Panda +07Paul +07RS Suck +07Rockysbudy +07coco +07guthix07 +07wan +080 +0800 +0800952449 +0837 +09 +0920 09Ash 09Ashley 09Ato09 09Chris 09Dans 09Paul +09Reaper +09Rhys +09Rvape 09Skillerino 09TroyScape 09milo456 09scaping 09wan -0800 -0837 -0920 0BAMA +0Behind0You0 0CdanC0 +0G 0GCore 0Giesel42O +0IIll0llIIII +0JL 0Joker0 +0KAT 0LKI +0MEGA PVM +0MG ST3PSIS +0MW2PVM +0Manbearpig0 +0MrJ +0PC +0Pwnseason +0S Iluvatar +0SFX 0Tempest0 +0WEK 0X010 +0_BADASS_0 0anabanthis0 0bD0G 0bankspace 0bby +0bby Man 0belix +0bscure0ne +0ctopus +0dds r u win +0desza 0dexy 0dyssey +0ff Task 0ffline 0g_player +0gden 0ggyy +0gie +0h Hi Mark +0h4Sure +0hh 0hmMyGod +0hp +0im2old4this 0inke +0k +0l +0l m +0ld Mate +0leaguespace +0li 0livers 0livias +0lki +0llieNorth +0llies +0lmet +0lofmeister 0lurker0 0mfgcows +0mg A Baboon +0mg A Scimmy 0miseGo 0mnisciens +0n Time 0nMyWay2Max +0na +0nenonen 0neski 0netruememe 0niichan 0njon +0nlyClouds +0nmy 0ops 0oqs 0pSe 0pen +0pen Al +0pi ates 0pportunity 0riole 0rjan +0rl +0rnstein 0rphaned 0samaBdabbin +0sc4r 0smasher0 +0so 0ssimpwner +0syb +0t 0taku +0taylor +0verHyped 0verdrinking 0verhaul +0vershield 0viBeSo 0vyy +0wnag3s +0wnage_2017 0wnagedaddy 0wned 0wns +0wnu1h1t +0x Good x0 +0x05 +0xBitcoin 0xocube +0xp Fail 0xygen +1 +1 0 1 0 +1 1 4 +1 2 2 +1 337 +1 3s +1 4 11 +1 54 +1 9 7 +1 A M O R +1 A N D 1 +1 Account +1 Corin 6 9 +1 DC +1 Flicki Boi +1 Free Ryde +1 Ham +1 K0 Is Back +1 Line +1 Lion Tell +1 P P 1 +1 Percent +1 Waffle +1 and only +1 is ln of e +1 kc 1 pet +1 parhaista +1 s t Blood +1-800DILLDOE +1-GrayStone +10 Four +100 Duke 1000 Antz +1000 Eyes +1000 Ways 10000Fists 1000PingOnly 100Cl 100Grabb 100g 100kyews +100m gp 100xcoin +101000101010 +1017Trev 101e 101evil101 +101rootbeer +104512 +105 107M 1085 1099s +10Hz +10R80 +10b +10cc +10lachs +10mm mafia +10th Reaper 10v10 10v10v +10v10v10v +10x Brew +1101953119 +1111 +11111111111d 111fishkite1 +112OceanAve +116 +116 123 1183kenny +118s 11inchlimp 11l1 +12 +12 49 +12 XP +12 hours 120u 1212ajs2 +123 Zeus +123456205 +123Four 123bear5 +123tseemijni 1272172 +1288 12bar 12bar_ty +12blackeagle 12boo8 12earlycob +12in +12millionGP +12oss 12oz 12th +13 37 +13 Daas 1300 130SS 130rk 1312AFCA +1313 +131kg +1337 af +1337Trevor 1350 138hans +13D 13LACK0N3 +13O 13alerion +13ayek +13ehh 13ert1 13ig 13igdog +13kc Corp +13oneZ 13purecs +13ruce +13th Witness +14 wides 1400 +14060M +144 1441 +144forever +1453 FSM 149122089147 +14Fre-e +14GT 14Words +15 min Break +150 kilos 1520sedgwick +15b name +15mg +16 Fly Tell +16 Fps 1602 +16bumpysnow 16lB 16le +17 76 +170 IQ 17222 +1780 17Kc 17_FLHXS +17rune2277 +18 Or Older +18 Points +18 girlll +18-06-2022 x 1800BetsOff 1802M 180555 +181 1817 1827 1845 184910381412 +187 +187 781 1877 187PIGMORGUE 187er +1889 18cast1935 18hr 18killz +18s +19 KAPLAN 05 19088ml 1942 1948 +199 1992 1994 19O7 +19edgebee +19puxx +1AB +1After909 1Alfa 1Ali1Plane 1BGP 1Bio 1Buck1Love +1C2R +1C3 W4RR10R 1CuteBot 1Fbs +1G1D +1GramIronMan 1Hit2Lum 1Hunnid +1I1I1IIll1l +1InchWalrus +1Iron Reborn 1Kyle +1Lank 1ManGangBang +1Mayze +1NANO +1NU 1Nikolai +1Nut Dude +1O1Barz +1Ogp +1P Game +1Parthannax2 +1RlE +1ST KC +1Shadow9Fist 1Shark +1Stunner ISU +1Swan 1TapDirtNap 1Tick +1Tick 2 Slow 1TickShit +1Unforgiven8 +1_BLEED_BLUE +1ars 1badprogram +1bankingnoob 1blackhawk17 +1blk eye r2 1cooking 1da5 +1dan2 1day +1day iwas pk 1eat 1einad +1eyeNinja +1god max1 1grootfeest 1hundrednite +1imp1jar 1isa +1itemtbow 1jbone 1john +1k no zik +1kDuramax +1kMaster QXD 1k_0 +1kc myself 1kctobpet 1kill3dsanta 1kk3 +1kkc 1kona 1llmatic +1llusionss +1mforest +1nOnlyBigB 1nVaSioN +1ndy +1ne life 1nfiniti 1nsane str5 1nv1s +1nvercargill +1o 8 +1ocation +1please 1powerhydra +1r0nRyan 1rock23 1savage +1st Frans +1st ed mint +1st son 1stHCwasPKED 1stlrfan 1stnoob7 +1t8w 1tapaturma 1tickspecwep 1trueMortyy +1ucif3ro +1v1d a sedan 1w1lll0se 1wayEscape +1wwdwd2e21ed 1yfe +1zet +2 0 1 4 +2 1Savage +2 2 7 7 +2 2 8 9 +2 3 7 5 +2 9 +2 Big tities +2 Brothers +2 Much Tuna +2 P A C +2 Rich 4 Dis +2 Silent 540 +2 Smooth +2 ball cane +2 funny bro +2 grls 1 Jad 2 h p +2 in +2 kups +2 lN +2 more min +20 20 vision +20 Agi irl +20 On Pump 3 +200 +200 Cook 2000 +2001Arwen 2006nope +2007scape +2008Anthony 2009Anthony +200MXP Cook +200m for Olm +200mDefence +200marchalt 200mslay1day 2011Turmoil +2013 Rt +20130406655 +20136 +2027Parzival +202o2 +204 Wootang +205alphago +208 209th 20Four 20I0 20JuanSavag3 +20ms +21 5 +21 Average +21 Musketeer +21 Savage +2137 gp +215O +2173 +21JJ 21SavageX2C +21unit +22 69 +22 Geese +22 Gz +22 darnoc 22 +22 day fury 220mg +226559 +227 7 2277 +2277 Beast +2277 Soon TM +2277MaybeNvr +2277kg +22O5 +22X7 22btc 22harry +22mario 22whitewolf +23 x 3 232o2oo +234071973416 +23463564 +235iii6i666i +2376Total +2376ed 23847239571 23CD +23I +23coalcare +24 Hour 24000 +241 241196 +2424 +245 +247 365 +2488 24YO 24l7 +24w +25 S 25simulator +26 th 260sheepdog +265344626546 +26ll98 26pandas 26th +27 5 +27 M +271MPN 27ml 2841280 28BagsOfSalt 28goldpieces 290x +29384652 2996 +29Pons30 29enchant821 29robdead +2B Nier +2Broke4Coke +2C-T-2 +2D E F2 +2D pantsut 2Edgy4Meme 2Far 2Fast2Fuego 2GIRLS +2GLE 2Girls +2Goblins1Jug 2Guys1Wyvern 2Guys1dds 2I40 +2InchLift 2InchPnisher +2JZ GTE +2JZ Soup +2JZ-GTE Mk4 +2Jerry 2Lit 2M0X1 2MIN 2Men 2MinNoodles +2O xp +2O07 2OO7 +2QC +2Rare2Die 2Secs 2Sparks 2TH3MAX +2Tbows51Kc 2Tits +2TonHoneyBun +2VX +2amtossedher 2anmlsglued 2beFrank +2buttedgoat 2cbrein 2coldkillaa 2cool4u +2cythe +2d irl 2danny1 2dslap +2fastkilzz 2g0ds1cup 2girls1Kyle +2girls1Tbow 2girls1bed 2girls1troll 2girlz1jbird 2gurls1tick +2h ur azzzzz 2hopp +2hot2touch +2hot2touch2 +2hs +2id 2kav +2late2team +2logx +2nd Marksman +2nd Max Cape +2nd Sucks 2ndpanz 2olon 2oul 2pac 2pacs +2plush +2sm0keyyyyyy +2steps 2th7 2tickin 2tti 2two77 +2uBz 2ual 2ugi 2woke 2x92is99 +2ze 2zick1zussy +3 Hit V +3 5 P +3 50 +3 77 +3 Moons +3 S I X E S +3 SwordStyle +3 T C +3 arcanes ty +3 me0 3-age +30 yo b00mer +300m MPS +3019 30FF 30SHOTFOCUS +30XY +30thNovember 30zl +311s +3155 +315lbs 315squatreps +3160 316Austin +32 kay 320m +33 Dust Cat 335K +33jf 33zero2 +3400 341all +34241245321 345138 +34HL6432G6L2 +34T 34rj394thgro 351329 +35ankoumoon +35cm bicep +360 Labels +360backhand +365 day +369x +36ACT 36answersay +379 37Kg +37kg +381N 38CoolestMan 38drivelift +39 PETS 3BigDoobie +3D AnimeTits +3D Dorito +3E8 +3G 3III 3L1QZaD +3LetterName 3Miller3 3TicYaMum +3TickEat 3Ticks +3WordName +3a B0ng 3aly 3amf +3arbeed +3ash 3awe +3b 3bay 3bobyshmurda +3d age boots +3d354 3dderino 3erzerk +3h scimitar 3ibal0e9 3inchsoft +3ioc 3iron5u +3km +3lPatron +3lack 3litz 3lilbirbs 3lit3 3liteSupreme 3lven +3lyrie 3lys +3niZ 3nosedmonkey 3nps 3oh5 3pic 3ragesave +3rd Age Ryan +3rd Age THC +3rd Age Toes +3rd Age Wife +3rd Hunter +3rd Mage Owl +3rd X +3rdAgeHolds +3rdAgeHunt 3rdAgeSlayer +3rdMistake +3sd +3sl 3stripe +3uck +3uzi +3verD3ad 3vil +3vil Giraffe +3vil Lawyer +3we 3x3i 3xDestroyer +3xtra-1arge 3yes +3zR +3zi +4 Bros Info +4 Man Nex +4 inch demon +4 inches now +40 IQ +400L +400s +403 b +40699 Crabs 40Atk 40ms 40oz +412087542131 +413 JokeR +416MiIf Jade +41O +42 Mime 2462 +42 Reasons +42 skankhunt +420 Perkele +420 Sam +420 kc +420 lobster +420-2-Day 420Arch420 420Every +420Hellz 420LavarBall +420Pixels +420cyguy +420licious 420michael13 420tarmslyng +42342343342 +42Def 42O42O 42nd +432andone 43technetium +44 bot +4400 +44444444444 +45 fail +4500c +4564 +457 45smith2345 478k +47an 47th +48H +48hour +49 r +492117837813 +49forcerage +4ALLYaYa03 4D Entity 4EverAlone +4HeadScape 4Hymnz +4IQ Idiot +4K MrKrabs +4KT Youngboy 4Kath +4L O K O +4LDO 4LeafCIover +4Lt Goon Bag 4MoistScoops +4Nick8 +4STER 4Sale399 +4TheGalaxy 4The_Horde 4Tune +4V2Coldplay +4_Th3_mAiN +4are 4asphalt4 4biddin3 4cof 4dan2 +4dapigs 4dosemonster 4ever 4everdry +4got2pull0ut 4gottenvoid +4hQ +4hit pl0x 4holyhydra +4iend 4lex4nder +4litraa 4mag1996 4otobemaG +4pf PvM Lao +4pf danaw1te 4plate +4rKsTon3 +4sen +4th lesson +4th8 4the 4themininoob 4thunderbolt +4ur Elise +4werty4 +5 56 +5 Nine +5 Oh +5 mil +5 ms +5-Bet Fold +50 DKP Minus +500 BJ +5000men4 +505 +50Dkp_Minus +50TintenUwMa 50bitsnka +510 51Highlander 51xp +528racklover +5304 +530pm +53R10U5 53m0g +54 Slayer +548 55mg +562 5639 56667 56771910 +56O 570215 +5771 +57tallfred +57wraith2076 +5876 58th 59OG +5ADx 5Aces +5BY5 +5G fries 5GCovidTower 5H4NKS +5IRLOIN +5Id3Track +5M3H 5M9SNH31KAOI +5NAX +5OP 5Orudis5 5UBLlME +5a9 5alood +5alve 5ammito +5dudes1bank +5eekingdeath +5eizures +5g Internet 5gum 5harp5hoota 5hauny 5hayWh1te +5head +5inch Floppy +5is +5j5 +5kc Zulrah +5l9 5lNS +5lap +5nis 5parrow 5quid +5st +5t h +5th Blessing +5th hcim LUL 5trm +5wan 5wattia +5x3 5xr2 +6 57 +6 9buttholes +6 Donuts +6 Drive Fox +6 Foot 5 +6 I X GOD +6 M +6 Mil +6 Qp +600 Years +605 +60min is 1hr +617 +61V +6264 +629fm 62steeplist +6384 +647 +64DD +64th 6535 6620 +666 317 +666 J +666 is leet +666Ds 666Duuvel666 +666drkwizard +66Cute +66sick +675 +67M 67jj6j7 +68 savage +6822ii +68pickleman +69 L OR D 69 +6942O +69KolaOlli73 +69Skrrt420 +69bbygurl +69maryj420 6Dukke +6ESkarmory 6LACKY 6PaperJoint +6R6 6T9sofine 6TMG +6Tilbud 6UGG 6cansOfBeer +6cythe 6dr3w9 +6e +6enny +6ess +6et Schwifty +6h Logout +6in9 +6ix 6ixty 6ixx 6jadkiller +6km +6lb brownie 6mat 6ong 6p8o6 6pathsofpein +6qp +6shooter +6uapo +6uh 6utt9lug 6y6y6y2 +7 7 MAFIA +7 Curry +7 DeadlySins +7 Fat Drake +7 Of Nine 7 Trouts +7 pets chimp +7 seconds 7042 +70Point1 lol 70rangeboy 70to120 +710 710 710 +716 718m 71rc +72005sc +73 and Kree 734590325839 +737 73Head 73HoundKey +73gp 742617OOOO27 74ChaosLTUU +75 IQ 76frozen44 +76ms +7738 777slayer777 77Dunamis77 77Stingray +77ms +782 +784162 79giantfoot 7AYL0R +7D9 7Esconar7 7Ethereal +7F9 +7GB 7God +7H3 7J4FXEL7YFW5 7Lazy7 +7RAC +7T +7TF +7Vick 7Viggie +7ZP 7abibi 7amowdahli +7aq 7asty 7ate9 +7axy 7bazillion 7ckng +7ckng Mad 7claudia7 +7crypto7 7emo 7emp 7emptest 7fisherdog +7havage 7min 7mins +7mni +7om 7ourney +7out 7rad3 +7raphouse +7rev 7ridley 7scaryfire +7th Chamber 7th February +7uP joAo 7wizard10 7xshadowx7 +8 1 O +8 3B +8 Sue Build +8 alien 8 +8 bit bling +8 oh 8 8008tator 808Southside 80leavefox +82 Sue Say 8282 +831pride 832arba +8485 +849 +84Bandit +85 N 8502 +852K +858 +85U 85dakota85 +88 Odd Wand +8800 8885 +88gg 89devoid1329 +8ASS +8BootRaw6220 8ElMandinga8 +8J8 8O8O8O8O8O8O 8ass 8balknowsall +8balled +8eauty +8h of sleep 8ind 8l0wm3 8lackMamba24 +8loodrune +8lue Phat +8owser +8qxkf02v +8tail +8uD +8yrs +9 9 Problems +9 B 0 +9 DUIS +9 Tick Brain +9 mb +900mexp +901Grizzlies +90804 +9092514 90tegguy +91 +91 Tin Idea +911_Nate 91414 91CAL 91flip +92 way there +920 Bdops +9227 +9297 +92t 92times2is99 +94 xp +94AR BTW 95EliasAw +95LH +95p7 +96 WINDSTAR 9687 96fastfrog 97DEF +97ccman97 97fsh +98 BEDARD +98 Civic +982 +98Bn 98max1 +99 Doobies +99 Grill +99 Grinding +99 Mage +99 Rats +99 StaKe LvL +99 Steeze +99 oz +99 rwt +991atatime +9991499 99BnkStnding 99Juuling +99Lives 99S2HP +99Scents +99Scotting 99Slayer +99Souls3Days 99Victim +99_Maxed 99bottin +99charming 99hh +99moretimes +99ox 99problems4 +99ss +99sweatlvl 99wc500m +9Bar +9Barr +9CX 9D9Skillzz 9Dimensional +9GAG Reflex +9JR 9KL00AZIIZ9K +9O 9 +9PetsSoFar +9T3 +9TY9_Sailing +9UNIT +9cansRavioli +9ieman 9inchStepBro +9mm ko +9mmlesah +9ne +9ond +9till5slave 9ussy 9yearoldpops +A 2 The Aron +A 3 +A 45 +A 7 F O L D +A Articuno +A Bad IGN +A Bad Meme +A Big Hippo +A Big Leap +A Blind Man +A Booty Clap +A Born King +A Boss +A Bozo +A Bozz +A Bronze man +A Butcher +A Catowl +A Cityzen +A Claptrap +A Classy Boy +A Crazy Cook +A Crisp Sock +A Curry +A Cute Snail +A Dreamer +A Drunk Beer +A Du Ma +A F K Scape +A F KING +A F M Scape +A Fat Deer +A Fat Pike +A Fat Swede +A Gauss +A Girthy Boi +A Godsword +A H Fire +A Half Fool +A Hofasho +A I D E N +A I I e n +A II D +A Iron Yoshi +A J +A JJug +A Jack O Lit +A Jug +A Kimura +A L 3 X +A L C A P WN +A L E K S +A L I S H A +A L T A Lava Lamp +A LifeTime +A Lilypad +A Little Lit +A Llama +A Long Story +A Loose Seal +A Mattias +A Maxed Iron +A MaxedBeard A MeatStick +A Melic Poet +A Message +A Moist One +A Moot +A Nathan +A New Area +A Newbi +A P R O X +A Panther +A Pauled +A Pixxel +A Pkr +A Plush +A Poothy +A Pot Head +A Psy +A Quest God +A Quickie +A R H +A R Z +A Raccoon +A Random 4nr +A Real Bamf +A Revuelto +A Rocky Road +A Scylla +A Sly Deity +A Snorelax +A Sofa +A Soft Spoon +A Solo Slave +A Soul Rune +A SpaceFox +A Spaceman +A TRX +A Tonk +A Towel +A Tuxedo Guy +A U G +A V T U R A WILDR0NNY +A White Girl +A Wiki +A Wild Nolan +A Wise Sloth +A X Y S +A Yang +A Yep +A Zee +A Zeer +A Zoo Keeper +A Zuk +A Zuzakini +A aron +A bit north +A broke 126 +A capybara +A cclimation +A d e b y +A dam +A damm +A dammmm +A e d o +A e s i r +A f r a i d +A gg +A lba +A ll F +A llan +A llstar +A ltar +A m a nd a +A n d re +A nz +A rdy +A rmin +A rmoa +A rrow +A stoner guy +A to teh Jay +A ug +A y s a +A z k e n +A z t e r +A-Chronic +A-F-Kaveman +A123 A13X +A15 A1KMAN A1nz00alGown A1rhook +A2 A22Y +A47 Soldier +A543 A7MED +A84 +AAA GG AAAAAFK +AAAAAddy AAIGHT +AAsamba +AB Dash +AB84 ABEC +ABG Huntr ABILITEETTI +ABearCat ABlazys97 ABlueShirt +AC Dicing +AC TEMP IQ +AC0T +ACDC +ACatGirl uwu +AColdBeer AComp ACucumber ADACardano +ADAMB73 +ADHDerral +ADRlAN +AD_inc ADankTank +ADirtyDan ADrugTaker +AE2AW AEKDB AER0B +AER1410 AFCA +AFCA CBS +AFCA SCHOREM +AFGard AFJay +AFK Always +AFK Kay +AFK Liam +AFK SCO +AFK Spoon +AFK twigz +AFKJOHN +AFKaas +AFKarl +AFKevv AFKolby +AFKspiracy AFTW +AFX64 AFrickinLion +AGIT8 AGP3 AGRONOMlST +AGSpec +AGWA AGlassOfH2O AGorski AH Energy +AH64 Apache AHHSCHMEEEEE +AHK XD AHMETJACKSON AHarmlesKitn AHlager AHriMTaLeZ +AI Fighter +AI0 +AII 99 +AIchemyz +AIecko +AIeksib AIexmeister AIixs +AIlByMyself +AIm23ARDesti +AIways sm1le +AJ R +AJ Skills +AJ4J AJTracey AJ_24 +AJisHere93 AJsk +AK Alpha +AK Sam AK47 +AK4LF AK5C AKI-47 AKK1E +AKM +AKSpring AKinkyMonkey +AL-Trojans +AL3CX +AL7 +ALBlNO ALEXppresso ALLCAPS +ALLEGATlONS ALLTY4 ALSO +ALT Lurer ALargeMudkip ALevel115 +ALevel126 +ALittleLofty ALittleLogan ALonelyKurt ALonelySpoon ALonelyTaco ALv3Magikarp AMAWM +AMC Millions +AMD352 +AMDOSRSIRON2 AMGS65 AMRSY AMST +AN07HER AN0NYM0OOOUS AN1MAL1ST1SK ANDERDAPLUG +ANDR3 +ANDREVVTATE +ANDROlD 18 +ANGL0 SAX0N +ANGRY BL0KE +ANGRY N3RD ANIKV ANNA7AR ANNOYYEED ANON +ANRH ANUBlS +AOMA Doomfox +AOT GOAT +APC L000000L +APTZ27 +APrince AQ COCUGU AQMD +AQUAMARROCKZ +AR Brah +AR Fifteen AR15ONA AR1F +AR53 +ARCANO RS ARCHER ARCHIT3CTS ARESCREED23 ARNGCantrell ARRIVISTEZ ARRRot +ARTHURSHLBY ARTIZN +ARZ Ranger ARandyCat ASAP +ASAP Decky ASDQ ASH88 +ASIAN CHAD +ASIANBABIE ASMR AScrubIsHere +ASkillersAlt ASpacejunky ASuperDood ASuperior +AT-AT ATAR96 +ATEIROMU ATLx +ATR ATastyPastry +ATurboVirgin AU6URY +AUD1O AURl AUSLANDER AUSTlN +AUTOart AUTUMNELEGY +AUT_Alex +AUT_KoDeD +AV1 AVATARRR +AVE MARlA AVICll AVOCAD0O00OO AVlCII +AWW CRIKEY +AX0L0TL +AXL gun ROSE +AYRI DMM AZER AZNPanda +A_G_4 A_Wuh AaaBiiCee Aaalmost Aadalyn +AadreNaline +Aahatto +AakieSnaakie +Aaking AangTurambar AardbeiSoep +Aardwormpie Aaren Aargh Aarhus +Aarmir Aaro236 Aaron +Aaron 23 +Aaron Btw +Aaron Quiz +Aaron Samuel Aaron11700 AaronJMLP AaronPVM Aarsworm +Aarti Aary Aaryn +AashUnce +Aastradsen +AatroxLife +Aauburn +AavikonGaara Aayraz +AbInito +Abaay Abacraumbii +Abaiz Abaker Abaqus +Abariel +Abbas Elect Abbey +Abbey Ruins +Abbo baker +Abbyscimmy +Abc easy as +Abdallah6 Abdirahman +Abe lnnkon +Abe numse AbeTheHobo +Abengers Abernasty AbiChillii Abide +Abido +Abigayyl Abismaalinen Abito Abiuro Ablazin Abnegation +Abnxy Abocrate Abolish +Abolish NFA Abool +Aboriginal +Aborts Abortuary +Aboss Abou3Fiddy Abov Above AboveAvgGoat AboveHonor +Abpor Abr19 +Abradolf +Abrafebre +Abrakadaddy Abrakadino19 Abree107 Abridgetolum Abrils Abritrage Abruaa +Abruzi AbsentPray Absol Absol-EX +Absolut1on +Absolute POS +Absolute St8 Absolutism +Absolver Absorpt Absoullutely +Abstand Abstergo +AbstractNay +Abstractable AbsurdGreek +Absurdly Gay Absynthial +Abu Chungus +Abu Salih +Abuk +Abulssoni Abuv Abyission AbysmalGrind +Abyss Laps +Abyss Whip AbyssFreaks AbyssWalkerr AbyssaI Abyssal +Abyssal Roar +Abyssal Sire +Abyssal Wook AbyssalEmu AbyssalTrout AbyssalWrath +Abysse +Abyzz Acady Acai +Acai Berries +Acamarine +Acan D Acardi AccessPoint +Acciainoli Accio +Accio Bond AccioHorcrux +Accolades +Accountant 0 Accursio +Ace Kills +Ace12209 +Ace123445678 Ace2cool AceAlexander AceArcaneon AceOfSevens +AceTenSuited AceTookUOut Acefalcon3 Acekicker +Acemachine Acemanjam Acenr Acer Aces +Aces x3 +Acesuke +Acesupersoak +Acetazolamid +Acha9 Achaeos Ache +Achenar Achernar Achievement Achievements +Achilles Low +Achilles XXI AchillesFist Acholight Achuu11 Acid +Acid Cat420 +Acid Christ +Acid Dab +Acid Frick +Acid II +Acid Lunatic +Acid Magick +Acid Reducer +AcidBxbies +AcidHouse Acide Acidic Acidylia Acir +Ack Varmland Acke +AckeSSBM Ackman67 Acko Aclu +Aclyss Acolytes +Acorn Potat AcornHunter1 +Acoustics +Acquila Acquilar +Act Ov Vodka Actaeor +Actan Action +Action Dwarf +Action Movie Active +Active Whale Active-Bombi ActiveRecord +ActivelySent Activeshot Activis +Actor Actt Actual +Actual Bald +Actual Yak ActualName Actually Actw Acuila +Acumen OSRS AcuraIntegra AcuteSloth +Ad Pulvurum Ad0pted Adachigahara Adada62 +Adalman Adam +Adam pd1 Adam8 AdamBonar +AdamInAtl +AdamPwnz +AdamTehMong Adamant Adamanta +Adamantoise Adamchrisp Adammmmmmm +Adamp1 Adampewpew +AdamsMain +Adamskieh Adamy Adaptations +Add Jisuke Addderall +AdderLord Adderall Addi +Addicted Tom +Addicted2Rs +AddictedIM +AddictedSoul +Addlero Addycusfinch Addytt1 +Adee3 Adeeb Adelaw +Adele Adelier +Adeliya +Ademon66 +Adenocard Adept +Adept Brick +Adeptus W40k Adeq Adeus AdeyP Adgoar +Adhd Adam Adhurim +Adi Laser Adic Adiieu Adil Adin +Adios Punani +Adiosk8r AdjacentAce +Adjudicatior Adjusted Adjustmyfan +Adkille +Adley Admetis Admirable Admiral +Admiral Addy +Admiral Kev +Admiral Nano Ado12322 Adogg0323 Adolari @@ -769,46 +1995,85 @@ AdonisUkko Adorak Adorations Adore +Adornare +Adr Iron Adrean Adrian AdrianMMO Adriatik Adriatik7 +Adrik Adriyxs +Adroid +Adskip Adss Adstar +Adster98 Aduadu Adust +Adusy +Advance2Max +Advanced Rat +AdvancedOwen +Adventure On AdversY +Advvil +Adwan +Adyn1 Adz92 Adzyy +Adzz +Ae rith Aeariyion +Aeckersss +Aecyra Aedon Aedreius Aeganor Aegislash Aegon Aeikora +Aejayem Aelin +AelitenRS Aelos +Aemil +Aent Aeon AeonsOG +Aequites +Aerack +Aerdont +Aergius +Aeric Shun +Aerith 68 +Aerivas Aerj Aero +Aeroaxe +Aerocity Aerohead50 Aerolustly +Aeromi +Aerosol AeroxAces Aerros +Aeryen Aerzo Aestana Aesthetiix Aeterni +Aetharan +Aetharyn AetherEra Aethyrs Aeugh +Aev Aeyriex Aezolix +Aff it Affaires +Affan Khan Affect Affectie Affidra @@ -817,95 +2082,191 @@ Affirmed AfghanisDan Afghanistan Aficionado +Afk Blake +Afk Jasper +Afk N Scape +Afk Ray +Afk Scape +Afk To Smoke +Afk em +Afk is EZ AfkBandos AfkGod +AfkMachine +AfkTbh Afked AfkforGainz Afkillz Afkin +Afkoelen Afkstar Afkwarrio6 Aflamed +Afnacho1 +Afonso Afperser Afrecan AfricaSavior Africagamer1 AfricanMelon Afrie +Afrikka +Afriquee Afro +Afro Deagle +AfroFishh +AfroShay Afrojofe +Afroman +Afromann Afromouse87 Afrothunder Aft3rmath +After Dark +After3Scoops +AfterLike Afterlife Aftermatter +Aftermax Aftex Aftyr Afx31 Ag0b Ag3nte +AgagaWeeWee +Aganis +Agaperik Agatsuma +Age Forever +Age of Hell Aged Agenda21 Agent +Agent 3 +Agent Jass +Agent Slidt Agent805 Agent94 AgentFluff2 AgentOrnox Agentbunny1 +AgenteGanso Agentlobster +Aggressox +Aghiestic67 AgiNagii Agil +Agil Tank Agile +Agile AI +Agile Rob +Agile Tom AgileAllMile AgileFlea53 AgileLlama AgileRj +Agilities Agility Agitare +Agmaur Agnar472 Agni Agnoscere Agnykai +Agoge Agressie +Agroni Agronox Agronyss +Ags G Maul +Agsungg +Agua Diablo Aguanator +Agv +AhaShakes Ahab Ahav Ahegao AhegaoShawty +AhegaoxDrool +Ahero Knitly AhiPoke +Ahjin Ahkscape Ahkward +Ahlaundoh Ahmishcyborg Ahol Ahoyhoy +Ahreams +Ahri babe +Ahriah +Ahrim Job420 +Ahrou Ahvexx +Ai Haibara +Ai activated +Ai u +AiMienOortje +AiNebesvaik AiXiao Aiai8 Aian +AiasIM +Aiayu Aid12100 Aidann +Aidens Iron Aidios +Aife Aigua +Aiii Guey Aiikis0 +Aila Aillwynd Aimbot77 Aimdur AimenForFun AimenForYou +Ain Zak +Aina Vapaa Aintos Ainu +Air Aaron +Air Bison +Air Cube +Air Hawkz +Air Nimbus +Air Up There +AirAction +AirRin +AirWindSurge Airborne +Aircendition Airexz Airforcin Airomatren +Aironmaen +Airorider1 +Airplanez +AirsickMold +Airskipper +Airstone Airstrike +Airstrikes Airwalk Airwipp +Aishi owo Aisyah +Aivery +Aiwe +Aixaa +Aixleft +Aiyaaaa Aiyzer +Aizor +Aizzz +Aj Blitz Ajamian Ajarn Ajaxius @@ -914,99 +2275,193 @@ Ajeh Ajeti Ajikk Ajinz +Ajt141 +Ajushox Ajuus +Ajx +Ak 4854 Ak5u +Aka God AkaSpecs +Akadian +Akagi +Akali Akalron +Akarema +AkaseAkari Akasha Akashy Akatsuki Akaza +Akduman +Akeno +Akhasa +Akhavan Akhotha Akiha +Akihiko Main Akilled Akimbo Gmaul +Akira28 Akirakiyomi +Akka Flakka Akkaido +Akkezander27 +Akkhai Akmore720 +Akn Magic Akogare Akolyta Akomatic +Akomatk Akowii AkraLaDragon Akropolis Akshan Aksu Aksu596 +AksuRS Aktii +Aktivaros +Aku Megami AkumaPenguin Akunte +Akushizu Akusti +Akustic +Akvarij Akyba Akyle +Al Go Rhythm +Al e x x +Al ex G +Al-Kimiya AlCaponee AlFromOhio +AlIigator AlMusallam95 Alabandus +Alabarce Aladfar Alak4zam +Alakazoom +Alakazzaror Alameda Alamittainen Alan Alan200414 +Alandar Alanowsky Alantiwa +Alasse +Alaurise +AlbaisBack +Albananaa Albanoi +Albatrossse +Albatrox +Albert 1888 +Albert Klett AlbertaDean +AlbertasRec Alberthorn +Alberto +Alberto P Albertttt AlbiBambi Albin0z +Albinos10 +AlboBloodZ Alboy +AlbusTheDood Albuun +Alc1 +Alcadeias Alcado Alcarnia Alcatres Alcatrez +Alceini Alcerathe +Alch O Holic AlchKids4Gp Alchaline AlchedMyLife AlchedMyM0M AlchedMyNuts AlchedYaNan +Alcheimers +Alchemical A +Alchemicc +Alchemisten +Alchemize AlchemstDefi +Alchemyst +Alchhorn +Alchulon +Alckx +AlcoSkillz +Alcond Alcool Alcoz Aldastro Aldecaldos AldenolcyCB +Aldi Knight +Aldit0r3 Aldol +Alduiin +Aldwin Mose +Alec +Alec-kun +Aleck_l2 Aleffy Alegrete +AleizzleX +Alekja Aleks Aleksi Aleksib +Aleliumbis Alem Alemao Alenac Aleous Alerio Alessan +AletosCR Alex +Alex Blaze +Alex Cartman +Alex Grey +Alex IV +Alex Meret +Alex Power3 +Alex V2 +Alex Welshy +Alex Zander +Alex from IT +Alex the dad Alex12161 Alex3 +AlexDirty AlexHill AlexODaGreat +AlexSpkt +AlexV Alexa Alexander0k +Alexandre M Alexbrave2 Alexbrock +Alexis2Pro Alexmeister Alexnchill +Alexownsmatt Alexr0 Alexx Alexx2G +Alexxandraa AlexxisTexas Alexzilla Alf11 @@ -1015,51 +2470,95 @@ AlfaQ Alfahane Alfahanne Alfication +Alfie 96 Alfonga +Alfonso AlfonsoKhan +AlfredTB +Alfrid +Alfuh +Algiebeer Alharbi Alhyrr +Ali Shuffle +AliThePvmer +Alibaba Alicander Alicc Alice +Alice x +AliceOMalice +Alicent Alicezero1 +Alicola Alien AlienAntFarm AlienTTmilk +AlienVoucher Alienmage +Aliens +Aliii33 Alijr AliksOh Alioman +AlistarTb21 +Aliste +Alive Bozo +Alive Seb +Alive Vein +Alive18 AlivenHappy Alixz +Aljase Alkan Alkene +Alki Holic Alkkor Alkoholismi Alkymo +Alkyne +All Blue +All Darn Day All Fore One +All Frosty +All Peachy +All There +All a Bone AllRubyMoi +AllThePain AllTimeNo AllYourBase +AllaBarri Allabaster Allan +Allan man +Allards Allcreation Allday Alldays +Alldogg AllegedTheif +AllegedTree Allen Allerb +AllesPaletti Alleviate +AllexWx +Allext Alligaattori Alligamanor Alligood Allisun Allkune +Allky AlllySpawn +Allmethyst Allo Allomantic Allon +Allonsmoke Allowe +Allowed to Allscreen4 Allsen AllstarTb21 @@ -1070,54 +2569,105 @@ Ally Alma Almahh Almighty +Almighty2277 AlmightyMilo +AlmondJoy AlmostHadMee +AlmostSavvy Almost_124 Almosttheir Alno Aloha Alohas +Aloise Aloittelija Alondraj Alone +Alone CRNA +Alone RS AloneHeWalks +AlonelyPlace Along +Alonzo520 +Alonzo52O +Aloqab Alosthawaiin Alov Alow +Aloxc +Aloysius Alozaps Alpaca +Alpaca B0ng +Alpaca Lips AlpacaMyBags +AlpacaMyBowl +Alpacaliptic +Alpedocles Alpha +Alpha Cygni AlphaCoderXI AlphaFeeb AlphaMathic +AlphaSeraph +Alpha_Scott Alpharma Alphonse Alphray AlphusBrah +Alpine Climb Alpinetree +Alpoopi +Alppiruusu Alprazoland Already Alright +Alright Mom +AlrightBucko Alrite Alry Alsatian +Alsatians Also +Also Jack +Also Luci +Also Lucky +Also Nexxtar +Also Noexi +Also Schlak +Also kawkky +AlsoAlso +AlsoRabbit Alst +Alston +Alt Ctrl +Alt G boys +Alt Juana +Alt Redshok +Alt prepot +Alt3rbridg3 AltOclock AltSkillsDoe Altairre Altamonte Altchilly100 +Altcliffe +Altdunk +Altemeier Altenan Alter Alteraga Alternate +AlternateArt Alternatee +Alterones +Althamen Althornson Altifueled +AltimateRalf Alting +Altkandos +Altnik Altonorin Altruistic Altus @@ -1126,154 +2676,305 @@ Alucks Aluspalvelu Alvaaro Alvarreth +Alveoli Alvislt +Alvx Always +Always Alex +Always Awake +Always Harm +Always Late0 +AlwaysByrnes +AlwaysDNS AlwaysLost AlwaysPoor AlwaysQuest +AlwaysSunny +Alwayscuffed AlwayzJarvin AlwayzSol Alwex123321 +Alwin S Alxs +Alyks +Alysanne +Alyv Alzad +Alzuraak Alzz +Am eer +Am ity +Am ln Danger AmCatWhatDo +Ama zon +AmaAvenger Amadeux Amaiya Amak Amalie Amanda +Amanda Btw Amandelbrod Amarantine +Amarok Moon +Amasclit +Amateur Amathyn Amatsukaze Amatus Amazarashi +Amazaro Amazing +Amazon Power +Amazonia Amb3rLeaf AmberTheCat Ambik Ambion +Ambipom Ambisagrus +Ambition IRL +Ambition98 +Ambitioned Ambrose34 Amcaroz AmcyC37 +Amd27 +Ame Hara AmeJoyRock +Amean +Ameero7 Amel +Amelia Beth Amen +Amend Amenity +Ameno l +Americlaps +AmiableDingo +Amibis Amida Amigeau Amigo +Amigos +Amillie +Amin +Amir Psycho Amis Amitwin +Amityz AmixBeast +Amjad Amjar +Amka0s +Amkings Amlodipinee +Ammastian +Amnesiia +Amnios AmoMeuFilho +Amoei +Amon Amarth +Among Dead +AmongUs R34 +Amongst It +Amordrise Amos1500 Amper +Amperes Law +Ampiainen +Ampilify Ample +Amplify Ampura +Amsclarke +Amsterdamage Amty +Amused Fonty +Amuzements +Amuzzr Amuzzzr +Amy Sonck AmyMacdonald Amygdala Amylit Amyshaw123 +An Amputee +An Animal +An Ebony BBW +An Old Chum +An epic OAP An old Gnome +An0mandaris An0niminis +An6ers AnActualHorn AnAmerican +AnEnginerd AnEpicWookie +AnEskimo AnExperiment +AnEyeOhLate AnOldTank +Ana D Armas AnaWynn Anabella28 Anabolic Anabolic h1t +Anabowlen +AnaklusmosAN Anao Anaphylaxiss Anarchy +Anarchy870 AnarchyOS Anari AnataNoWaifu Anbu +Anbu_Mobb +AncIrew Ancalagon Ancastry AnchorMann Ancient +Ancient Fury +Ancient fir +Ancient hil +Ancient soul AncientFreak AncientLamb6 AncientMagus AncientOath +AncientP Ancientgh0st Anciento +Ancientz pal Ancitif +Ancona +Ancow +And e +And r ew AndSo +AndYetISmile Andardenn +Ander5 Anderave +Andericus Anders375 AndersenXo Anderssen Andhra AndiCandy AndiVT +Andiamo98 Andipyrus Andirath +Anditre +Andj Andoyen +Andrade149 +AndreasBL5 Andremagico7 AndresVZLA +Andrethyst Andrew +Andrew Marr +Andrew OG AndrewWigins Andrewjaay AndrewsMeat Andrezee Andrezz Andri02 +Andrian Andrick Andrishh +Andrius X +AndriusBykas Androgenic +Android Iron AndroidFox Andromed1k +Andsaca +Andx Andy +Andy Candy +Andy Ops +Andy Salrem +Andy btw Andy2 Andy2511 +Andy43229 AndyG223 +AndyIsComing +AndyL AndyMcbob4 +Andydiaz Andyfromvent Andyn9 Andyooi Andyvns +Anele Boy +Aneluy AnemicIzzy Anesics Anetha Aneurin +Anez +Ang3li Angalad Angel +Angel Advise +Angel Allie +Angel Gabe +Angel Martyr Angel Vlad Angel4killin Angel5 +AngelOfZeal AngelOrHour +Angelic Lust +AngelicOrb AngelicVixen +Angelisimo +Angell SL AngelsCrys Anger +Angerfish208 +Anghelic One +Angie Bos +Angl 0f War Anglerstein AngloSamson +Angoose Angry +Angry Bison1 +Angry Child +Angry Thumb AngryHusky24 AngryMvP +AngryNachos AngryPickle AngryScape AngryWizard +Angsti AngusM +AnhTaDuong +Anhedoniaa +Anid +Anida Hanjab Anidien +Anieli Aniheyu +Anim Anima Animal +Animal feces +Animalia Animation Animations Anime +Anime Nips AnimeExpert AnimeMilkers AnimeWaifus @@ -1281,51 +2982,95 @@ Animorph Animos Animosity Anion +Aniril x +Anita Dong +Anita M Wynn AniviaKush +Aniwave Anja +Anja Rubik AnjaPija Anjigami +Anjru +AnkaraAisa Ankedia +Ankka51 Ankn +Ankou btw AnkouClothes Ankougnu +Ankourule243 Anlaku Anlex Anmah Anmokyu +Anna Huikka +Anna Liebert +Anna Planks Anna Rosanna +Annavvaa +Anne Puppy +AnneWB Annero +Annhilate0 Annihilated +Annihilation Annihilative +Annna Puu +Annoys Anoie AnomalousFox +Anon E Maus AnonDoctore Anonim +Anons Anonymiity +Anonymous aF +Anonymousse +Anoobass1 Anooge Anoomliebird Anor +Anotha Skar Another +Another Name AnotherCsTa AnotherDoor AnotherGamer AnotherName +AnotherPb +Anouar +Anoubis Ansaittu +Anscombe +AnselAdams Ansoil +Ansovs Ansuz +Ant M8 +Ant a AntRIP +Antartsant12 Antast Ante Antee294 Antelope123 +Antex +Anth x Anth52 Anthiex Anthilll Anthony +Anthony Btw +Anthony I Anthony5002 Anthoons +Anthooony Anthorak Anti +Anti Drop +Anti PK G0D +Anti002 AntiFuh AntiVaxMothr Antidope @@ -1333,59 +3078,102 @@ Antifa4figs Antifire Antiflag42 Antiguy24 +Antinyte Antipathic Antipixel AntiqueRS Antiqxx +Antireflex Antis Antiserum420 Antixan Antiyano +Antlers +Antmix Anto Anton +Anton T Antonio Antonn Antony +Antony1202 Antony142pay Antoun +Antracid +Antron Antstolis Anttila Antweezy +Antz Xii +AnuBi 1337 Anub1s Anubis +Anubis ex +AnubisT3 +Anuj Anul AnullSecs Anv1k Anve Anxi Anxiety +AnxietyBTW Anxious +Anxious Mess AnxiousDoggy AnyDrops AnyLesS +AnyQuestions +AnyScrolls Anze +AnzheliK Anzie Anzied Anzu +Anzypoo +AoA Jammer AobaJohsai +Aog +Aoh +Aohc +Aohu +Aoi Tetsu Aokijahr Aokijii AonEne Aonyx AoooA +Aorpheat +Aosrs Aowi +Aozaa +Ap0logy Ap0phis Ap3x Ap870 +ApRoMn Apaat +Apaatje Apache +Apache30 +Aparlo ApartAbyss Apathetik +ApdoJ +Apdomine +Ape Cape +Ape Dos Mil ApeAtoll Apetamer +ApetimusPrym Apex +Apex Pro +Apex-scaper +ApexGT +Apexflashy Apexist Apgujeong +Apherna Aphex Aphroditeee Apimer @@ -1394,74 +3182,136 @@ Apldale Apm90x Apoc Apoc142 +Apocriya Apocryphe +Apolliox +Apollo Beach +Apollo13th +Apolytos Apop +Apophiss Apor +Apostasie Apotoxin App3lflap AppaYipYip +Apparat Apparitionn +Appeasive +Appel Farm Applauder Apple +Apple A Day +Apple Mart +AppleBluue Appleboss +Applecus +Applejuiceaj Applemaxx Applev2 Applied +Applul Apportant +Apprenti1 +ApprenticeRS Approval ApprovuL AppySauce4 +Apqle Aprella April April 8 1997 +April twenty Aproximity +Apsa Larr Apteryx +Apteryx luna +ApuHapu Apul Apullu +Apyon Aqew +Aqizu Aqtive AquaUnit Aquah Aquaileo +Aquajd Aqualetics Aquamation +Aquamentus9 Aquascaped +Aquaticbob Aquatik Aquellex +Aqueueser +AquiIa Aquilo +Aqva Babe +Ar ex +ArA100 +ArKadeeee +Arab Frieza Arabian Arada Araet +Aragonx Aragornmv +Aragornous +Aramaki Araman +Aramex Arandae Aranna Aranruth +Araq Araqon Arasex Arashikato Arastaiel Arathir Araur +Aravt Araysen Arazz Arb4n +Arbator +Arbenn Arbin Arbyy +Arc1s +Arcade firee +Arcadian96 Arcane +Arcane Grima +Arcane Queen +ArcaneApollo ArcaneBear Arcanezeus Arcangel +Arcangel IX Arcanic +Arcanox Sad +Arcanum XIII Arcas3 +Arced RS Arceneus Arch +Arch RS +Arch er Arch3nLight +ArchFarmer ArchX Archaea582 Archahl +Archaic Wolf Archaiden199 Archanjel +Archas +Archavia +ArchbishopC +Archduke Btw +Archelon Archer ArcherYew Archie @@ -1473,6 +3323,9 @@ ArckenSphere Arclight Arcnan Arctic +Arctic Roach +Arctic Vaggy +ArcticCamel ArcticMank ArcticTitan Arcticas @@ -1482,8 +3335,16 @@ Arda Ardaddy Ardames ArdenDZY +ArdestRange +Ardilos +Ardougn e +Arduino69 ArdumTheMain +Ardumm Ardy +Are Dry +Are ng +Are you well AreYouMyMumm AreYouPepega Area @@ -1491,12 +3352,17 @@ Areimer0606 Arekusei Arena ArenaRebuild +Arend Nest +AreolaArnold Areolas Areoloth +Areow Ares +Ares 3060 Ares1701 AresArmy AresKnight +Arescoth Aretx Arezrazer Arfex @@ -1505,282 +3371,534 @@ Argawan Argent Arghoslent Argilla +Argo Vesta +Argonuts +Argory +Argov +Argyle Sock +Argyle Socks ArgyleGrandt Arhedel +Ari AriSlash Aria +ArianDRZ Ariana +Arias star +Ariazel Arid ArieMoon AriesWarrior +ArieyaeIron +Arifureta Arigorn Arigorn55 Arihant Arillian Aris +Arisen I +Aristo +Aristokratas Arisu +Arith1um Arithe Arizotal Arjoon Ark9tog +ArkAngel029 +Arka91 +Arkaniz +Arkantos51 +Arkaros Arkavos +Arkaynine Arkeela +Arkells +Arkem +Arkemir +Arkend Arketryx Arkevin +Arkhero +Arkizah +Arkki +Arkonka1 +Arkonknight Arkvasal Arkysh Arlind ArloTheBrave Arlorict Arlyeaxn +Arlyse +Arm Chair +Arm Guy +Arma Frost Armadexx Armado Armadomin +Armadyl king +ArmadylPker Armadyllo Armament +Armanyte Armapickle +Armas Chosen Armchairs Armerak +Arminius Sol ArmisticeDay Armo ArmoBlood +ArmoMike Armoah +Armondega +ArmorHelmet3 +ArmorSeeds Armourer Armsdray +Armweak55 Armysam Arna +Arndas Arnear +Arnhems Arnie Arnold +Arnor +Arnthor Arntj Arobpl Arod Arodaz Aromipesa Aron +Aronya Aroorin Arousen +Arousin +Aroyu Arpang Arpegio Arptacular Arr n Geesus Arrandarls +Arrasca +Arrazha +Arre10 Arrizu +ArrowHaste ArrowTank Arrowmind +Arrows Myth +Arrowtower +Ars Nova Arsaydar Arsenals +Arsene rar Arsenic +ArsenicEyes +Arsenn Arshal +Arsi Arslen Arson ArsonScape +Arst +Arstan Selmy Art Dayne +Art Star +ArtIsHard ArtStylerzz Artces +Artegal Artenmis Artesna +Artezor +Artful Dodgr +Arthaniel Arthesus Arthropods Arthur Arthven +Artic0 +Articuno1991 +Artidote Artillion1 Artipeng Artisaani +Arto Lauri ArtofKush ArtoriaSiff Artoriias28 +Arts +Artu12v Arturis Artychurro Artz +Aru Arumen Arunas Arusas +Aruwyn_Xi Arve +Arvinthir Arviragus +Arvns +Arvsta Won +Arvx +Arwe +Arwon Arxanec Arya Aryabhata Aryuts +Aryzha +Arzemnieks Arzi +Arzna AsalentBlaze Asami +Asami Sato Asap +AsapLamb Asbi Asbloodfalls Asbur +Ascadex Ascanliss Ascended +Aschen +Ascii You Asda +Asdasd107 +Asdewq +Ase Aseae Ased Asfixiator +Ash K +Ash Solo +Ash Wreckum +Ash l AshBash AshEvillDead +AshKetchum00 AshLad94 +Ashabee Ashandarei0 +Ashcroft Ashealia Ashen +Ashen Bride +Ashen Heart +Ashen One AshenSughar +AsherMentuI Ashes Ashes630 Asheviere +Asheville +Ashhh Ashieboyyy Ashikaru38 Ashington +Ashkelmek Ashkii +Ashkyn Ashleigh Ashley AshleyNZ +Ashleyi Ashlyce +Ashmeow Ashn Ashoo Ashsole Ashton +Ashura Bakke Ashwin09 +Ashy joey +AshyKneecapz Ashyy Asian +AsianGrinder +Asics +Ask Oziach AskMeDolCare Askraf Askumi AslanMaximus Aslywyn +Asmir9990 Asorf Asos +Asot +Aspen +Asper Aspestia Asphyi +Asphyi Xate +Ass Balm +Ass Clams +Ass Drill +Ass Rocker +Ass locator +AssClapping +AssMcButt Assasindie73 +Assasintoad Assassinado Assaulted +Asshats R Us +Assktchum +Asstain Ast 360 Astan +Astaro +Astartes +AstartesXIII AsterSG Asterlad Asterlyte Asterus Astiminate Astoia +Aston Fartin AstraDan93 Astraea +Astral Queen +Astral laws Astrali +Astrals +Astray +Astrayus Astro +Astro Dust +Astro O7 +AstroKP AstroXgK AstroYogurt +Astroflare +Astronaut Al +AstrooWRLD Astrophe Astrostone +Astylez Asubu +AsuhDude Asuka AsukaLangely +AsukaYenOSRS Asukas Asumaton Asumistuki Asuna Asunnn Asura +Asus bl +AsylumTRAV Asymmetry Asyn +Asynergy Aszalem +Aszard +Aszension At0mic +Atacrite +Atar Ataraxia +Ateo +AthIetic Athaw +Athe na Athedeia Athena +AthenaOfOsrs +Athenaloki +Athi Athire +Athius Atika Atilio +Atin +Ativan IM Atlamillian Atlantic AtlasErol +AtlasUsurper Atlashi +Atleast Atli567 Atmosfare +Ato m +Atolla Atolli Atom Atomic AtomicFlux +Atomicdomb2 +Atomikaust Atomsk Atomyze Atonic Atorvastatin Atouk +Atoxicary Atoz +Atriades +AtriummDream Atrixas +Atro phy Atroo Atroph +AttackMoons Attard +AttemptedUwU Attic +Attic Ghost +Attic Witch Attics Attikos Atton +Attuned Atuking +Atvinnulaus +Atylos +Atza +Au 0srs +Au 1 +Au Bar +Au Barrett +Au Joel +Au Shooty Au92 AuRoyce AuStarZ Aubrey +Aubrey UIM +AubsG +Auburn Lax Aubzzz Auclaw Auctionable +Aud AudacityOP +Auddax Audi +Audi Nurse +Audi Reach +Audo +Audronan Audtnec Audylinks Augment AugstBrnsRed Augurk +Augury Tank August AugustAmes Augustiner16 +Augutis Auhdy Auja3 AuksoAlt Aulono +Aumoki +Aunonen +Aunt Wu Auntie +Auntie Mabel AuraBeast AuraSissari +Aurah +Aurelia AurelionROW AurelionVM Aurelya Aureou +Aurgodi AuriZed Auriana Aurionx +Aurizon Aurorin +Aurrok Aurtle AurumFoxfire +Auryn +Aus +Aus 2277 +Aus Shizam +AusBruto +AusGram Ause +AusieBumpkin Ausripper Aussie +Aussie Jay +Aussie Luke +AussieKunt +AussieOandE AussieSparta Aussome +Aussybear +Aust Terps Austie Austiiizy Austin +Austin Ames +Austin is 1 Austin296 +Austiz +AustlnPowers Australia +Australians Australiaz AustrianOak +Austs Austyn Autchin +Authorized +Authorizer Autickstic Autilon Autism AutismeKnaap Autist Autistic +AutisticAndy +Auto Tuned +AutoBonsai AutoEmp +AutoLoot EXE +Autoacid AutomailArm Automonteur Autophagy +Autorotate +Auts Man Autumn AutumnKevegy Autzerk Auuustin Auuuv AuzReaper13 +Auzium +Av o +Av3z Str +AvC OSRS +Ava End Avaetar +Avaigo Avatar +Avatar Evan +Avatar Magni +AvatarBean69 AvatarShakur Avedon +Aveng +Avengerous Aventy Aver4ge Average @@ -1792,7 +3910,14 @@ Avernic Avero Avertehs Avest09 +AvestGIM Avex +Avexaon +Avfc Holte +Avg Tom +AvgMG +AvgScape +Aviaatar Avian AvidTech Aviiation @@ -1801,85 +3926,154 @@ Avinosis Avir Aviron Avlek +Avocatocat Avoidable Avoinmieli +Avonak Avondale +Avouch Avrahm Avsendesora Avysto +Avze +Awadi69 Awaiting +Awaiting 126 Awaits Awaiyume +Awakened Olm Awarde +AweJeez Awendana Awesome +AwesomeBros AwesomeJared Awezm Awful +Awful Name +Awfully +Awh DB +Awh Nuggets Awies Awilkins4231 +Awkquavian +Awkventurer3 Awkward Awowegei +Awowo Gay +Awry +Awtangg AwwSeriously Awwdiddums Awwtis +Awyr +Ax3 +Axayre Axdrew +Axely +AxemPink Axeo +Axhers Axies Axillaa AximusMax Axiom +Axlerod +Axleson +Axodyi +Axolotl +Axsentz Axton Axylix +Ay Monk +Ay Ron Man Ay3m AyAyRon AyB33 +AyJae +Ayafuyuzu AyameDespair +Ayatan +Aybills +Ayd +Aye Sip AyeBaddaBing +AyeePizza Ayeeet +Ayema IM +Ayenull Ayetg Ayfi Aylia +Aylward Ayman +Ayo4Yayo AyoSteeze Ayoe +Ayonikz Ayra Ayri +Ayrton +Aysuu Ayveros +Ayy Nakana +Ayy bae bae +Ayy q p Ayyye Ayyyon Ayzo Az PVM +Aza zel Azad +Azad Kashmir Azala Azami +Azandari Azathor Azathoth26 +Azathrir +Azazel OSRS +Azeenil Azemu Azerma Azez Azimut Azimuthaal Aziz +Aziz7 Azkaton Azken Azkybot Azlo Azmataz +Aznbabe Aznmixboy Azom AzorAhaiBTW Azotize Azoxy +Azpa +AzraelReaper Azriiele Azryel +Azs +Azshara +AztecLT +Aztra Azula +Azula Whip +Azur Lane Azur_I Azure Azure23782 AzureSpirit +Azuredadi Azuremadi +Azuretiger Azuuure +Azynn +Azyrith +Azza Bear Azzaar Azzaboy100 Azzakel @@ -1888,100 +4082,257 @@ Azzanadraa Azzax Azzgarnia Azzz +B 0 B S +B 0 S S +B 0 U J E E +B 3R +B 58 +B A F F E Y +B A MF +B A U W S +B B Bouncy +B C 2 +B C M +B CA +B D Y +B E E G +B E R T A +B E R t I 3 +B ELA +B Gates +B Gonkeybron +B I G G L E +B I R T +B Ian +B J O R N +B L 4 N K +B L A D E Z +B L A N E +B L A Y E D +B L ANK +B L I X T +B Milesy B Minor +B O G S +B O O T H +B O Y E A +B R A l N +B R II A N +B R l C E +B S +B SlDE +B T J B Victor B +B W 1 +B W A K +B aylor +B aze +B ecky +B eeez +B iggles +B la z e +B las +B r a g g +B r eezy +B rads +B raes i +B ruised Lee +B u bs +B ug +B un +B utt +B w +B-0-SS-M-A-N +B-Dollaz B-Lal +B00 KAW KEY B00Lici0us +B00MERAT3R B00ST B00SY +B00tlicker B0ARD +B0B The Cat B0BaH B0GLA B0ND +B0NERCRUSHER +B0NGRIPS42O B0OP B0aty B0atyquila +B0bz BurGerz +B0dka +B0n3z84 +B0nes2Weed B0rders B0rn B0rn2bking B0rnas +B0tched B14cksh4d0w +B1G BAD CHAD B1G8 +B1GARMS +B1GBOB +B1GGY B1G_D1ESEL +B1G_SW1GS B1RDUP +B1Te Me +B1ack Lotus B1ackJack B1asphemy B1gTTgothGF +B1gd0wg B1ink +B1mboBambi B1zrme B2AD +B2F +B2J3 B2bZeroSpecs +B2rad +B3A5T +B3CK B3NJAMOON +B3NT D0ver +B3TTERLUCK +B3Y0ND B3njamima +B3njamin +B3nny Blanco +B46 +B4RR +B4S B4llista +B6a +B6i +B70 B747B +B8 H8ER +BACKURBOI +BACONisgd4me BADASS BADDONE BADPanda2 BADUPDATES BAKED +BALD n DUMB BAMF BAMFnificent BARBARlANS BARRAGENOW BARRON24 +BASED DMM +BASEDQwert BATATUNGA BATH0RY BAYLlFE +BBBBBONKA BBGL +BBK BBKwenie +BBL RIZZY +BBQs +BBW Pizza BBarnzeyy +BBeepLettuce +BBoys Father BCBDestroyer +BCC YT BCDOJRP +BCK CigButts +BCMagoo BDCMatt BDrichard +BEANS9991119 BEARDED +BEAST ARCHER BEATONiT +BEBELAC28 +BEEA BEG0N BEG0NE BEINGMAXDSUX +BELSJ BEMBOU BEST +BET5 +BEYFYBOI +BFKay BHAFC +BIG ASHL3Y +BIG C0X LUVR +BIG HIT GOOD +BIG pontifex BIGBADWILLY +BIGD05 BIGDROPHUNTR +BIGFERGLOAD BIGHEADSMASH BIGJP BIGMINK +BIGSITUATI0N BIKlIllIlIIE +BILR0Y +BIOATED +BIRD SHlT BIRP BIRWAAA +BIS Monster BIaded BIadet BIapa +BIood Prince +BJ Applegate +BJ M +BJPlaysRS +BKBB +BKK BKLN +BL00DANG3L BL33DPL34S3 +BL3SS3D4LIFE +BLACK DOG NI BLASE BLGesus BLICKYSTIFFI +BLOBi WRX BLOOD BLUEPIZZAMAN BLXCKPINK +BLYATMOTOR BLlNKY +BMEUR +BMooldijk BMrgn BO0MERSO0NER +BOA Liger BOBGIGALUCKY BOBYAHMDGECI +BOER KAMIEL +BOGOBoneless +BOL0CKS BOLSOONARO BOMBAKLAP +BOMBU +BONITA 02 BOOPlNG BOOTTYBANDIT +BORDEN DAIRY BOSNIAQUE BOSS +BOSS OG +BOSSMANHOG BOlNEXTDOOR +BPNS Hawk +BPTheIronOne BPrimitive +BR0 BRO BR00KES BR0CE +BR0ER BR0THERS BR3AKABLE BRA71L @@ -1990,16 +4341,34 @@ BRAMMOSOVIC BRANDONSMlTH BRCH4 BREJCHA +BRUTAL BRabbit25 +BRlOCHE +BSB Howie BSNR +BST Steve +BSickler BSven-B BTCEUR +BTKMGJKL +BTMillz +BTW Beirre +BTW idgaf +BTW vs RNG BTWSaberlion +BTWsanta +BU1MER +BUHLL BUILD BUILD PONYS +BULLlSH BUNDHA BUNStheGOD +BUR13D AL1VE +BURYT0MORROW +BUSS IT BUTTB0NERED +BUTTCOlN BV Martyr BWheatZ BYEq @@ -2008,101 +4377,219 @@ Ba1i Ba5b0y Ba6y Ba77erY +Baa m +Baaaats +Baal157 BaalZvuv Baals Baalthas Baamf Baami +Baandos +Baarb Lahey Baas Baba +Baba Booey9 +Baba Borgar +BabaLovesKos +BabaSlaaf +BabaSleep BabaTarzan Babafasa +Babayaga-9 +Babayaga2121 +Baberrandrid +Babica Mraz Babiez +Babocat Baboosh +Babs221 BabsCox Baby +Baby Bear +Baby Bobby +Baby Boeing +Baby Daphne +Baby Houdini +Baby Motel +Baby1400 BabyB BabyDogeCoin BabyDogeFTW BabyGroot BabyHat +BabyHewy BabyHiggy BabyJIREN +BabyLinga BabyPandaa3 BabySas BabyTamer Babycerasaux Babydump +BabyfaceBill Babyjoker828 Bac0n BaccaM Bachelour Bachuras17 +Bachus67 Back +Back Jauer +Back Seater Back2Backk Back2ourdays BackInTime +BackToBambi +BackToOwn +BackelsOSRS Backinthe09RS Backlit +Backspace +Backsterr Backus Baco +Bacodie Bacoid1 Bacon +Bacon Glizzy +Bacon24717 BaconBlunts +Baconcannon +Baconist Baconlord100 Baconpancake Baconstrike Bacteria Bactomet Bacun +Bad Advice +Bad Ape +Bad Axe +Bad Day +Bad Fruits +Bad Kind +Bad Kuip +Bad Mario +Bad McNamey +Bad Mistake +Bad Name Now +Bad Robert +Bad Weather +Bad exp Bad2dabone30 BadAndB0ujee +BadAss_oO +BadChicken +BadChronic +BadDecision +BadIdeaDog BadIllusions +BadInIronMan +BadInNames +BadMamaJama +BadMannerz +BadSass +BadSpalling +Badaping Badass +Badass Fe +Badass Iron +Badass Rs +BadassIron +BadassPotato Badasseness Badaxx BaddieDragon Badgalriri +Badger Bush +BadgerInABag Badgerq97 Badical Badman +Badman ET +Badoodle Badora +Badora II +Baduk +Badvask +Bae-Kun8er Baeby Baekah +Bag it +Bag of Yay +BagFryLife Bagadigi +Bagan Bageera BagelSpanker Bagels Baggyshaw +Baghdad Baginga +Bagis +Bagokk Bags +Bags n Beer Bagsnacks +Bagz BahRitTanEe4 BahamutLimit Bahn Bahnzeen +Bahp +Bai Ningyang +Baib +Bail Jait Baileys Bailsby Bailz Baimonnnn +Baines +Baino BainoLad +Bainz Bairac +Baites +Baja Baja +Bajan Bajart Bajcolado +Bajela Bajere Bajhole +Bajista +Bajji Bajkami +Bajsanus Baju +Bak cornet +BakIron +Baka Mop +Baka Prase +BakaOsaka +BakaPho Bakazuro Baked +Baked Mage +Baked Saiyan BakedVandon Baked_Beagle Bakedd +Bakedmuffins BakeonBits +Baker Bully +Bakerloo +Bakers Baked Baketto +Bakhmut +Baki Hanma +Bakingsodah +Bakingsweets Bakkis Bakllava Bakron +Bakthawar Baku Bakuchiol Bakusho @@ -2110,49 +4597,100 @@ Bakuthedrunk BalIsackt1ts Baladend Balan +Balan Dinh Balar Balarezo +BalazinGIM +Balboa Park +Balbuli Bald +Bald Arab +Bald Male +Bald Shupa +Bald Sicknez +Bald To Bold +Bald Wookiee +Bald at 29 +BaldKnees +BaldMansKenn Baldfuc +BaldheadBill +Baldoc Baldorr +Baldrake Baldras Balerion Baliboosca Balkan +Balkenende Ball BallOfCotton Balla +Ballack342 +Ballade No 3 Ballcheck369 +Ballenaso Baller006 Ballerina Ballesekk +Ballet BallinBamf Ballotaa +Ballroom Bally +Ballztacular Ballzy Balmung311 Balneum Anas +Balob Balontra Balou +Balrogs Hell +Balthazar BL +Baltimohr +Baltimore MD Baltoth Baltramiejus +Baltzerboii Balu +Balu Titan +Baluk +Bam Achilles +Bam Grizz Bambi0326 BambiSlayer Bamboo +Bamboo James +BambooPandas +Bambuliuss Bamf BamfJoe Bamfbeav +Bamiman +Bamse Bamztile Banan Banefish Banerz +Banio +Bank Stander Bankaiz +Banki 1 1 Banzu +Bape +BapeNation +Bapelsin +BaphometsLov +Baptor Baqels +BarShake +BarSmash Baraek Barakoli +Baratheon +Barathrum BarbaariJuho +Barbatos Barbose Barbwiire Barbyte97 @@ -2160,60 +4698,105 @@ Barca Barca230492 Barcodes Barcoding +Barcy Bardimuss +BardleDooDoo Bare +Barely High +Barely Legal BarelyBusy BarelyDecent +Barfallonyou Barfs Barfy +Bargli Barhoor Bariviera49 +Bark sample Barkki BarnVo +Barncle Boy Barneey +Barnet Ftw Barney12370 +BarneyKing +Barneylover Barnez10 +Barnyard Boy Barnz BaroBro +Barometz Baron +Baron Iron +Baron Timmy BaronConey BaronGiraffe BaronVonGeeb +Baroondon Barqueefa +Barr +BarracuDro +Barraggah Barrako +Barrel Flop Barricade Barrowry Barry +Barry Koota +Barry0408 BarryBanaan BarsasBoom Barstukas Bart +Bart Heredit BartBelly BartSimps +BartenderBTW +Bartheez Bartholomeii Bartje +Bartol Bartycool Barzhal +Bas +Bas Waterpas Bas481 +Basant Base +Base 99s +Base Skills Based +Based Evan +Based Kyoko +Based Miyagi BasedGob BasedHeru BasedScape +Basement Dad +Baseplate86 Bash BashinBosses BashiraTHC +Bashram2 Bashx Basic +Basic Drop BasicBilbo BasicIronman Basil +Basil Hiiri Basileia +Basilikos12 Baska +Baskervilla Basket Basketballer Baskie Baskrans +Basmah +Bassaidai2 +Bassey +Basshu Fon Basshunter Bassilliaux Basstomouth @@ -2221,42 +4804,71 @@ BastasRemmen Bastermate Bastiao Bastidaz +Bastin101 Baszist +Bat Fastard +Bat Kills Bat418 +BatChatillon BatFat Batbot101 Bateau BatedUrGonna Batesanator Batgirl +Batin +Batistaisraw Batleris Batmain +Batmam Batman Batmanlul Bats BatsVsChina Batsborkair Batsmattie +BattDoode Batter +Batter Cake +Battle Jack Battousai +Battousai09 +Batu +Batussy +Batzch Batzz Bauchop +Baulsacky Bautista I +Bav Bavaria +Bawdlands Bawjaws Bawn +Bawwz DeadAf Bawz +Bax2 +Baxi 247 Baxxis +Bay +BaySeoul BayaniSenpai Bayern_pvm1 Bayes Baykr +Bayle Domon Bayleef180 Baylin Baylon +Baylon rs BaylyBoyBro Bayman +Bayou Bengal +Bayside +Baza +Baza NZ Bazilijus +Bazimga Bazmobile Bazoo415 Bazoomaster @@ -2265,45 +4877,96 @@ Bazukashrimp Bazz0r Bazzak BazzleB +BazzleBTW Bazzooi BbDontHurtMe +Bbase12 Bbaws Bboygainz +Bbubbsy +BcShane Bcgod +BchImaBus +BckOFFRTRD BckScratcher +Bcowzy Bdawg +Bdub187 +Be Aware +Be Rad +Be Strong +Be X Unlucky +Be as t +BeEzyMan2 BeFawn BeThankfulll BeTy BeaTee Beaan +Beak er +Beaken Beaky Beamesy77 +Beaming Beamo +Beams btw +Bean +Bean Bunn +Bean Slapper +Beanieus Beanis Beanisdead BeanozZ +Beanpot Beans1991 Bear +Bear Downn +Bear Finale +Bear IV +Bear Jake Bear Savage +Bear W Scarf Bear0nBeer Bear32 +BearByBlood BearByte +BearDown80 +BearGrillz BearImmunity Bearac +Beardboy Bearded +Bearded Hick +BeardedGummy +Beardedwick +Beardilizer +Bearing Down +Bearly Iron +Bearopenart +Bearrito42 BearsBeetsBG Bearsarefrie Bearsfan5455 Bearshot +Bearsome BearsyXL +Beary Beast +Beast Guard +Beast Things Beast1Range1 +Beasted Main Beastgriff +BeastieBoy31 Beastied +Beastley BeastlyGinge +BeastlyMuff Beastman642 +BeastyY69 Beat +Beat Tit +Beat my Wifi BeatboxRS Beatdown115 BeaterGod @@ -2311,34 +4974,73 @@ BeatmyJonson Beatrix Beatz Beau +Beau Ryan Beau1o Beaukaki +Beautifull Beaver +Beaver Booty +BeaverSweat +Beaverr +Beavers79 +Beavis 420 Beavis825 Bebbie Bebe BebeAtron Bebexx Bebo294 +BeboKAhnung Beckerr +Beckovas Beckyboo308 +Beckymikyu Become +Becoming Becton22 +Bed +BedByDaylite +BedForSale +Bedanc Bedeh +Beden Bedevil Bedni1 +BedtimeHERO +Bedwoods +Bee Butts +Bee Keep +BeebeM Beef +Beef Mince +Beef Squirt +BeefBottom Beefense Beefs Beefy +Beefy Potato +Beefy Treat +Beefycopter Beeg +Beeg splat +BeegeKhaos Beeghs +Beeks Beeky Beeline Beelzebubba Beelzebubby5 Been +Been Mobile +Been Poor +Beepern Beer +Beer Diet +Beer Is Cool +Beer Pong +Beer Tankard +Beer gut Jim +Beer n Blow BeerIsGood Beerchamp1 Beerfest @@ -2346,397 +5048,886 @@ Beerhana Beershits Beersmack Beerzinnss +Bees169 Beest Beestig Beeswakka BeetchAustin BeetchJeemmy Beetle +Beetus93 +BeeyondBeef BefJekyll Befkeuning +Before Snow BeforeDeth +Befsnor Ben +Begani +Begave +Beget Begin Beginning Beginnings +Beh +Behaarde lul Behemoth Behhnchod Beholder24 +Beibs Beidou +Beige Carpet +Beikengaut +Beikenost BeirH Beirreee +Beirut BekanTering +Bekfist +Bekk Bekkie Bekske Bekt Bekutma +Bel Lando +Belaa +Belamylinds Beleid Belenthir Belgarathion BelgianBeast Belgiium Belgique +Beliefofmine Belindaa BellWoods Bellatrix +BelleBeans +Bellebutties Bellerin Bellfontaine Bellicus BellsOfWar Bellum50 BellyEscobar +Bellzbellz +Belorca Beloved BelowAvrge +BelowMe +Belsassar Belsey Belsfyre Belsyn +Belt +Belt vs Kids +Beluge Belzebu Belzeddarr +Bemerson Bemke Bempii Bempire +Ben Babeslay +Ben Behling +Ben Bekkuman +Ben C H +Ben Jay +Ben Jones +Ben Kingsley +Ben Manolo +Ben Salden Ben Standish +Ben di +Ben1kzeker +BenDjammin BenDover321 +BenKuro +BenLevensMoe +BenQ Smasher BenRobbo06 BenShapirOwO BenWithJam Benarends +Benbooo Benching +BendOverBabe Bendak +Bendeguz BenderBuilda Bendigo +Bendigo Man Bendo +Bendos Hilt +Bendude +Bendyruler Bendzo Benedict Beneee Benefitz +Beneh Benelovent +BengtBreak +Bengtsson Beni +Beni Siitoin +Benifax +Benifird +Benis Hammer BenisTechTip +Benisbringer +Benja1666 Benji +Benji Stax +Benji189 Benjiii Benllech Benman Benmiester44 Benneta +Benni234 Benni2345 Bennie +Bennie Lam Bennis Bennny0_o +Benny Sins +Benny Stacks +Benny Yuh +Benny p mage Benny1175 BennyBeeee +BennyQ Bennybooom Bennyz Benocotch +Benoid +Benononono Benoragon +Benoxo Benqqu Benquad Bens +BensBent +Bensmom7 +Bensos Benstjohn Bentso Benvil Benyy +Benza Benzema1 Benzine +Benzoed +Benzylll Benzz +Beopia +Beozqt +BeppaPig BeppsaN +Ber Berada Beralf Bercuckle Berd +BerettaM9A4 +Berettapwnge BergJr +Bergheimen Bergkamp +Bergr Berk Berkan Berkis Berkven +Bermaitha Bermbommert Bernache +Bernie Mac +Berno +BernyMadoff +Beroepskech +Berraok BerrieFan Berrr Berry +Berry Carry +Berry Soap +BerryBus BerryInBooty Berrys Berrzerk Bersbillus +Berserk FTW +Bert Curtis +Bert NUFC +BertMacklin +Berta B0y Bertie Bertje Bertow +BerttDog Bervoets +Berzerking Berzurkah +Bes +Besin +Besseggen +BesselJ Bessone Best +Best Kio1 +Best Lolz +Best Murmeli +Best Nher yh +Best Realtor +Best Whilbur +BestCat BestDIzzyNA +BestFioraNA +BestHouse +BestInSloth BestJester BestMommyGF BestSenpai +BestVersion +Bestia Solus Besties +Bestkilnot Bestoladec Besty +Besynderligt +BethMeow +Bethany +Bethell Bethevoid Bethrezen +Betray Betta1009 BetterCookie +BettsISale1 Bettuh +BeugLizard Beuglord Beugsmate +BeunDeHaas Beunhaas053 Bevaun Bevelle +Bever Mama BeverGT +BeverlyPils Bevers +Beverst Bevruchter Bevvy Bewaker +Bewq Beyond +Beyond Max +Beyond Mind +BeyondKenzie +Beyond_blitz Beyta Bezbi +Bezdzwieczny Bezeo +BezosTezos +Bferg3 Bfh1master Bfood BgoinHAM +Bhaals Rage Bhakli Bhalobashi Bhangre Bhench0d +Bhillup Bhongk Bhoy Bhrad +Bht Bhuggy +Bi BiBi +BiGtOkEsBrUh BiZaAr3 BiZaM BiZoNaDe +BiasVariance Bibbit7 BibleThump BibleTrump +Bic +Biccins +Bice Bucket +Bicep Peak +Bicep Smooch +Biceps Btw +Bicho BichoFeote Bichslap +BickyChicken Bictim +Bid Whist +BidaFire Biddah +Biddiss Biden +Bidens Slow Bidensity +Bideo_Gabes BieBras +Biebje Biebop Bierliebe BierryTaudet Bierscape09 Biffo89 Biffsy +Bifking Bifta89 +Big Armpit Big Arms Ben +Big Ass Turd +Big Baby Boy +Big Bearius +Big Beets +Big Bennys Big Binotte +Big Boi Ian +Big Boone +Big Brane +Big Bruno +Big Buffalo +Big Buzz OG +Big Bwana +Big C +Big C A S H +Big Calquat +Big Cat Fan +Big Chest +Big Chugger +Big Crafter2 +Big Cypress +Big D Brasco +Big Dav II +Big Delts +Big Discus +Big Dog Sly +Big Donads +Big Dumb Zac +Big Eazy +Big Erecshun +Big Genitals +Big Geordie +Big Gol +Big Gorg Big Grorb +Big Guy Hax +Big Hingus +Big Hoss Lad +Big Jake +Big Jezza +Big Jim Hun +Big Johnnyy +Big Josher +Big Krukke +Big Latvian +Big Lesbo +Big Lew +Big Mag +Big Meth Big Mike +Big Mo +Big Mooch +Big N LilCox +Big O Wiener +Big Ole +Big Ole Dog +Big Pancaker +Big Poopa +Big Rek +Big Sage +Big Scoops +Big Seaweed +Big Shaq +Big Slick +Big Slurpp +Big Smi +Big Stivz +Big Suze +Big T +Big Tanz +Big Tripod +Big Zaff +Big mfkn Obi +Big ol Bag +Big rOve Big0neNC +BigBad Matt BigBadPurps BigBaller BigBallsagna BigBankTake +BigBantonio BigBaseNZ +BigBear675 BigBenPies +BigBinkus BigBlackCats +BigBlueCox +BigBoiiiBuzz +BigBoyBorri +BigBrad Wolf BigBrownMan +BigBtheOG BigBug +BigBulli BigBustUp BigBwanaCox +BigChinger +BigChuggen +BigChung99 +BigCitta BigCoatBrum +BigCruch +BigD Randy +BigDSurgery BigDaddyBomb BigDaddyEddy +BigDaddyMeme BigDaddyNate BigDaddyT85 +BigDick Q +BigDillz +BigDonKeedic BigDrizzleRS BigDug4U BigEar +BigEgoSmolPP +BigGreenEgg BigGuy +BigHatxLogan +BigHeadPG +BigHootyBoot +BigIronPanda +BigKusa BigLemonTree +BigLez71 +BigLiftsDad +BigLoadOfOof +BigLovve +BigLuke69420 +BigMainKilla BigMav0416 BigMilkerz BigMo +BigNerdd BigPapaDank +BigPapaya BigPepega +BigQuadric3p +BigRaph +BigRat17 BigRedDog +BigRedRodney +BigRickusTra BigRodger +BigSack2 +BigSammyD BigSappas +BigShot BTW BigSikTv BigSpook BigTastyy BigTimmy +BigUp01 BigX BigYitties +BigZikEnergy +Big_B0g +Big_Beard Bigballsac Bigbenslayer Bigborncrazy +Bigboy0007 +Bigboytec Bigcros Bigdaddy Bigdrongo +Bigex Bigg +BiggSackss +Bigga Boi +BiggerNDumbr Biggie +BiggieChonks +BiggieMcLarg +Biggieeeeeee +Biggiemollz +Biggies Maul +Biggums +Biggumz +Biggus +BiggusSnails Biggy BiggySauce Bighomiedebo +Bigjwood +Biglex GIM Bigmet +Bignoob80 +BignoseChris Bigred8616 Bigrigcoin +Bigripper420 Bigrobowskki +Bigtor Bigwildo010 Bigwilly597 +BigxFisch Bigz +Biic Biig +Biig Boobies BiigHatLogan +Biig_Boi +Biiggg B Biitter +BijnaMax +Bijstandswet Bijuzin +Biked Biku Bikura +Bil28 +Bilal Awan +Bilbalbek Bilbo +Bilbo Dabins +Bilbo55510 Bilboro Bilby Bilde Bilie +Bilk Mowl +Bilkos_Ices Bill +Bill Niah +Bill Smiff +Bill Ward +Bill Wigly Billa Billest +Billfish1 Billgodyz +Billie Boi +Billie Gin Billiee Billington Billjetti Billogbfd BillowyMilk +Bills Late +Bills PC BillsITIafia Billy +Billy Blunts +Billy Buchu +Billy H-M +Billy Joe77 +Billy Plates +Billy Tonka BillyBob546 +BillyBonka +BillyMav BillyNotRlly BillyRay Billyn +Billyreino +Billz xd BillzNSkillz +Bily Mavrick Bilybil +Bimmers Bingerss Bingo +Bingo Carla BingoBango Bingus +Bingy lol Binki2021 +Binkleborp +BinksBrew +Binky Stinky Binneli Binny +Bins78 +Binv +Bio s BioCosmic BioFrank +BioMasterZap Bioavailable Bioch +BiofieldMage Biohazard541 +Biomutant +Bionic Muse BionicKing +BionicalWolf Bionicle1395 Bionycle +Biosafety +Bioterrorism Bip0lar BipedalBear Bird +Bird Ibex +Bird Tickler BirdFactsr +BirdFarmRun Birdger +Birdie Train +Birdie713 +Birdies +Birdman +Birdman593 BirdmanZ17 +Birdmanjr07 Birdnesto Birds +BirdsNotRea1 +BirdyguyFe Birelis +Birjeldadge Birk +Birkenau88 +Birkenstock Birkenstocks +BiroGanda Birth +Birthfather +Bis +Biscape Bisccy +Biscuit +Biscuit Cats Biscuitnipz +Bishbasher +Bishbosch Bisher +Bishop Shane +Biskante +BiskyRizness Bison Bisq Bisse Bisun +Bit Bald BitScottish +Bitcoin Z Bitdefender1 Bitesized Bitey Bithc Bits +Bits Init +Bitsy Bee Bitte +Bitterkoekje +Bittles +Bitttimon +Bittykat +Bitwalker +Bitza BixT +Bizanovic +Bizarre Hobo +Bizk Bizness +Bizotic +Bizoune +Bizwald Bj0rnsson Bjarne +Bjarngrim +Bjergstroem +Bjonny +Bjorhn Bjorn +Bjorn XXVI +Bk BkGime Bkedlikelays +Bkeezy +Bken Bkguytd6 Bkostas Bl0od +Bl0od Legion +Bl0odFenix +BlG FROSTY +BlG MOBY +BlG POO +BlG WOODY +BlNA +BlSHNU BlZZ Blaaaaake Blaack +Blablibla101 Blac +Blaccy1 Black +Black Atlass +Black Bears +Black Bro +Black Caucus +Black Fuel +Black Hole +Black Hunlef +Black R X +Black Rifle +Black Upa +Black User +Black lv +BlackAliss BlackAwaken +BlackCawfee BlackCloud BlackHawkEye +BlackNuget BlackPyramid BlackTurtles BlackWidowM +Blacka +Blackasses3 Blackbandits Blackbelt Blackberry +BlackdRedHed Blackdahlia1 +Blacked Out Blackeye603 +Blackking435 BlacklMamba Blacklmp Blacknight +Blackout20XX +Blackpak Blackplosive Blacksamuri2 +Blackstar755 Blacktide1 Bladbro BladeTongue +BladeWizz24 +BladeXFury +Bladeboy6 Blademail +Bladenight69 +BladesEspada Bladypus Blaest +Blaf +Blag0 Blainyckz BlairChan +Blairzy Blaise +Blaise Green +Blaise22689 BlaiseDebest Blak +Blak Deshi +Blak Hawk987 BlakHammah BlakTooth Blakaraknid Blakdragon Blake +Blake Bar +BlakeOCE Blakeboi Blakeeeeee Blakely +Blakerke +Blakey3 Blakk Blakkeyy Blakpn0y Blame +Blame Blitz +Blame Dave Blamed +Blamer Blamp +Blank Face +BlankTree +Blanka1990 Blanke +Blankfillin +Blanks +Blap Blapa +BlaqBeard Blard +Blare Blaser Blasphemy Blast +Blast Bepe +Blastoise Blastrune995 Blaszczy16 Blattermans +Blauwe Brief Blaze +Blaze Hooker +Blaze King +BlazeBaked BlazeItDad +BlazeThatSht BlazeWhale Blazed +Blazed GIM BlazedRanarr +Blazed_Chip +Blazer Kdog +Blazer-31 +BlazerSven +Blazikenite +Blazin Blazinbiscut +BlazingGood BlazingREAPZ BlazingSid Blck +Bleak Days Bleak House Bleakair Bleasi BledReborn Bleekybleeky +BleepMyBloop Blehalol Bleidas +Bleiesnus Bleifuss +Bleken88 +BlendedWhale Blendon BlessOneTime BlessTime +Blessdd Blessed +Blessed IM +Blessed N L +Blessedcrypt Blessin +Blessnt +Bleuski Blevins33 Blew Bleyage @@ -2746,72 +5937,155 @@ Blije Blimey Blimpie33 Blimpysaur +Blind Yeti +Blind1 BlindByron BlindSamael Blindblinker +Blindeyy Blindspott +Blindwizard Blingblin255 Blinger Blink +Blinx337 +Blioneer +BlissWarrior BlissfulDrgn BlissfulIron Blisss +Blista Blistered Blithering +BlitzJuuls Blitze BlitzedBoss Blixtslag +BlizSukzNuts BlizZinski +Blizz of Ozz +Blizzard343 Blizzartd +Blk Kush Blkbeard22 Blkup Bloat Bloated +Bloats hard Blob Blobman1 Block +Block XD Blockhead +Blodmire +Blodreiina +Blodreina 1 +Blody Mess 2 +Bloedkuul +Bloeps +Blogmas +Bloke Kisser +Blom Blombo Blommer1 Blonde +Blonde Don Blonket +Bloo2 Blood +Blood Face09 +Blood Lotion +Blood Man478 +Blood Moor +Blood Rift +Blood Spawn +Blood Spawns +Blood Turd +Blood Vials +Blood Voss +Blood Wyrm +Blood0fhell Blood4Peace BloodWarzz Bloodfan0 Bloodgeon Bloodiedawn +Bloodlet +Bloodmaged +Bloodrave182 Bloodraven +Bloodredmano Bloodshade +Bloodsheds Bloodsportt +Bloody Scarf +BloodyMurder +Bloodyengine +Bloodyrootz Bloodytem BloomBouquet Blooms +Bloons TD +Blops Far +Blorgons +Blosh Blote Blouch +Blow Off +BlowBiden Blowd +Blowin Ohs +BlowingPipe Blown BlownbyTwins +Blowup Dolz BlowyBarry +Blu Ocean +Blu3Mink96 +Blu3print Blu3s BluAnimal +BluNightfall BluSPANKSyou BluSlidePark +Blubberboy BludMaul +Bludclat Bludgeoner0 +Bludime504 Blue +Blue 420 +Blue Atmos +Blue Fox 64 +Blue Inn +Blue Jay +Blue Legend +Blue Limes +Blue Nahuatl +Blue Osiris1 +Blue Oyster +Blue Summer +Blue Trex +Blue Winds +Blue Ziv +Blue305 BlueBoat +BlueBorough BlueCashews BlueDHYDshld BlueFrogsOP +BlueGwapes BlueHawkie +BlueHornet BlueJob BlueLegendzz BlueLemon66 BlueLine BlueLite +BlueMandril BlueMeanEyes BlueMuff1n +BlueOverkill BlueRanger BlueRose91 BlueTyphoon @@ -2820,61 +6094,108 @@ Bluebears Bluebury Bluecaps09 Blued +Blueface G Bluefir Blueluna Bluemoon97 Blueprint19 Blueqerry Bluerope14 +Blues 1 Clue Bluescreen +Blueshores +Bluestopher Bluetiger919 Bluewarthog +Bluexy +Blueyy04 Bluez Bluezaros Bluff Blufire +Blumkohl +Blump King Blunt +BluntBird +BluntSurgeon BluntTaster Bluntmore Bluntobject Bluntology Blunts +Blunty Pyro BluntzyMcGee +BlurOfLight +Blurr62 Blurred +Blurtt Blusaunders +Blut Arteiri Bluternite +Bluutooth +BluzCluzz +Blxke Blyat Blyckertski +Blyocr +Blze Bmart Bmaylor +Bmeg Bmoot +BmwNerd +BnB Bnaar +Bo Ed +Bo Selecta +Bo0nies +BoBgss126 +BoBoTaeTo Boa92 Boabs Boagrious Boang Boas +Boater lad +Boats N Hoos +Bob Blinger +Bob Burglar +Bob Kelso +Bob Lebowski +Bob Marley +Bob Shermon +Bob Violet Bob11790 Bob19922 Bob44th +BobBojangles +BobCatMilk BobGuenille BobNegao BobRossDied BobTheDaddy BobaNeZmogus Bobakadush +BobbaStanley Bobbanxd Bobbiie Bobby Bobby Brawl +Bobby JoJo +Bobby Lash7 BobbyBigLips +BobbyBonk +BobbyShurda BobbySmooth Bobbyccf Bobbydrake09 +Bobbysweggg BobbyyHill Bobi Bobicles2 Bobidabob +Bobite92 +Bobo Bagins Bobrobber Bobrusu Bobs @@ -2882,45 +6203,82 @@ Bobsaytoad Bobtunafish Bobvill Boca +Boca Raton +Bocaj +Boccle Bockovie +BockyOG Bodaajamies Bodacious Boddy +Bodhy BodisDelotis Bodjery Bodlamadrid Body +Body Kit +BodyRune +Bodyart +Bodybuilding Bodyguerdson +Boe f Boed Boeing Boeing MAX Boekanier +Boemsjaka Boer +Boer Salad +BoerJohannes Boerboel +Bofad Esnuts +Bofas Boff +Bog Jr BogDomen +Bogalog Bogart +Bogby Bogchamp +Bogged Dacks +Boggmonster +Boggsy III Bogi153 Boginskaya Bogmellon +Bogusbart +Bohachii Boham Bohejmen Bohn BohneSaw +BohnerSoup BoilerMakerr Boints +Boise Bronco +Bojaroff +BokOrmen +Bokbok9 Bokeva Bokje1 Boko BolaRobin Bold +Bold Smut +BoldPelipper BoldandBrash BoldupG Bolibomba BolleBenny +Bollieflex +Bologang +BolsaDeCoco +Bolsta +Boltagon +BoltonRamsay Boltzzzzz Bomb +Bomb Squad Bombergray Bomboy Bombu @@ -2928,76 +6286,171 @@ Bomer Bommerche Bommijn Bompa +Bompanero +Bompton Bomtastic +Bon Pa Tin +Bon fee BonQong Bonar +Bonar Slayer Bond +Bond Digger +Bond Huntin Bond09 +Bond4MyIron +BondBought BondedLiam +Bondegang Bonden +Bondi altti +Bondify Bondkyle +Bondoos Bonduwel Bondz +Bone Hawk +Bone Man +Bone Medic +Bone Thugsz Bone Ur Hole +BoneSurgeon Bonecrushing Bonedork Bonehead Bonen2 +BonerMachine Bones2Peach BonesNAltars +Bonez III +Bonfire1 +Bonfire237 +Bong Lenis +Bong Quixote +Bong Squats +BongAppetite +BongSec +BongTokez +BongZiller +Bonglefin +Bongletopper +Bonglewongle +BongoBasse78 BongoRider +Bongobodil +Bongotree +Bonh +Bonjwa1 +Bonk Weekly Bonkers517 +Bonkeykong Bonnaroovian BonnieTHICCC Bonnyjoy1 +Bonnyyyyy Bonus Bony +Boo Duh Boo5tn +BooBaker +Boob +Boob Dragon +Boob Slip +Boob zilla +Boobini Booblee +Boobs Mom BoobyHill +Booca +Booduh +Booffee +Boofqueefius Booger +Booger Ballz BoogerSnacks +Boogeyman Boogie +Boogie339 +BoogieCorgi Boogieman +BoogurBoy Booiesblazin Boojwazee +Book +Book of Sand +Bookie Killa Bookless +Booksmart BooleanSpl1t BoolinScape Booll05 Booloo +BoomBangPow8 +BoomFire69 BoomFloof +BoomMatt Boomdead123 +Boomerclicks +Boomfire2 Boomfire9 +Boomhakik +Boomjuice Boomstick08 Boondow +Booney Tunes Boookuh +BoopBeepBeep Booped +Boopette Boopie +Booping +BooptSnoot +Boorrie Boost Boost736 +Boosted six +BoostedBruh Boostedd Boostergold Boostify BoostyBetard Boot +Booteelick Boothanqq Boothyy BootieMix +Booties Bootihole Bootlesape Bootsjunge Booty +Booty Dishes +Booty Kev +Booty McDab +Booty Sensei +BootyCheek +BootyGod Zac +BootyNasty +Bootypixels Booxia3 +Booyeh Booze Boozem +Boozeobagins BoozyBirdy BoozyXander +Bop +Bopla +Bopoman +Boppin Bora Borads +Boramoss Borderguard Boreall Bored +Bored Idea +Bored Ingame BoredMalamut Bored_IRon5 BorenZo @@ -3006,8 +6459,13 @@ Borgiie Boriix BoringName Boris +Boris King7 +Boris sfisgh +Borkiin BorkingCorp Born +Born Abroad +Born to Hodl BornToTrade BornTwoGrind BornofDragon @@ -3017,203 +6475,421 @@ Boromer23 Borring Borsten Borussia +Bos Marmot Bos9 +BosNaes +Bosco Wong Bosh Boshby Bosif +Bosnald Bosnian Bosnier Boson Boss +Boss 4 Pet +Boss Biz +Boss Fights +Boss Mati +Boss Mei +Boss Rarkley +Boss Slayer Boss4Days BossMan BossMann +BossOnly100 +Bossalinie Bosses +Bossin x Bossk +BossmanJCriz Bossnian BossyEnemy +Bostin Loyd +Boston Tony Bosw8er +Bot Detected +Bot Matt +Bot Owen +Bot To 2277 +Bot for dayz +Bot player BotBooster Bothbalgone +Botman1431 Botsii Botsji Bottatrice +Bottlewin BottnScheise Bottrill +Botty Boub Bought +Bought Cape +Bought Gear +Boules Boulli120 Bouncy +Bound Books +Bounzy +Bourbon Time Bourgeoiis +Bournos Boutopia Bouwkundige +Bouwmans Boven Bovine +Bovyy +Bow And K0 Bow1ng Bow2ThyQueen +BowIads Bowbby Bower +Bowfa Barry +Bowfa Dees Bowin Bowinkle +Bowjacked Bowl BowlCutMonty BowlNutta BowlPacked +BowlResin Bowlcut +Bowleo +BowlerBTW +Bowlhead Bown Bownerator +Bowny20 +BowsB4Hose Bowse +Bowser Jr BowserSideB Bowwsy +Box Art +Box Office +Box T +Box Therapy +Box of Rain +BoxOGnomes Boxacle Boxedup +Boxer +Boxic BoxingNugget Boxio Boxse Boxxie Boxxy +Boxy +Boy Mobile +Boy Wonder +Boydem Boydie4427 +Boyfredaaa +BoylifeInNZ Boys +Boys Broke +Boys No Good +BoysAndGirls +BoysenBill Boysennn Boyyo Boze +Boze Worm +Boze mol BozeOog +Bozut +Br ay +Br ibb +Br yan Br00dje +Br0ox +Br0wnSpit Br3ws +Br4dders Br4w Br5andon BraBraBrad +Braaamps +Brabbss Brad +Brad RS +Brad T King +Brad017 BradIsAChad BradIsChad +BradKavanagh BraddahPoppz Braddahoodz +Braddict Brader +Bradj_55 +Bradlem95 +Bradleyussy +Bradlio Bradolai +Brads Wrath +BradyDezNutz +Bradycus Bragon Brah +Brahamus Brahu +Brain Drill +Brain Kancer +Brain Stim +Brain Sucker Brainiac2018 +BrainrotMaxx Brainsquash Braithy Brajen Brak Brakathor +Brakence +Brakke Bever +Brakza +Brallerx Bram +Bram91 BramDx Brambickle Brambo100 +Bramboo +Brammie +Bramxoo Bramziee Bran +Bran dont +BranDaMfMan +Branch Brand +BrandNewHere Branden +Brandi Rose Brandir Brandish Brando +Brando n +Brando23x Brandog Brandon +Brandon 126 +Brandon TJ Brandon9250 BrandonLarge Brandonp32 Brandonx188 Branflakez +Brannttt +Bransk +Bransterdamn Brap BrasilHemp +BraskaDad Brass +Brassy Bird BrastaSauce +BratusB +BraunBrains +BravSlav BraveBear +Bravenewfy +Braves Bravest Bravo +Bravo Eagle +Bravo Lv +Bravo8 Scav +Brawl Brawlers +BraxMax +Braxt +Bray0420 Braydons Braylor Brazden +Brazeheart Brazzerker +Brb Delivery Brblol +Brdy Breaches Bread +Bread Again +Bread Dead +Bread Init +Breadatour Breadhats +Break3r Gabe Breakchance Breakdownz +Breaver Brech Bredbeddle Breeann Breeno Breenus +Breeoh +Breez +Breezeeh Breezy +Breezy Jai +Breezy2277 +BreezyMT Breffest Breivig +BrejchaBoris Brejin +Brelinguette Bremen71 +Brendann Brendvn +Brenkku Brenkolovski +Brennzo +Brent Ham Brent4000100 Brentiscoool +Brenty88 +Breskvice +Bressjul Bret BretHammy24 Breth +Brett who +Brett6910 +BrettThePunk Brettdog Bretz +Brevetted Brew +Brew Dr +Brew IPA +BrewceWillis Brewdo +Brewin BrewskiGod Brewsley Brewsy +Brex Brexit Brezell Brezzy +Brian Dub Brian-senpai +Brian1234146 +Brian4755 Brian8781 Brianmyth +Brick Brick Brick49 Brickerino +Brickhead +Brickhooouse Brickhouse +Bridding +BridgeFourr +Bridger +Brie Larson +Brieenne Brief +Briefly +Briggs +Bright Day22 Brightest +Brightly +Brihyun +Briickzz Briidi Brin Brinfish Bring Bringtheheat +Brinkler Brinkosaurus Brinsgr Brisiinger +Briskly Brispy +Brist Brit Brite +British Diet +British bamf Britswelll Brittanys +Brittanyx Brlm BrntSausages +Bro bee +BroTwoTher BroUFailLol +Broad Broadboat +Broadday Brobasaurus Brobible +Brobin +Brocadillo Brocaine +BroccCheddar BroccoIi BroceanMan Brocepticon Brocknation +Brocolis +BroderPierre Brodie Brodie410 Brodie827 +Brodisi Jr +Brododore +Brodus Clay Brodymon316 +Broekloos +Broficiency +Broft Brogfrogdog +Broha +Brohard Broiled +Broken Cpu +Broken DPS +Broken Hip +Broken Top BrokenBones Brokenn +Brokensunset Brokk +BrokkMachine +BroknScrotum Broko Brolic Broly Bromagic +Bromatron Bromerly +Bromosapienn +Bromz +Bron Yr Aur2 Bronkey Bront +Bronxie Bronxy +Bronze Cow +Bronze Eel +Bronze Moose Bronze5 BronzeDong BronzeWorthy +Bronzegnu199 +Bronzr Bronzy BrooceWillis Broodje @@ -3221,38 +6897,69 @@ Broodoos Brooke Brookesbeast Brookfield +Brooksher +Brooksy BroomInBum Broomi Brootloops +Brootuss +Broque Bros Brosaph +Brosoul +Brossy Brotatochip +BrothaForest Brother BrotherChong +Brothermon Brotherr +Brotholomew Brown +Brown692 GIM +BrownTree +BrownTree63 Brownecakes Brownmo +Brrandon +Brrd +Brrinn +Brrr Zeus +Brthdy +Bru now Bruce +Bruce Jenr BruceJennder BruceNutty BruceWayme Bruceh +BruciebearTV Bruenor +Bruffell +Bruges Bruh Bruhh +BruhhChungus +Bruhs Bruiser Brumaks Brumle Brundeen Brundles +Brundo Brungoil +Bruno p15 Brus Brutal Brute Brutescape +Bruthar +Brutified +Brutzli Bruut +Bruva Eww Brvte +Brwny-mix Bryan BryanFury Bryannn @@ -3261,88 +6968,152 @@ Bryce Brychu Bryci Brycikins +Bryham0 +Brynildsen +Brynmor Brys Journey Bryson Brysons Brystreams Bryu Bryymstick +Bsakke Bsaunders0 +Bse +Bsgs Bsketbl +Bskli +Bslayer Bthomson Btownballer Btrec +Btv +Btw Das +Btw Guy +Btw tietjes +BtwBallo BtwImJoe BtwTradeMe +Bu nny Bu11itt +Bu11seye00 BuBszs +BuDzNBooze +BuLLeT PVM Bub Josh +Bub389 Bubba +Bubba Gage +Bubba Watson Bubbateux +Bubbba Bubble +Bubble Butts +Bubble Tea65 BubbleBlob BubbleJuice BubbleOLuke Bubbleguy Bubblenab BubblesGO +Bubblies Bubbo Bubbz +Bubgi moment +Bubo Bubu Bubzs +Bucc ees +Buccsta Buchu +Buchu Bong +Buchu Daddy Bucito Buck +Buck Oakly BuckNastyy Buckeye BuckinThanos +Buckjames Buckner1 Buckner20 +Bud Right BudLightBtls +BudSake Budabupbup Buddaball BuddahCheese +Buddeke BuddhaPuck +Buddweiiser Buddy +Buddy Waters BuddyGuy +BuddyJ Budgen Budget Budgets Budjeke Budpotamous +Buds Bud +Budsteel Budster Buduhhh +Budward Budwise +Budzinski Budzliteyear +Budzyn Buff +Buff Bezos +Buff Mafia +BuffFridge Buffel +Buffel x Bufubu +Bug V2 +Bugalado +Bugaloo Bugazzi +BugcatMoo Bugg +Bugg XO +Bugis x Bugs +Bugs c Bugsaur +Bugyo Bugyy +Bugziee Bugzy Buhe Buhnuhnuh Buhole Build3d Built +Built Dfrnt +BuiltToSpill BukesCarKey Bukkakey +Bukkele +Bukmyhr +BukseFar Bukt Bula +Bulb_a_saur Bulba BulbaThor Buli Bulk Bulkier BulkyTrout46 +Bull Shifter BullSharkBob Bulldawg1289 Bulldogs815 Bulldozer297 BulleT1017 +Bullerbyn Bullet135191 BulletBlitz Bullschiff @@ -3351,91 +7122,180 @@ Bulltill Buloz Bultac Bulte +Bum Hole +Bum Vinegar BumPounder Bumble +Bumblethumps Bumjam +Bummer +Bummholee +Bumveld +BunanaMuffin +BunanuhBread Bunceylad Bundle +Bundy red +Bungle Bug +Bungstar BungusBoi +Bunion Bunjamino +Bunni Pig Bunns +Bunns Dying Bunny +Bunny DeIron +BunnyRabb1t Bunnytrack +Bunq Bunryl Buns Buntian +Bunty Boy Bunzosteele +Buorin +Bup Buqqi Bur eye on +Bur y +Burak I Buray Burec Burens +Burensbd Bureze Burezz +Burg de Rott Burger +Burgerb0y Burgerr +Buri Burial Burials +Buried Mole Buriial Burkekey +Burkkle Burly +Burlyy +Burmecia Burn +Burn Herbal +Burn With Me +Burn t BurnMyChi1d +Burna Boy Burnardo Burnari Burnceller Burned BurnedIron Burners +Burnetplanet BurnhamAll12 Burnin +BurninOctane BurninStarIV BurningBrian +BurningCole BurningFight BurningKushh Burningdavid Burninghippo +Burnley Burns +Burns Green Burnstown Burnt +Burnt Bonez +Burnt Bunz +Burnt Senpai +Burnt cod +Burnt lol BurntT +Burntmeat BurnzWhnIPvp +Burnzaloree Burnzie Burp +Burpenen Burpsy Burrkle Burst +Bursts Burwell Bury BuryMeDeep Busch +Busch Ebba Buschhhhhhhh Buschhuscher +Buschkilla Bushbaby Bushido +Bushido Jack +BushidoNegro Bussch Bussino +Bussy Bwana Bust Bustard Busted +Busted Shaft +BusterBlader +Busternut +Bustinbibear +BustyBarry +BustySaurus +Busy Phat BusyDayToday BusyRightNow ButMuhMain +Buthole +Butinz +Butje Kef Butlergunner +Butt Clouds +Butt King +Butt Liquor +Butt Plog +ButtChugr +ButtExpert Butter +Butter Sock +ButterSirup ButterSyrup Butterbur Butters +Buttgers Butthxle ButtnCLICKER +Buttt Mud Butzaf06 +Buu Blat +Buuloki +Buurtpooier Buus Buutsika Buwuchu Buwuchuu +Buxi +Buxom Lady +Buy Wards +BuyBitcoin01 +BuyGF_1GP +Buyer Beware Buying +Buying IG GF +Buying gf 2M +Buying99rc BuyingRsGfs +Buzi Mi Daj +Buzi Syrom Buzin +Buzin Benji +Buzy BuzzL1teBeer BuzzMax Buzzard @@ -3444,121 +7304,294 @@ Buzzlghtbeer Buzzzwin Bvanana Bville23 +Bwan a Bwana +Bwana Brah +Bwana Haz +Bwana I +Bwana Rat +Bwana TK +Bwana Zander Bwana-senpai BwanaObama +BwanaOnDrugs +Bwanah Bwananabread Bwanario Bwanner +Bwarath Bwekfast Bwekfeest Bwie +Bwila Bwse +Bxao Bxdhi +Bxo +ByDesign +Bye Felicia +Bye Friend +Byles Bynguyen Byrd +Byrd Gang +Byrd Park Byrne ByteMeM8 Byzo Bztm +C 678 +C A M R O N +C A R S 0 N +C A R S O N +C Biologist +C D C D C D +C H l S E L +C H l Z E L +C HARL IE +C HlCKEN +C J 102 +C L A M P +C L U E 5 +C Maelstrom +C Mauricio +C OLLINGWOOD +C R I X US +C RoyMustang +C Rx +C S +C Sol +C Trafalgar +C W +C Wills +C a c h e +C a le b +C a r lo +C a sp er +C alvarium +C amel +C e v +C eej +C h a ds +C hap +C hristt +C ip +C itadel +C lhris +C nr +C ntmaster +C o r a l +C oach +C orgi +C osmos +C oty +C rafter +C raig +C raiig +C rux +C u r t +C x L C-11 +C-53 C-Dom +C-Stones +C-bat +C00RS Light C00per +C0Dl +C0LTE +C0MBAT 126 +C0RAZON +C0SA C0WK C0XG0BBLER +C0Xsuka4gp C0YS C0c0nUt +C0dy +C0dyssey C0nner C0wanz C11 H15 NO2 +C137 Beth +C18 C18H27NO3 +C204 C2okies +C3 P0 +C33 C3Pz +C4 RL C450 +C4L1BRE C4RL C4RNAG3 +C8M +C9rl CA5E CAKESNIFFER CALL +CAMBO D N CAMEL0T CANNONlNG +CANT SPEAK 0 CAPITALIST CAPSLOCK +CARAPlLS CARDlFF CARROLLYZER +CATS GO NYA CATsmoothies +CBC +CBD Brownie CBK20 CBMPeterson CBas CBomb +CC 9 +CC HM CCCCFF CCCO CCatt CChuk +CConnor CDKein +CDR +CDRMark +CDawg420 CEClL +CEL4L +CEO OF ARK +CEO of TOB +CF5 CFoodBisc CFour CG MindPr0 +CGA +CGC Zeus +CGR +CGoldy CH1P CH3CKMYSW4G +CH4OS_REIGNS CHATBN +CHEEFO CHIEF CHIEFWHALE +CHIEFxKEETH CHOF28 CHOLEZmusic CHOPSTlCKS CHOSENBYNAME +CHR187IAN +CHRlS PRATT +CHRlSDUDE +CHUCKDABANK +CHUDZY CHULIGAN911 +CHURNlN +CHlC-FlL-A CHlCKENS +CHlCKNUGGET CHlLDS +CIA GF PsyOp +CJ McCreery +CJ2K +CJB_01 +CJPez CJlivin11 CJoaboneP +CK the Wise +CK2 +CK9 CKSKEE CKVY171 +CL0wn Inc CL3O CLIIllIIllIT +CMBloodcraft CMER CMMCTk +CMU Chips CMoneyTwo CN77 CNC2112 +CNGT +CO maxplayer +CO0RS CO1N +COKECOKECOKE COLE COM3THAZINE +COM3TS CONFlDENT CORONA CORP +COTTONPlCK3R COVID +COX Kane +COYM COYMauves +CP8 +CPA Scape +CPR +CPT Morghun +CPT-Rock69 +CQJB +CR1SPY_BAC0N CR4ZYH34D +CR7 +CRAI9 CRLmastrFlex CRSSD CRTS CRUSlR CRY0GENIC +CRlMP CRlP CRlSTO CRlTIC CRtallboy +CS6 +CSG0 +CSchicky CT42 CTFU +CV90 CVID +CVTRILLOG +CYP 3A4 CYP450 +CZHANG +C_mrade +Ca 11 +Ca m el Ca3ino +CaL4MiiTYxX CaMOOflaged +CaPl Caam Caater +Cab Up +CabbageSeeds +Cabbi_cs +Cabdi Cabela Cabido +Cabinetsalt +Caboose121 Caboucha Cabouchi Cachalot Cache Cachet +CacklingMagi Cacoadragon Cactus Cactus9k +Cactusaak +Cadallic0 +CadmiumBird Cadov Caduzitcho Cadzie @@ -3567,143 +7600,290 @@ Caelanity Caelums013 Caerus Caesar +Caesar Pasta +Cafe Fraiche +CafeZing +Caffeine +Caffeine Use Caffeiner +Cages +Cagrets Cahors +Cahsmo Caide +Caifan Caifanes +Caillou hobo +Cailthun Cainie Cainn Caio +Cairn08 Cairo Caiser +Caitlin Rice Cajjj Cajun +Cajun Blood +Cajun Fox +Cajun Fries +CajunCrimson Cake +Cake qp CakeBoss1337 +Cakeboy 43 +Cakefound +Caketins +Cal Fong +Cal l u m +Cal-Mag +Cal_C +CalamityD Calamityy Calb_Potta Calbod Calcab Calcd +CalciferGIM +Calcio CalculateWhy Calcusource +Cald0g +Caldaris Caleb +Caleb o_o Caleeba Calf15 Caliace Calibeafall Calibrated +Calibur CaliburZ Calico +Calierazon +Califaa +Califauxeous +Califirona Calimandro Calipha Calipso +Calist0 Calisterie +Calivego Call +Call Me Milo +Call me Cham +Call me m16 +Call0 CallMeCletus CallMeGeorge CallMeJAS CallMeJoey CallMeKeen CallMeKeezy +CallMeLeger +CallMeNoLuck CallMeSofD CallMeStevo CallMeTipz +CallMeow +Call_Me_Arty +Callaghxn777 +Callboy Calliburr +Calliott Callisto +Callisto Cub CallmeZach Callmekee +CallumTM +Calluum +Calm Chris CalmCombo CalmDownSon CalmYourBits Calmoran +Calo3 +Calquat +CalquatFruit Calster26 Calu Calum Calvi +Calvi n Calvin +Calvin924 Calyxsys Calzano Calzone +CalzonePizza +Cam Jong-Fe +Cam Jong-Un +Cam Rebuild +CamAlot_iron CamDeezy CamLite +Camakie Camaniack +Camargue +Camb o Cambeezy +CamboSliice Cambridge +Cambulance +Camdenan +Camel Glue +Camel Neckit +CamelActive +Camelm8 +Camerocity CameronNeal Camhanaich +Camil Camion Camise Camm +Cammo545 Cammy +Cammy Ded Camosaur +CampBingBong Campbell Camperfish CampinOnline +Campisii +Campus Crew Camsdadddy Camshows Can Berry +Can Fe Spoon +Can U C Me7 +Can it Bozo +Can0fBeans CanChem CanMJ +CanManCannon +CanOManBFTM +CanUGetAway Canada CanadaBawd +CanadaGuuse +CanadaScape2 CanadasChief Canadian +Canadian Bc +CanadianDevi CanadianYeti Canadiehn Canadiian +Canan32 +Canberk +Cancel Cancelled +Cancelled It Cancer7 +Cancerfree24 Cancerios +Canderos +Candlebox Candrok Candy CandyFlipin CandyKing42 -Capt -Capt420 +CandyKing420 +CaneCorso Canear Canehdiann Canibalistic Caniz Cann +Cannabinoidz +Canned Beer +CannibalGK Cannibble CannoliBoi +Cannolis Cannondorf Cannot +Cannot Login +Cannrrrr +Canon Bob Canook Canowhoopazz Canserber0 Cant +Cant Quit 07 CantCasino +CantMaxBc69 +CantTalkPerm CantThink +CantTradeTho Canta Cantaloupe +Cantclik4sht Canter Cantina +Canting Cantu +Canyonranger CaoFasho +Caoe +Cap E Bara Cap10 +Capalotty +Cape Fear +Cape Max +Cape Seller CapeScape +CapeZer0 Caped Capez CapiiTano CapitalGainz Capitalise +Capitalist34 +Capn Wahle CapnCookd CapnMeliodas Capniq +Capnplant +Capo Yamato Capone Capos +Capotia Cappe Cappei +Cappie Greek +Capreol Capriccio Caprius Caprix Capsule +Capt +Capt Bobette +Capt Bumi +Capt Dave +Capt G +Capt Halo +Capt Hootler +Capt Kenway +Capt King +Capt Kumquat +Capt Murdoc +Capt Plank +Capt420 CaptHardon CaptLongJon +CaptPleb CaptZilyana Captain +Captain Jack +Captain Lev1 +Captain Tast +Captain Tec +Captain Y +Captain Zoso +CaptainAlice CaptainCanto CaptainCox CaptainDom @@ -3711,6 +7891,7 @@ CaptainDredd CaptainLuker CaptainOboy CaptainObvio +CaptainWalt Captainshiny Captainzzz Captan @@ -3718,44 +7899,62 @@ Captcha CaptinA CaptinKorasi Captinrandom +Captiva Captn +Captn Bear +Captn P00F +Captn Sqirk CaptnCommand CaptnMittens Capu Capussi +CapybaraDung +Car Ram Rod CarNalgas CaraDuraMC Caracal Carademlof CaramelSlice Caratheodory +Carbo Cat Carbolic Carbon +Carbon K CarbonCarbon Carbonist +Carbos Carbyne Carcinoid Carde +Carden CardiacKemba +Cardinxl1 +CardyZ Main Care Carea Caregiver Careo +Caricapaya Cariej CarimsEygon Carino +CarjUIM Carjacking Carked Carkis Carkosa Carl +Carl Sagan CarlBarker CarlDerp CarlSagan80 Carleton789 Carlin +Carlingue +Carlitos Carlo CarlosM +Carlosjavily Carlrip Carls453 Carly @@ -3763,6 +7962,7 @@ Carlyle Carmillae Carna Carnadova +CarneGrande Carnie CarnifexVeil Carnitas @@ -3771,93 +7971,188 @@ Carnzlo Carolan Carp3di3m13 Carpe +Carpenters Carpi Carr CarrickDaddy CarriedBayo +Carrot s +CarrotMilker +Carrs Pasty +Carrutt Carry +Carry Yak +Carry9otter Cars +Cars Suck Carsillas Carsten10 +Carterfish +Cartman Carton +Cartzy +Caru +Carvdogg17 +Carve +Caryopsis +Cas1a CasZeal +Casamigos +Casawn +Casc Casca +Cascola Casell +Caseten CaseyWaff Cash +Cash two Casherbob Cashewk +Cashlemke +Cashs Main Casino +Casino Sand CasinoProblm Casketball Casmatos +Cass Cath CassTheGod Cassarole Cassath Casserolio Cassidyy +Cassie Aram +Cassim +Cassirer Cast +Cast Rate +Cast Turbo Castello Castilla Castorly +Castrophany Casual +Casual Man CasualChris CasualGrinds CasualPete CasualStorm +Casualdkdk +Casualty +Casvel +Casviel +Cat Man1001 +Cat Nips +Cat Shaped +Cat Smuggler +Cat Snacks +Cat Soup +Cat Woman +Cat got out +Cat shirt +CatBoyInHeat +CatPandas CatPissRNG CatSaysMeow +Cataclysm55 +Catala Catalepsy +Catalyticx Catan CatchTheDrop Catchin +Catchin Pets Catchlove Catdog1280 +Catechism +Cater Champ +Catfish Rock Catflap +Catgirl Cafe +CatgirlSan Cath Catharina Cathays Cather Catherbae Cathuntdog +Catman31 Catnip +Catnip Cutie Catnor Catomic123 +Catra Meow +CatsnCars +Catsnarterrr +Catspeak +CattoKitty3 +CauZ Cauldrons Caulf1eld +CaulkPushUps +Caustic Cauterised Cavaleiro888 Cave +Cave Closer +Cave Horror Cavern +Cavern Freak Caves Cavos Cavs Cavsy +Cawrin +Cayk +Cayman 07 Cayrus +Caza Lowell +Cazaq2 Cazik Cazos Cazum Cazwise Cazzakin Cazzy +Cba Ofc +Cba To Carry +Cba To Share CbarDaKing +Cbetrs +Cbf Playing Cbot05 Cc17wo +Ccn Cd777 Cdale +Cdoc +Ceana +Ceb Ceber +Ceceil10 Cecetra CedIsMySon +Cedty +Cee real +Cee-Jay +Ceebooty CeeeHooo +Ceeege +Ceejaydjj +Ceekay Ceeon Ceeps Cefiro Ceio CekicGuc Celach +Celach 2 Celadus24 Celazer Celebio +Celer0 +Celesdel CelestialSun Celestive Celestron @@ -3865,130 +8160,229 @@ Celhon Celi0 Celiac Celikanen +Celine Dijon +Cell Saga +Cell Z Saga +CellaDwella Cellectric Celli Cellmate Celms +Celrisen CeltBrenny Celtic +Celtic Hero +Celtic555 Celtica Celyzh +Cemen Demon Cengkeh +Cennolink Cenpie +Censor +Centac +Centennials +Center Fit Centers +Centershot5 CentraIka +Central CentralC +Centrimag Centropy +Ceo of Timbs +Ceoe +Cephalopods Cepp Ceppt Irn +Cepxy Cera Ceraseus Cerati Cerb +Cerb R Us Cerberus Cerberus98 Cercle Cerea +CerealGuy +Cerebro +Cerenade CeriGG +Cerkev Cermi Cerpin +Cerpin Taxt +Cerpooch Cersey +Cersky +CertIronBoy +CertifiedPoS Cervantes18 CesarPalace Cesema Cetr Cets +Cev Cevap Cevarus Ceverie Cewl +Cewl Hwip +Cexilius Ceyyl +Cf b4 Cfretz244 +Ch i +Ch i c k en +Ch ief Ch00bies Ch0c0tac0 +Ch1cag0 Bear Ch1mes +Ch1noLf +Ch1zz Ch33sy Ch3ckMat3 Ch3spy +ChNPP +Cha rles Cha0ticAngel ChaCha +ChaCha Benny ChaSniff +Chaavez Chaboud Chaboul +Chacaliando +Chacksen Chad +Chad Draven +Chad Stride +Chad Vibes +Chad Wardn +Chad again +Chad isAFK +Chad okeefe +ChadBehavior +ChadCor ChadFratStar ChadMadLad34 +ChadR3333 Chadacas +ChadamantBar Chadders Chadding +Chaddyboy Chadga +Chadieus Chadkiller76 ChadronX +Chaehee Chael +Chaendo G Chaewon +Chaga Chai Chain +Chain Mace Chainn Chainsaw +Chainsaw Guy Chair ChairmanMao +Chaiyse Chaken +Chakleton +Chakra Monk +Chal1ce Chalba +ChaldeanGIM +Chalgrove +Chalk Bar Chalked Challandria Challll Chalva +Cham Cham +Chamariapero ChamberBeast Champ +Champ Ryan +ChampGaryOak Champagnole Champiion +Champion910 Championship Championz Chance2Skill +Chanced Chancellor +Chancie Chandler737 Chando ChangWu Change Changebear Changes +ChangrOfName Chanios +Channel +Channon Chaos +Chaos River ChaosBandego ChaosCleric +ChaosD00M +ChaosGIM +ChaosInbound ChaosJS ChaosedElf1 Chaosfish33 Chaoslynx +Chaotic Cole ChaoticH0B0 ChaoticMoott +ChaoticScorp Chaotixx Chaottic Chaoz Chap Zachman +Chap em up Chapels Chaplain +Chapo Chapoo Chapp +Chappe Chappers Chapter +Char Zeta +Char lang +CharL-32 Character252 Charamio Charatcur Charben Chardonn ChargeN +Chargez Chariot Chariten +Charitonin Charizardz Charlez +CharlieFTG CharlieFine CharlieOHair +CharlieScene CharlieTheIV CharlieWork Charlieb9 +CharliesFE Charloi Charlotta Charltonb +CharlyDarwin Charm Charmey Charmin12 @@ -3996,208 +8390,374 @@ Charmos Charmoul Charms Charmy +Charon0 Charor +Charred Yews Charrysteas +Chartart +Chase Goals +Chase Jones +Chase Riley ChaseGuy ChaseNBake ChasePP Chaser959 +Chasing Pets +ChasingDragz Chasmata +Chasse +Chastised Chatorbait Chattanugget Chatto +Chatty ChaukletZ +Chauman0819 Chauska Chavi Chaz +ChazMac Chazzdiddy ChazzedBangr Chazzy +Chazzy Paws +Cheah +Cheaps Check +Check Point CheckAndMate CheckRaiseHS CheckTheWiki CheckWikiPls +CheckWikiPlz +Checkaaa Checker +Checkley Checkmate CheddLaurent Chedda Chee CheecHnChong +Cheech Blaze +Cheeek Cheeks Cheeky +Cheeky Peeky +Cheeky Prawn +Cheeky Tom CheekyBanter +CheekyCheeto +CheekyDrop Cheelee Cheeno Cheepnis Cheermancy Cheers Cheese +Cheese Borgr +Cheese Slice +CheeseTax +Cheesebubby +Cheeseilton Cheeseit32 +Cheesteri Cheeswiz +CheesySweet Cheesyrice Cheetas CheetoRatFan +Cheetu +Cheex +Cheez-Zits +Cheeze Caper +Cheeze Nepz +CheezeOx Cheezer2000 Cheezewiz0 Cheezo +Cheezuz Cheezyboy25 Chef Chef Bu Fang +Chef Malone +Chef Mihali +Chef Peter +Chef Poopy +Chef Special ChefBoiRJay +Cheff Zaya Cheffrey Cheffy95 +Chefs Cheif Cheimuu +Cheiquispir ChelTheNelf +Chelate_D +Chello Sexy Chellyy +Chelsea Bot Chelsko +Chelsy Chelx Chemanelo ChemicalFade Chemleech +Chems +Chen Luu +Chendlar +Chenzooo +Cheomeister Cherba Cherisu Cherno-byl Chernoblyat +Chernobyl +Cherri Bomb Cherry +Cherry Field Cherrydown CherryxPiex Chesco +Cheshmate Chesscape420 ChessyQ18 Chessyboi Chestbrah +Chestbroh +Chester63 Chesterfi3ld Chestickles +Chestnut Chestodor Chet +Chet Baker +Chet Max +Chet Ripley +Chettos Chevaliers Chevrolet Chevron ChevyB1998 Chew +Chewbacca No Chewbakkaah Chewby +Chewby Lt Chewed Chewitt88 Chewy Chey +Chi hiro +Chi11 Wi11 ChiCity +ChiIdo ChiLongQua +ChiamataM +Chibattagreg +Chibber +Chiboubo Chicanery Chiccbacca ChichaBabby +Chichhuve ChickeNOG Chicken +Chicken Cat Chicken996 ChickenRings Chickenelli Chickenneth +Chickens Inc Chickensnout Chickerolies ChickinNugie +Chico Bean +Chico Cool5 Chicold Chicopee +Chid Heredit Chie ChieFbLuntz Chief +Chief Checka +Chief Gordy +Chief Herres +Chief Otaku +Chief Seneca +Chief Sound +Chief Toxine +Chief812 +ChiefBobert ChiefSmakaHo Chiefss ChieftonP Chiekz +Chiester 45 Chigginwangs Chiiiraq Chika +ChikenLiro Chikinbone Chiksan +Chikupa Chilasr Chilaxinman Chilcos +Childhoods Childish Chilgamesh Chili +Chili Pepper +Chili Popper ChiliTurd Chilibean ChilidogBank Chilidoger +Chilipupper Chill +Chill Mate +Chill Maxxy +Chill Zege ChillAssGuy +ChillHill +ChillScape Chillagalet Chilled Chilli +Chilli Ramen +Chilli dong +ChilliPesto +Chilliam +Chilliburns Chillmitch Chillrend +Chilly +ChillyPolarB ChimJongUn +Chimbilin Chimera364 Chimire Chimmy +Chimneybob +Chimp10n +Chimpywimp ChinStar China ChinaInBox17 ChinaSupaman Chinanumber1 Chinchompin +Chinchonkerz Chinchoopa +Chinegroe Chingie +ChingwaChing +Chinley Chinolc +Chinook Bram +Chinquila Chintan +Chio Bu +Chionophobia Chip Chip Black +Chip Skylark ChipRain +Chipotl e +ChippedHam ChipperyChip Chippy +Chippy btw +Chipsbok +Chipsncrackr Chipster321 Chipz Chisa Chisels +Chiswick +Chitus ChivZz +Chiw ChixDigTbows +Chiyo-Father +Chizle +Chizzet Chkn ChloeTragedy +Chloemacmate Chloes +Chloramine +Chnce +ChoNaWiadro +Chob Choccazz Choche +Choco Flex +ChocoMeteor Chocoblow Chocobo Chocobos Chocomalo14 +Chocys Chodemate +Chodless Chofl Chohanzzz Choi Choicess +Choke Daddy ChoklatMoose Chola Cholesterol Chom +Chombe +ChompVonDile Chompadile +Chompakilla Chompy +Chompy chick Chompys Chon ChonYee +ChonerScaper +Chongsy +ChonkPenguin Chonksta +Chonky Duck +Choobage Choobcob Choochy Chooks Choomb Choooooooch Chop +Chop Rips ChopSthix Chopemania Chopin ChopinDolphy +Chopinaway +Choppa ChoppinWork Chordes Choreboy Chornflakes Choronzon Chosen +Chosh Chow Chowfun +Choybin Choz ChozenGod +Chozen_Azn Chozo +Chozo Lite +Chozo Statue +Chqse +Chr Mck +Chr0nl Chranic ChrdyMcDenis Chri5ty @@ -4205,11 +8765,21 @@ Chriiiis Chriisgg Chrimon Chris +Chris F +Chris JR +Chris Luxon +Chris P3 +Chris Slays +Chris xD Chris0527 Chris1f +ChrisCleans +ChrisFate ChrisHanson ChrisKringle +ChrisOnTilt ChrisTheUnit +ChrisThomps Chrisadk Chrisha Chrishowe @@ -4217,67 +8787,122 @@ Chrisible Chrisjay Chriskies Chrisob +Chrisog Chrispy +Chrispy-sama Chriss +ChrissPIBass Chrissy +Chrissy Tooh +Chrissyx Christ +Christ an +ChristFarley Christiannnn Christidog Christlan +Christmonkee Christoffer Christoker +Christopher ChristyCloud +Chrisxmas Chriz +Chriz297 Chrizzoz95 Chrl Chroist Chromadorr Chromalox Chromatica +Chromi ChromieOX Chromixe Chronepsis Chroner Chronic +Chronic Jack +ChronicChris Chronicflame ChronnerBro +Chrono Aeon ChronoKiller Chronoburn Chronomancer Chronorage Chronos +Chronosanity +Chrostopher +Chrunndle +Chrusee +Chrysaorr Chrysaros Chryserys Chub Chub n Tuck +Chubafet Chubby +Chubby Nomad +Chubs-Magee +Chubsy Bubsy +Chuchin Chuck +Chuck Hoots +Chuck Prime +Chuck truck ChuckChan ChuckDogg +ChuckMeDaddy +ChuckNat ChuckSpedina ChuckTesta Chuckerberg +Chucky Chuda007 Chug +Chug Butt +Chug KoolAid ChugMyPPot +Chugg Jugg Chugga Chugger Chugging +ChumSlugger +Chuml +Chump +Chumpingham ChunchuloX +Chunetops Chung +Chung us +Chungus-kun ChungusClam Chunk +ChunkiCinni +ChunkmanFYB +Chunksy +Chunky Nan +ChunkyGimp Chunkybudda +Chupa Chupperino +Chur Broo +ChurchMouse ChurchTuring Churchfield +Churchieboy +Churd Churlrunone +Churnin Chuzyz +Chvrles Chxmpanzee Chyky Chyna +Chyurr CiSCii Ciamballer +Ciaphas Cain Ciastkowy Cic321 Cicely @@ -4286,241 +8911,447 @@ Cici Cicindelinae Cider CieloQueen +Cigarettez +Cigblaster +Cigggy +Ciggitybutts Cighan +Cignii Ciji +Cim Cimakas Cimelia +Cinamin Cincinnatus Cinderal Cinderhulker +Cindirty +Cinemaxxin CinmarRS +Cinoxe +Cinqoo Cinquain +Ciomsa +Circle Pea +CircleStrafe +Circleone58 +Circomcised +CircularSaw +Circumflexx +Circus Clown Circuz Ciresidnal +Cirexi Cirez Cirmit +Cirn0 +Ciroren +Cirrus Virus +Cirth Ciryatur Cisco +Cisk Cisplatin Ciszak1996 +Cit Funt Citadel +Citadel Wyrm +Citate CitizenTay CitrusLemons +CitrusTree City +City Limits +City Morgue +City Perks Civeo +Civz +Ciziin +Cizre Cizzakillss +Cjg117 Ckale +ClGARO +Cla ws Claca Claco Claiborne +ClairDeLune +ClaireFarr0n Clambam Clamburglar2 +Clan thmoker ClanChats +Clan_Daddy ClankImaTank Clannyy Clanworld Clap3d +ClapMaster4K ClapMeMommy +ClapYouDown +Claptrap ClarKah Clardy2 Clarisse +Clark C +Clarkey BTW Clarky +Clasherz Clasico Classic +Classic Max +ClassicTrap +ClassicVibes Classically Classickxd Classsikh ClassyCod +Claudenstein Claudiu Claw Clawdius Clawsie +Clay Nasty +ClayNugget Claymor Claypops +Clayters Claytn Clayton Clazerbeam Clean +Clean Dishes CleanSleeve CleanedBown Cleann Cleanst Clear +ClearEyes Clearly Cleatis Cleaver CleaverGreen Cledos Clefable +Clefairy +Cleg Drop Cleible Clem Clem585 ClemFandango CleoTehCat +Cleopatraa Cleoxc +Clerric Clethbery ClevelandOH Clevey ClexOrie +Cleyra +Clff Cliche Click +Click Bosses +Click hero ClickAndChil +ClickB8 Clickbait21 +Clicks0nMobs +Cliffder Clifferd +CliffyOG Cliffyy ClimateChang ClimberAZ +Clingy +Clinician +Clinicwater Clint Clinttt Cliphanger1 Clipper +ClipseZ Clipz +Clipz Ahoy CliveTrotter +Clix Cload +Clockwise Clod +Clogged King +Cloggin +Clogging Cloistered Clone +Clone bone ClosedLoop Closertohell Closeshots Closofy +Clotert ClottedCream Cloud +Cloud Cover +Cloud Els +Cloud Griega +Cloud Nine +Cloud Stairs +Cloud Surge +Cloud y +Cloud1K CloudSoftass CloudT +Cloudhill +Cloudi Boi Cloudjumper9 Clouds +Clouds_Song Cloudy +Cloudy Boi +Cloudy Sleep +Cloudy Wolf CloudyOcean Cloudys +Cloudystrife Clouted Clovie Clown +Clown Around Clown0164 +Clownfart7 +Clryy Clss CltRain ClubBruggeKV ClubWolf Clue +Clue More +Clue Relic +Clue box +Cluebringer +Clueful +CluelessKook +Cluer Clues +Clues Hunter +Clumpey Clumsy Clunker ClutchFlipsy Clutchy +Clyde Cooter ClydeBarrow Clynelish Clyps +Cmallz02 CmarBeast Cmndrcool222 +CmokinSrack Cmon +CmptrGmr +Cnbl +Cnhil +Cnr Cnwalker CoFlack +CoKMcGay +CoX Mentor +CoX ToB ToA CoXAcc Co_do_blyat +Coa Coach +Coach Trip +Coach Wright +CoachJal Coachsharter Coal +Coal ore Coan +Coat Throat +Cob Web Cobab Cobalt +CobaltKings CobbMorty +Cobba +Cobplacecow Cobra +CobraChickn Cobreu Cocajumba Coco +CocoGetsLoot +CocoaPuff +CocosLilSimp Codai Code +Code Mellow Codemax Coder00d Coderedcfc Coders Codfish808 Codi +Codonz Cody +Cody Smith +Cody The IM +Cody The M +CodyBeaumont +Codys Nuts Codyx Coeeyyy Coekebakker Coenzyme +Coex +Cofeni +Coffaholic +Coffe277 +Coffee Latte +Coffee Love +Coffee Robot Coffee94 CoffeeAndExp CoffeeBarrel CoffeeIsBest +CoffeeKitty +CoffeeMafia CoffeeQ888 CoffeeSlayer +Coffey +Coffin Cape +Cogelon +Coggle Cogstyle +Coheed Coherent Coilman Coin +CoinToss +Coinism Coipo CokeHogan CokeShoveler +Cokebro +CokedPepsi Col10 ColVolgin Cola +Cola Flesje +Colaboks +Colb y Cold +Cold Bowl +Cold Ham +Cold Hash +Cold Hemp +Cold War Cold1 ColdReign Coldhound591 Coldpiee +Coldraze +Coldrootbeer Coldshop Coldstream +Coldvayne Coldvepz +Coldwar +Coldwoods Cole10083 +ColeEleven ColeQuil +ColeVeryBakd +ColectionPog Colee +Colei Coleus Colgate777 Colienergia Colin Colins +Colivanov +Collan33 CollectMemes +CollectibIes CollectionIM Collectively +Collector of Collega +Collier Collierss +Colliflopter Collin892 CollioKey +Colom ColonColitis Colonel +Colonello ColonialDank Colonne +Color Climax ColorBlindHC ColorMeBlind +Coloradodo ColorfulE Colossus 5 Colossvs Colt +Colt trigger Coltan +Colthound +Coltn Coltrainz1 +Coltsfan1996 Columbot Columbus175 +ColumbusCrew +Colxman Colzy Coma Combaed +Combat Phase +CombatStudy Combatking13 Combibo Comboed Combos Come +Come Loads ComeAtMeBruh Comet Cometz +Comex Comfort Comfortably Comfy +Comfy Butt +Comfy hug Comic +Comic Books ComicalBust Comicmaster0 +ComingHome +Comiya Comlidor +Comm Zilyana +Command Grab +Commander Fh +Commander Ra Commas Commiefornia Common +Common Drop CommonGinger CommunistMoo CommunistPig CompactSugar Companiion Companion +Compd +Compe Compgeek Compilacion Complain @@ -4529,346 +9360,707 @@ CompleteAss CompleteSpud Completes Complex +ComplexTree +Complextro Composing +Composites Comptons Compy +Compyclon ComradSergey +Comrade Hanz +ComradeCas ComradeCovid +ComradeMule +ComradePugs +Con JD +Con Safos +Con ner ConKlave ConaAmadora +Conaizy +Conal +Conceited Concentrates Conchrist Concritus +Conductor4 Cone01 Conedinho +Confederacy Conficker Confidentiel Confined Conflamit +Conflate +Conflict Confuze +Congest Congetus +CongiestMunt Congra ConicLight Conjay +Conjo Conman Connavar +Connee Conner +Conner OK +Connerr Connerxx +Connor M +Connor xv +Connzy Conor +Conor J +Conor07 Conpetgrebe Conqo Conquar +Conquers Conquestions +Conquestti ConradK Consan Considerable Conskis +ConstantZero Constantnips Constellar +Constence Constricted Constructeur +Consumption Contaminate +Contant Geld Contendedd Conterfeit Contes +Contrabant +Contract M +Contradicted ControlAll +Controller Controlllers ControneX Contyy Conventicle +Converter Conway Conydriving +Conyon +Conzila +Conzine +Coob Lad Coogs Cooj Cook4everu Cookdaburra +Cooked Chook +Cooked Sinus Cookedvomit Cooki3Crumb CookiMan Cookie +Cookie Cake +Cookie O_o Cookie904 CookieKid00 +CookieSpec CookieV3 +Cookiers +Cookiezi Cool +Cool Raccoon +Cool Yak 496 +CoolAssName +CoolG WC +CoolNameBrah Coolair Coolavatar1 +Coolboy_cal Cooldesert2 +Coolest91 CoolestCow +Coolio +CoolmanCool Coolmanafo +Coolminer685 Coolmintoreo +Coolmonkey50 +Coolsniper Coolster Coolxkidz Coom Coomcoomber Coonrade Coopa +CoopaTroopah Cooper Cooperative +Coopr Coopsz +Coors Light +CoorsRight +Coorsy Coos +Cooter +Cooter Kick Cootie Coozn Copytopy Coquettish +CorCam Corabex +CoralCastlez CoralFire +CoralReef Corbi +Corbula CorbyTheLad +Cord Core OS Coree +Coreey +Coreling jr Corena Corey CoreyCarlaw CoreyNKH +Coreyeroc Corgi +Corgi Puppy +CorgisIron Corgo +Corinnna Corizz Corleone +Corley Corn +Corn x Holio Cornbuddy +Corndoq +CorneliusIII Cornflake Cornie Cornilius Cornish Cornwall94 Cornwalll +Corny10k Cornye +Corona +Corona Bat +Corona Case Coronad1 Corp -CorpToMax -Corpletics +Corp Scape Corp09RS +CorpLeecher +CorpRng +CorpSlapper +CorpToMax +Corping Bro +Corpletics +CorporalWolf +Correy Lahey +Correyyy CorruptDingo +Cors Corsa Corsetti Cortes +Cortex +Cortica Cortistatin +Cortsen +Corun +Corvanjer +Corvisquire Corvitolis +Corvo Corvoo Corvus +Corvus enca Corwin Corydonn Coryy Corzappy +Cos A Nostra Cosaintus Coseph Coshie Cosmic +Cosmic Booty +Cosmic Star +CosmicPebble +Cosmiclaws +Cosmog Costa +Costah +Costcutters +Costi CostlyOne Costom +Costs Cotched Cotopaxi Cotstini Cottee Cotton +Cottrell Cotty2Hotty +Couch Frame Couchie +Coughey +Count 2Three +Count Cranz +Count Dookie CountCuckula CountDrugula +Counterspell +Countries Country +Country Song Countwert Coupland Coures +CourtnyGears Couscous Cousin +Cousins Couzens90 +Cove Coventrians Coventry Covert +Covert Blade Covid +CovidFree Covvboyz +Cow Door Mat +Cow Foo +Cow Pet +Cow Tongue +Cow Wizard Cow395 CowChum +CowMr101 +CowSalsa +CowVein Cowa +Cowabungalow CowboyK1ller +CowboyKaroo +Cowdenbeath +Cowlories Cowrat +Cowsburp +Cowtongue CowzGoMoopy +Cox out boys +Coxed +CoyieGod +Coz +Cozmic_Raven Cozy Cozzza +Cpl Gaz +Cpl Seeder +Cpt Doobie +Cpt Fail +Cpt Kokopuff +Cpt Mellow +Cpt Mina +Cpt One Eye +Cpt Pepe +Cpt Pop Tart +Cpt Shanks +Cpt TRICKS +Cpt Unclutch +Cpt Wally CptAceRimmer CptKyle +CptRileyy CptRom CptSankara CptSmackAHo +CptUzu Cptainseveto Cptn +Cptn Jack +Cptn Murica +CptnBuckaroo +Cpunek +Cqrl +Cr o Cr0be Cr0codile Cr0z Cr4zyLuck +CrAzY HoRnEt Crab +Crab Emoji +Crab Jazlo +Crab Leaker Crabalt Crabby Crabcore Crader Craft +Craft Brew +Craft Guild +CraftPure +Crafter Jr Craftes Craftsmen Crafty +Crafty Man CraftyRunes +Cragyl Craig +Craig Dawson +Craighead18 +Craizy 8 Craizy9 +Crakced +Crammerr +CranadosX Cranberry Crangus Crank Cranke Cranky +Cranky Cows +CrankyScream +Crantock Crapicorn +Crapping +Crappy Luck CrappyScape Craqers Crash +Crash Crann +Crash Cymbal +Crash Site Crashbot Crashendo +Crashticles +Crateapa +Crateaqa +Cratzi Duhuh Crave +Crave Me +Crave to Max +Craw +Crawfish Crawl2033 Crawn +CrawsBow CrawsMain CrayQuaza Crayons +Crayy Crayzee +Craze NL +Crazed Man CrazedAfro CrazedAgain +Crazedmonkee +CraziKido Crazie Crazy +Crazy 859 +Crazy Canada +Crazy Sam +Crazy Skull +Crazy5115 CrazyDieMan +CrazyDryMan CrazyDutchy CrazyIron85 CrazyShrimp CrazyStuff Crazya0 +Crazyb00b Crazyhalo +Crazys Crazystevee Crazytree Crazzy +Crazzy Ivan +Crcsh CreaMiJeans Cream +Cream City +Cream Guzzle +Cream21 CreamFreesh CreamingPies Creamp +Creamy Fella +Creamy Whole +Creasential +Creat Steal Create CreateNoPain +Created +Creating6 Creator1212 Creator409 CreatorJR +Creaturree Creazy7 +Crecker Fux Crecket Credibility +Credito Creel Creenen Creepy Creezy CreightonRS +Crem Fraiche Cremator Crenoc Crescent +Cressp Cresss +Creston fftp Crevis6 CrewDoe Crewcial Crickets +Crickss Crier Crimewave Crimeway1991 Crimin +Criminaldmge +Criminalised Crimp Crimson CrimsonCow CrimsonDDS +CrimsonJayce CrimsonLily CrimsonRogu3 +CrimsonScape +CrimsonTide CrimsonU +CrimsonWic Crimsoncaim +Crimz0n Crinath +Cringy Grump +Cringy af +CrinsomX +Cripler Cripple Crippled +CrippledKev Crippler +Cripty Cris Crisby Crispiessss Crispy Crispy Bac0n +Crispy I CrispyBreast Crissco515 CristalAlken +Cristierra CriticalX +Criticizer +Critter J Crittx Crixos +Crixus x Criyosphinx Crna +Crna Gora CrnerMcGregr +Croc +CrocDanDee 1 Crocalu +Crocketeere +CrocoMaster Cromeh +Croney +Cronsus Cronus Cronz +Croogus +Crooked Path Crooklyn +Crooshtwoost +Crosby Alt +Crosem Cross +Cross Me Crosswinds Crouchling +Croupz Crow +Crow Mn CrowBox Crown +CrownConvict +CrownRoyal84 Crownescent Crowride1873 +Crowther Croww +Croxy Crozier CrspyPigeon Crudelismo Crudivore +Crue Xena Cruel Cub +Cruel Irony CruelVictory +Cruelcanary Cruixiote +Crumbledoor Crumblers +Crumbways +Crunch7O4 +Crus ty CrusH-HK +CrusadeKlr +Crusadershot +Crush Depth Crushed +Crushed Guam +Crusher9783 +CrusherWake Crushersun Crushertaco +Crushs noob +Crust Cape +Crustie +CrustyDuckr CrustyPusy Crustysnot Crux +Crux da King Crux25 Cruxyy Cruzty +Cruzzetbuzz +Crwfrd Crxk Crxsty +Cry +Cry0nman Cry4help +CryIs0gp +CrySupply Cryge +Crygechamp Crying +Crying Cutie +CrykeeOwO Crynceps Cryo +Cryo Chamber +Cryogen Cryogenica +Cryogenica 2 +Cryogenist +Cryorah Crypthead +CrypticSlays +Cryptling Crypto CryptoKitty CryptoMellow +Cryptonomico Crypzor +Crysaki +Crysh Crystal Crystian +Crzy Mia +Crzyarab +Csajka +Csk x +Cssy CtCandyRandy +Ctclaire999 +Cteel Ctep31 +Cth ulhu Cthrek Ctrengereid Ctrl +Ctrl F +CtrlAltDel x Cuada +Cuat3 Cuatche +Cuattr0 +Cub Will +Cuba Sybre Cubans +Cubed +Cubet +CuckChuck +CuckW +Cuckgex +Cucumbers CudddlyBear +Cujoh +Culemborg +Culinair Culls +Culltist +Cultured +Cultzy +CumHeretic43 +CumanderZili +Cummy Sigil +Cumpaska +Cunnavathing Cunny +Cuno Cuolua +Cuong +Cup Noodle +Cup Of Chai +Cupaplayer Cupcakess Cuppalimmy +Cuppi Cups Cupthebooty +Curaga +Curble +CurdTuttrboi +CuriPolymath Curll +Curls +Curlx Curly CurlyTwist Currancy Curry Storm +Curryleaf Curse +Curse on me Cursed +Cursed Chump +Cursed Nm +Cursed Side +Cursed ll +CursedOwned +CursedRNG oO Cursedpotato Curt +Curtis Jones Curve CurvedHorn CurvyChcken @@ -4876,32 +10068,64 @@ Curzonn Cushco Cushdy Custom +Custom Jr +Custom Sock +Custom TK CustomGFX Cute +Cute Cat lol +Cute Paunch +Cute n o o b CuteClit Cutegirluwu Cuti +Cuties +Cuttableedge +Cutting edge +Cuttl +Cuttle +Cutty Sarks Cuuap Cuult +Cuz im Jones +Cuz im jesus +Cuztom Cuzzo94 +Cuzzu +Cvanz Cvbgn Cvrkster Cvrsn Cw90 Cwab +Cwazza Cweavy Cwer Cwick Cwioktopus Cxffee +Cxld +Cxnnor CyaCyaCyaCya Cyal8rnub Cyan +Cyan Ablaze +Cyasoon +Cybb +Cyber Mind +Cyber n Bug +Cyber172 +CyberJesus CyberSlave18 Cybernautron Cybernike +Cyberpope +Cyborg Musk CyborgHex +Cybron Cycling +Cycling Road +Cyclogy Cyclone2498 Cycloner5 Cyclopedia @@ -4911,227 +10135,534 @@ Cygni CykPyk CykaNuggetzz Cyldan +Cym Cymatics +Cymbaline +CymricCat Cyn2k CynAcolyte Cyncess Cynda +Cyndaquiill +Cyndee +Cyndrakial Cynhi Cynic CynicalSilas Cynocephali +Cynognathus Cynosure +Cynox Cynthaen +Cyodot Cyous Cyox Cypersilver +Cypher Blue Cypress +Cypress H1ll Cyralx Cyrax Cyrax314 Cyriel +Cyrodiil22 Cyroenix Cyruscomrad +Cytain +Cytryn7 Cyuh +Cyum Czacha Czar +Czar I +Czar Trump +Czechmate +Czha Czivend123 +Czk +D A I J I N +D A L M +D A M 0 +D A M I A N D A M N L0L +D A N G I T +D A N N Yy +D A T H I T +D B A +D B Z pker +D Blo +D Clawz +D Darkblader D Derbles +D Dragon124 +D Duberstein +D E C O +D E F Q 0 N D E F Q O N +D E R P +D E V I N +D F U Q +D I Q +D I R T Y Ko +D J Diddles +D Long +D M T Elves +D O D +D O M M E L +D R 6 K E +D R l Z Z T +D Rack4 +D S A V +D Squarius +D U R K +D Wilson +D Wreck +D a mo +D a r t s +D a rk +D a u t o +D a v i d +D amz +D arking +D arkoz +D as +D ashing +D avey +D axe +D db +D ebol +D ecimate +D eej +D eek +D eep +D eez +D en +D enial +D entist +D i l a n +D i x o n +D i zz y +D iesel +D iizzy +D imi +D imitri +D onda +D onger +D oo l ey +D op e +D utchgr +D-D-A D00DLES +D00dey9 D0CTOR D0GS0NG D0NE0 D0NPABLO D0PESIC D0any +D0inkleberg +D0lNK +D0llynho +D0n vi0lad0r D0nte +D1APAM D1GG00BIITTI +D1P D1ZZY +D1ngu5555 D1no D24L D2Aina D2nzo +D2theOnTRUMP +D3 Washup D33L1N D3ATHBYPI3 +D3ATHVENG +D3C D3C0D3D D3DW8 +D3IVY OSRS +D3VONSHIRE +D3ZZi5 D3ceptions +D3precated D3thbyzebra D3v1lBoy D3vilmar3 D3zert D4H4EK3YSM +D4TE D4VO D4n0118 +D4ng3r Suca D4nkmemel0rd D4nnyy +D4rels D4rk D4rth D7NNY +D9 +D9R +DA ODB KIDZ +DA0IST +DA3N33RY DA4N +DAD563884271 +DADDYS IR0N +DAHDB +DARCHANG3L +DARGON DASH DAWGPOUND +DArtspret +DBA Paulo DBKangaroo +DBO90 +DBOL TRICEPS +DBUZZ +DC Flubber +DC-8-51 DCreek +DD 214 +DD G DD2I4 +DDAlt +DDSurWrists DDandy +DDoS Wildy +DDune DEFENDPOPPNK DEFlNE +DEM0L DEM0NIC +DEPRINS +DESPA SIITTO +DESPAlRGE DESTYLAT DFez +DG 00 DGAF +DH Marker +DH btw +DHIBZ DHSC4EVER +DHally +DHlN +DHoShow DIDZZ DIETDRDIET +DINGO SCUM +DIORITIC +DIORITlC DIRTYags DISAPRIN DITMANM0DE DIVINExNOVA DIY Ele +DIY Jamie +DIY Salsa +DIY Shane +DIY Steo DIYIronFeBTW DIYRevelled +DJ Bop +DJ Cranston +DJ Heiko +DJ Korsakoff +DJ Llama +DJ Pen is +DJEDDIK +DJK Daniel +DJKALLE ANKA DJKrampz DJMileyCyrus DJMuscleBram DJOFULLIN +DJSeinfeld +DKHo +DKJN +DMM 2 07 +DMM Gp Swap +DMM Ryu +DMT Dad +DMT Satan DMTDAN +DMTe +DMagnum 10 +DMessengerS +DN Atro DN20 +DNFL DNLD +DO0FY DOGELII DOITESTEVEN +DON FIJI +DON VALTEE +DONG GOLEM +DONJOHNNNY DOOMBRlNGER DOOMSlayer DOSNE DP776 +DPRNS +DPS Disciple DPvM +DPvM Jordan +DQ9 +DR PAAAK +DR VABA DRAEG0 DRANG3 DRD31 +DRFL DRGNSLAYER85 +DRIEST RNG DRL0NGD0NG +DRLGspace +DRNKN DWARF DROPPEDITALL DRTY +DRUNKIDIOT +DReelest DRegi +DS Stolen +DSHeavy +DStat DStroud DSyndrome +DT5 DUMB DUSKBLADEL0L +DV 8 DV trekpik +DVa +DW Gunthie DW24 DWlGHT DXQIWOL +DXXM DYao +DZ o_o +Da Bomb 149 +Da Buddah +Da Iron Jedi +Da Man 65 +Da Nils +Da Puppy13 +Da Sniper007 +Da T Virus +Da d dy +Da t +Da then bh +Da1ton DaBears DaBoz +DaBurg DaCatBeam DaCigarMan +DaCuddy +DaCult +DaDangus DaDude DaFatManDan +DaFeesh DaHumanClown +DaIronBooty DaIton DaJaVu DaLegendary +DaPootz DaRKi +DaSernet DaSheepFtClb DaTr3w +DaVinciss DaaChronic Daaak Daallas Daan +Daanilio Daanncorr +Daavos +Dab Thirty +Dab then pvm +Dab0mba DabANOMICS1 +DabDabDan DabInMyEye +DabTornado Dab_nScape Dabbadank +Dabbe +Dabbers +Dabbie Duck +Dabbin Dolo DabbinDonut +DabbingBrb Dabe +Dabe Sucks Dabei +Dabomb 13 Daborn92 +Dabos Weenie DabsWithDan Dabsmoke Dabsncats Dabsndogs Dabton +Dabvape420 +Dacaedia +Dacc +Dachowski Dackel Dackenerino Dacune +Dad Goals +Dad Sean +DadBurrys +DadGoingMad DadLeft DadRanarrWay DadamoSte +Dadbackward Dadbackwards +Dadbod4lyfe Daddaforce Daddy +Daddy Bundy +Daddy Chaman +Daddy Chubs +Daddy Danger +Daddy Dead +Daddy Drow +Daddy Oreo +Daddy Smit +Daddy Spoon +Daddy Yurdle +Daddy sandro +DaddyDeagz DaddyDylo DaddyLemming DaddyMac DaddyMars +DaddyNemmy +DaddyPig406 +DaddyTowel +Daddyfied Daddyplease DaddysLoad Daddyspie DaddyyDong Daddyz +Daddyz Clean Dadevil1616 +Dadfield Dadi415 +Dadorii Dadosaur Dads +Dadukez DadurQa +Dadyankee3 DaemonGunner DaemonTool Daemonmage +Daemonrds Daenrys Daep Daewolo +Daeyalt Ess +Daeye +Daez 95 +Daf Arch +Dafetsch Dafney Dafo322 +Daft Punked DaftDemon DaftPun Daftmoul DafttPunk +Dafuggg Dafy +Dag DaLooter +Dagannot hs Dagannuts +Daganoth Rex +Dagathar1 +Dagburn DaggaNOTKlNG Dagger93 +Dagggg +Daggou Daggz Dagin DagkingV2 +Dagnel Daddi Dago +DagobertTT +Dagoth Vemyn Dagsi27 +Daguar Dahlareen Dahls +Dahlson Dahmonkey Dahrmata +Dahrr Dahumbug Daijoukay +Daiju Spede Daiktusrenku Daileee Dailiana +Daily Grind +DailyDoomer DailyDosage +DailyPog DailyScape99 DailySharts +DailyShelfer Dailytoker Dain +Dainius Dains +Daipers Dairychuk DaisOfHavoc Daiseido Daiski +DaisukeJigen +DaisyApple DaivdFW +Daiw +Dajmkryss Daka +Daka Alt +Dakai +Dakay Daklozenkrat Dakotas Daksu Dal3y +Dalacks DalaiLlama +Dalanes +Dale Dobec +Dale G +Dale HC BTW +Dale Winton Dale1612 Daleferd Dalejamesw Dalek +Dalek Cookie Daley_Dose Dali176 Dalkz +Dalls Beep Dalmatian Daloomi Dalrak @@ -5139,6 +10670,7 @@ Dalski Daltficiency Dalton Dalton4theft +Dalton_LB Daltonnn Dalundo Dalzii @@ -5146,60 +10678,134 @@ DamDude DamSplash Damage Damarquis +Damberson +Damen +Dameon xd +Dami +Dami-an Damiaen +Damian_Xx Damish Damlotz DammitHarry +Damn Evil +Damn God +Damn its Sam DamnItHarlod +DamnSexy +DamnViton Damned +DamnedDaniel Damngoodsoup +Damni t Damo +Damo is free Damon +Damp Memes DampBucket DampForklift +DampMongot94 +Dampener Damzos +Dan Bad +Dan Craig +Dan Daoud +Dan Gleesac +Dan H +Dan M +Dan S +Dan xo Dan-Reijden Dan120201 +Dan452 +Dan646464 +Dan91 +DanAsker DanAye DanBTW +DanChan1101 +DanGreenFan DanGur27 DanMaxd DanMingo +DanO_o +DanOfCumelot +DanPJ DanRickshaw DanTheM4N +DanTofoo Danboy Dance +Dance for XP +Danced DancingForGP +DancingRa1n +Danco +Dandrikis +Dandwc88 +DaneDaddy99s Danea +Danelele DanernesLys Danex85 Dang +Dang It +DangFloopity +Dangelboi +Danger Swign +Danger Zoneh DangerBear DangerGlutes +Dangerouz Dangeruss +Dangerxi +Dangerz0ne15 DangitBobby Dani +Dani Cute +Dani D +Dani Dark 0p Dani007 Dania Danieelius Daniel +Daniel Mcc44 +Daniel OSRS Daniel12xx +DanielSumtin +Danielbisgod Daniella +DanielleOfc +Danielmcken1 Daniels +Danielwat +Daniiieell Danijenn1211 Danilin Danimal DanisH96 +DanishAdonis +DanishGoat Danje Dank +Dank Chef +Dank Exp +Dank Perp Dank Tigzy DankDylShpil +DankMagic +DankSavage99 +Dank_Mcnasty Dankdank96 Dankdog Dankdynasty +Dankey Dankfool +Dankleburgh Dankstanky Danktrees +DankumZ +Danky Kwuarm Danletics Danleypa Danlord3222 @@ -5214,32 +10820,51 @@ Dannk Dannny Dannum Danny +Danny Dubs +Danny Dvito +Danny Mate +Danny P +Danny Pudi +Danny m8 +Danny wtf DannyDeleto6 DannyK +DannyKjr DannyPho +Dannygem Dannytrol +Dannyw Danog Danoj Danol Danomeva +Danoontje Danozz +Danratty Danrow Danrue Dans Dansayeagle +Danski261 +DanteExitium Danxdoo1 DanykaNadeau Danzai Danzig Danzoler Daofather +Daoko X Dapper +Dapper Hades +Dapper Jr +Dappest Dappi DaquanNiguan Daquantaro Daquicker Darbinism Darc +Darc Sport Darcy Darda09 Daredevil595 @@ -5247,128 +10872,294 @@ Dareme95 Daremo Dareya2 DarfPlageus +DarfWantWarp +Darimy Dario +Dario hax +Darion Dariukas Dark +Dark X +Dark Alcyte +Dark Aloy +Dark Curtain +Dark Iron69 +Dark Jaxol +Dark Kadabra +Dark Kill L +Dark Knig ht +Dark Kurama +Dark Peter10 +Dark Rabbit +Dark Ranqe +Dark Side +Dark Specter +Dark Stone66 +Dark Tetrad +Dark Totem +Dark Uzi +Dark Veidar +Dark Wegener +Dark Xarpus +Dark kamui +Dark lll +Dark1437 +DarkAether DarkEater +DarkElf135 DarkEmerald DarkGraceful +DarkHoodGIM +DarkKn1ghts DarkMerliin DarkNut393 DarkOwI DarkReapingX DarkReign DarkWizard +DarkXiphles9 +DarkZulu97 Dark_Auth Darkang3lpkx Darkao Darkarmy40 +Darkbox777 Darkbright +Darke Hand Darkemissery +Darken Devil DarkenRahlrs Darker +Darkest Kind +Darkest Syde Darkfanime Darkflash15 +Darkgutz Darkhal +Darkine Darklord4211 Darknapster Darkp0wnz Darkphil007 Darkpupitar2 +Darkrai Darkraven368 +Darkscorpio5 Darkseance Darksense Darksim10 Darkskiller Darksn0w Darksnoweb +Darksocks1 Darkst4ar +Darkstar078 Darkturbo Darktyranno Darkwrath43 +Darkyr +Darlin g +Darling27 +Darma +Darnic Darquain Darras +Darren T Darrens Darriann Darse Darsehole +Dart Slayer Darth +Darth Kas +Darth Shiroo +Darth Spade +Darth Val DarthNevidia DarthSpliffs +DarthWrecker Darthe Darthodium Darthonion90 Darthrodger +Darthruneis Darthshea Darucell Darush Daryl Darz Darzix +Darzo5 +Das Idle +Das It Maine DasGoose DasReich88 +Daschiva +Dascrez Dasgirl09 +Daspwn +Dasrx RNG +Daszler +Dat Geezer Dat2eWoord +DatBoiNibbe DatBoyLoy DatGuySteve +DatIronNinja DatNeck +DatPeko DatYeet Data +Data Diddler +Data Privacy +DataDruid +Datadyne Datames Datcookie34 Date Dathx Datis +Datoxicate Dats Datskai +Datting +Dattos +Datuk +DaturaTrip Daubs +Daud +Daughters +Daunt Dauntless +DauntlessXav +Dauth Elda +DavSko Davaflav Davai +Davantage Dave +Dave From Au +Dave Hooray +Dave J +Dave Mario +Dave Senpai +Dave The Egg +DaveAckery DaveDaBeast +DaveDorvis DaveLister DaveYognaut Davebarbaren Davedication Davedude +Davej86 Daveken +Davesty +DaveyB0nes DaveyWSM David +David Co +David Duffs +David Ortiz +David R333 +David007 David2699 +David4755 +DavidKinaMan DavidPH Davidisiscoo Davidopathy +Davis751 Davlan Davo Davord +Davoron +Davros70 Davshing +Davu +Dawaj Lama +Dawg Dynasty +Dawkins Dawn +Dawn Destiny +Dawn Era +Dawn Summers +Dawn Wall +DawnEverbane +DawnSwanMon Dawna DawnfaIl Dawson141 Dawtrix +Daxidol Daxon +Daxx95 Daxxzy +Day Dreams Day Lightz +Day1ofNoFap Day6 DayJarVu DayOff2JOff +DayStar Turk +Daydrifta +Daye Xero Daykillz +Dayman_GIM Daymien +Daynnn +Daysi Darcey +Daystar +Daytrip +Dayuf +Dayveeeee +Dayz of Iron +Dayzd1 Daz3dnBlaz3d +Daze +DazedDave DazednConfsd +Dazzler95 Dazzz Dbeatz +Dbewt Dbmx +Dboot Dbricke +Dbz Pride +Dc B L I N D +Dc Hakkarn +Dc IronMan +Dcaravan Dced +Dced at Corp Dception +Dcing Dday6Jun1944 +Ddestroyer56 Ddos Dds4theko Ddsing +Ddsme +De Algerijn +De Baardman +De Eryngy +De Fishy Guy +De Gennaro +De Hoppert +De Jam +De Krikke +De La Trey +De Marco +De Max +De Mechelaar +De Pette 69 +De Redacteur +De Sam Matie +De monic De stoutsten +De us +De1icioso DeAndre DeDawgTubb DeEgis @@ -5387,38 +11178,80 @@ DeTrixzz De_lemme10 DeaTH Deacey +DeaconDrew Dead +Dead Baldy +Dead Bozo +Dead Chilli +Dead Easy +Dead HC Here +Dead Her0 +Dead I Guess +Dead Mum +Dead Policaj +Dead Psyc +Dead Sellout +Dead Ticks +Dead XVIII DeadDogRed +DeadGhost DeadKelly +DeadNowM9 DeadPickle DeadPower DeadPuto DeadRealSoon +DeadSanson DeadSlice +DeadSmog3 DeadWife Deadarrow99 Deadbeater +Deadblinx Deadened +Deadfallen Deadlft +Deadlift Deadliftjr Deadly +Deadly Pixel +DeadlyAnt DeadlyBatz DeadlyDJ +DeadlyDrinkr DeadlyHit DeadlyNecros +Deadman AF Deadness Deadpaal +Deadrango +Deadwool DeadxProof Deaf +Deaf Person +Deaf RScaper +Deafmau5 Deafs +Deakien Deakz +Deal or nah Dealing Dean +Dean Jac DeanRs Deandelouest Deantotheo +Deaptic Dear +Dear Deer +Dear no one Death +Death Devil +Death Eaters +Death Is Fun +Death Loco +Death Qweef +Death Rainer Death0fyou DeathByRC DeathPanda @@ -5427,133 +11260,224 @@ DeathSurgenc Deathbyclick Deathcloude Deathcore +Deathduspart Deathfuzz13 Deathhope666 +Deathism Deathit55 +Deathmast333 +Deathomen Deathrattle +DeathsCaII DeathsCoffer Deathscyt56 +Deathstarlol Deatths +Deb0wer Debauchery Debb Debdu +Debil Missed +Debiruss Deborla Debug Debwani Deca +Decapacitate +Decard Cain +Decarium Decath DecayedWrath Decca +Dece1ve Deceive +Decent Drugs Decerate Dechmann Decides Decim +Decim-san Decimate +Decius Maxim +Deckiez +Deckler Declare Declined +Deco Himself Decolonize Decomposed +Decon Decs +Dectron1 +Ded Ronald +Ded Smithy DedClicks DedVittu DedWilson DedZap DedZeppelin7 +Deddo92 Dedfin +Dedge Inside +Dediabl0 Dedicated +Dedicated XP Dedmoo Dedressing DedsetLegend Dedville Dedzone +Dee DeeLizard DeeLuxe DeeZe +Deedeedee630 Deedlebees Deeego DeeezNats Deejay +Deeku vaan DeelDoughs Deemush Deep +Deep Medi DeepInUrMum +Deepika P +Deepinuh Deepnsider Deerboy7I7 Deerhunt03 +Deerkl Deerski Deerskin18 Deevos Deeyja +Deez Mangoes +Deezima Deeztroyer Deezy44D Defaultbomb +Defaulted +Defeat Evil Defeater Defektas Defelorn Defence42 Defensief +Deffi +Defib +Define Pain Deflexus Defloat +Deflorator +DefoNotKiwi DefoNotSpoon Defog Deformedhell +Defqonlord Defrosted Deft Deftones Defund +Defunto2 +Defy Limit +Defyinq +Degak +Deganti Upe Degas +Degen Darra +Degen Ryu +DegenGod DegenRetard Degeneraatio +Degenic Neet +Degenomics Degradedd Deguns DeiAx Deidera Deifi Deimoss +Deinsmeins +Deiron Tyson Deitonus Deive +Deiviiz +Deivis +Dejagoo +Dekeyser +Dekkens Deko Dekul +Dekylex Del1nquent Del4no +DelaIron +Delaey Delay Delciotto Deldeen Dele +Deleted +DeleuzeSucks Deleven +Delga +Delger +Delhaize +DeliMeats Delic +Delicoffee Delimain +Delirah +Deliyria +Delkku2 Dell +Dell De Dul +DellaRS Dellamor Dellies +Delmar Delmaro Delonius Delphan09 Delskiii Delsym Delta +Delta 516 DeltaCloud DeltaEpsilon DeltaPapa Deltaskull +Deltawye Delten Delusional Delusionnn +Deluthul Deluvial +Deluxe5 +Delvex DemSkillsDoe Demander Demboo Demco Demerlay +Demetre130 Demi DemiGodKempo +DemigodI Demising +Demmegod Demolidor Demon +Demon Albarn +Demon Flare Demon Plate +Demon RS Demon1793 +DemonWolf1 +Demon_Matrix Demonaly +Demonas Demonboys1 Demoni Demonic @@ -5562,14 +11486,31 @@ Demonleader8 Demonslay335 Demonteats Demoted +Dempa Dempeanut +DempseyRoll +Dempsters Dempsu +Demyze +Den Bever +Den Duivel +Den Illya Den1z +DenZelouZ +Denaelc +Dench Bee Denclosure Denferok +Denfoe +Denggly Denglish +Denis Denix6 Denizenn +Denkil +Denkue +Denmarkian +Dennaro Denneny Dennis DennisWilbur @@ -5577,9 +11518,12 @@ Dennisfr Dennispanda1 Denny Dennyispro +Denonweff DenouncedGod Denoxite +DenseLayer Denssoni +Densu DentalMental Dented Dentistry @@ -5587,50 +11531,88 @@ Dently DenverHockey Deny Deny92345 +Denza93 Deon Deoo +Deoxy_19 Deoxys39 Depdada007 +DependaAF Depends +Depenenkal +Depletion Deplox +Deprimes Deprimir +Depster DepthStryder +Deputy Mibo DeputyDwigt +Der Hungrige +Der Panda DerPunkt31 Derbados DerbyDerbs Derdel DerekBarnett DerekEmKay +DerekWins Derenity Derick +Derived Hope +Derk Danger +Derkalurka +Derkila +Derkle Dermijiny +Dern Swan Derot +Deroy DerpCanin +DerpDeezy Derpmoil Derptimusbro DerpyClayDog Derrick +Derrick Rose +DerrickC145 Derrik Derrin +Dertay Des0rg +Desaus +Descendence +Desconectado +Desear Desert +DesertAmulet DesertEagle +DesertFlower Deserve Desi Desigium Desinger +Desinteresse Desire Desk Desley +Desn1q Desoroth Desper Desperados +Despitous Despot Dest +Destab Destinneh +Destiny Goat Destr0i +DestroyButts +Destructoid Desuelle +Desuhmate +Det BabyLegs +DetRedWings Detain Detects Detectum @@ -5639,219 +11621,416 @@ Detonati Detone Detriment Detrimental +DetroitSux Deugeniet Deunek +Deur NL Deurloos Deus +Deus Esq +Deus leto +Deus lux est DeusFerox DeusXQuinoa Deuxth +Dev Jacob +DevMoney420 +Devanar Devb0t Develinside9 +Develique +Devidedby0 +Devika Devil +Devil Horns +Devil lnside Devil9394 DevilOfheavn Devildog Devilege Devilgod +Devilish Deviljin583 Devilman Devils Devilsbkb0ne +Devilsjoker DevinTheDude Devinchi Devious +Devise Devizer Devo +Devon Btw +Devoted I Devotion Devoured Devourkitty +Devry Cain Devstated +Devv N +Devvy UwU Dewa +Dewarping Dewiro Dewitten420 Dewk Dewrunk Dewsk1 +Dewts Deww +Dex Territy Dexby Dexderp Dexlan Dexter +Dexter Lou Dexterity Dexxaz +Dexxtrouss +Dexy Fiend +DexyDean +Deykota Deyou Deyron Deysean +Deyvyejones Dezerthuntar Dezi-VII Dezkor2 +Dezmezz Deztroyer +Deztroyer 0 +Dezzu +Dflow023 +Dfs Sfs +Dfuks +Dfw Dgalaga Dgref DhRecka Dhae +Dhaegar57 Dhaeqriyil +Dhaggz +Dhalsim +Dharek +Dharma Van Dharoc Dharok +Dharok 0bama +Dharok Derek +DharokHardOn Dharokbomber +Dharoker +Dharokz Dhavy +Dhides +DhingusKhan Dhon +Dhon Do Dhor +Dhr Leon +Di vau vand DiaRelent DiaThresh +Diabalo DiabeticKid DiabeticPhuk +Diabetucus Diablo Diablo47741 Diablosis DiabolicDead Diade Diagnosis +Diagonlane +Diah Diako +Diako Gyan Dialga +Diam0nd01 +Diamega Diamond +Diamond D +Diamond Jozu Diamond2192 DiamondScott Diamondback Diamonds +Diamonds Jr Diamonds lit Diamoniakmep Diampromidi +Dianakins DianasaurEgg Diane Diapeetikko +Diaper Dan Diaresta Diariez Diarrhea +Diarrhea Tom Diart DiaryNoob +Dibbo Dibbu Dibidos Dibidus Dibsis +Dibsis CoMa DibtheLegend +Dibudabudi +Dibyel DiccEat +DicedBrotito +Dicer +Dicey ReRoll Dicio +Dick Jones +DickNBallin +Dickbruiser +Dickeroo +Dicko Diclo Force Dicnar +Dicso DictatorNL +Did You Fart +Did You Try DidAnalOnce DidISayWeast DidNotDieBtw DidUJustBgs +Didavoo +Diddle Drip Diddlybopp Diddmeister Didi Didnt +DidntAsk Didny +Didsome1say +Die hard 66 DieAntwoord +Dieby Died4Hides DiedRank DiedSierra +Diedrrr027 +Diegoide +Dien0 Dieno Diesel +Diesel Bill DieselPump +Diet Andy +DietSquid Dietch Dieu +Diffindo +Diffy +Dig Bick 420 DigBicker +DigDaniel DigOlBick Digestive Digger Diggernick32 Digghass +Diggy Digi1al DigiDestined DigiFlisp Digifreak045 Digironimo +Digit28 Digital +Digital Age +Digital day DigitalGamer DigitalKillz +Diglett Dave +Dignace Dignity +Digtalcarrot +Digweed Digyeety Dihl DiiK Diiferent DiiirtyDog +Diisphoria Dija +Dikk Mabbutt +Dikkaz Dikke +Dikke Hobbit +Dikke Kei Dikken +Dikuufd +Dil Pickle +Dilbo +DildoBagguns +Dilexro +Dilfslayer Dill0n +Dillaz Dillbert +DilleFlute Dillhen +Dillon DillontheFox +Dillusion94 Dilly Dillywacka Dillzpickl +Dilogos +Dilph Diluzion +Dilvy +Dilx +DimDimz DimJangle +DimKills Dimaa +Dimathys Dime +Dime Daddy +Dime Skate +Dimebag217 +DimitriosMVP Dimmu +Dimmy Dimples +Dimwits +DinFulaJavel +Dinamite +Dinari Dindu DinduNuffen Diner Ding-A-Ling2 +DingDong DingDongDell +Dingbat Rat Dinger30 +Dingle Eater Dingus +Dinh Dinho1 +Dinieras +DinkeLBerrG1 Dinkerwoltz +Dinkis DinkleBrrgh +Dinkleberg DinoBoy7 DinoSnore +Dinomite Dinoparrot91 +Dinorock +Dinosaur Dinostrong +DioBrandoXx Dioden +Diogaite Diogo Diogun +Dioor DiorTemplar +DiorTheGreat Dios +Dios world +Diosdado_12 Dioxins Dioxis6 Dipdadronan +Dipical Dipli Dipolio DippaDave Dippoldism +Dippy +DippyMcshit +Dipshit Dan Dipyo +Diq-In-A-Box +DirectDesire DirectDsLcul Direwolf Dirk +Dirk Stryker +DirkDigglr Dirkieflurky Dirol Dirt +Dirt Shark DirtAss +Dirtbag Dirtbikerpro Dirtboy345 Dirtjogger Dirty +Dirty Dozen +Dirty Nuts +Dirty Nwah +Dirty Pack +Dirty Tampon +Dirty Wit +Dirty Wookie +DirtyDoc DirtyGeUsers +DirtyGlock DirtyKo DirtyLube +DirtyOldMan +DirtyShire +DirtySouthNz +DirtySpade +DirtyWata +DirtyyIron Dirun +Disabled Disaster0 Disasterolgy +Disastro +Disbeliefs +Disc +Disc Chucker DiscGG +Disclosing +Disclosure Disco +Disco Mayhem +Disco PvM DiscoDarwin DiscoFever DiscoLars DiscoTronix +Discoburger Discodoris Disconnecct +Disconootje Discord Discordian +Discounted Discoveredx +Discretions Disentombed +Disfunctie Disgusting Diskmedel +Disloyal Disneyland +Disodrer +Disorderly Disperse Disprivilag +DissTeam Dissidence +DissyReborn +Distained Distanc3 Distard DistinctEvil @@ -5860,219 +12039,482 @@ Distroyer972 Disturbed Ditherman Ditt +Ditt o Ditto Ditty +DitzyGranny +Dive Ball DiveMedic Divertus +DividedSky +Dividends Divin3RS Divine +Divine Dream +Divine Fenix +Divine Furby +Divine Mass +Divine One +Divine Oodle +Divine Sveta +Divine Zaros +DivineLegend +DivineRhythm +DivineShine +Divinenro Divines +Divinethug Divinez Diving +Divinitii068 Divoky +Divorce +Divxd Dixed Dixie +Dixie Pixies +Dixin Yass +Dixon +Dixon Planks Dixxy +Dixy Wrecked +Diy Dan Diz_OG Dizho Dizk Dizstruxshon Dizza Dizzleslayer +DizzyDan +DizzyPanda DizzyRnG Dizzzzy +Dj Dimu +Dj Jordi +Dj Ju +DjNateP DjSpicyNuts DjWalkzz +Djacquays94 +Djagzar Djahat +Djauw +Djavul +Djbeejay99 DjenCraw DjentleSoul Djl0077 +Djmx1000 +Djoefer Djozztico +Djscoobsta_X Djunya +Djurfan +DjustinT DkPepper Dkafeine Dkzz DlAMONDS +DlBz +DlCKE DlCTATOR DlDS +DlE MACHlNE DlNNER DlONNE DlPLO DlRECT +DlSCONNECTED DlTTO +DlXON Dlghorner DliveMarc Dlorean +Dm8 +DmVinny Dmage Dmante Dmfs +Dmgp Dmhc Dmi11z +Dmitri333 +DmkFight DmkKilla Dmoe +Dmt Kitty +Dn Dayander +Dn Havoc +DnB Fanatic +Dnc +Dnv +Do It Best +Do It Myself +Do You Zerk +Do ur Best DoDArmy +DoHerbRuns DoKZx +DoMeDirty035 DoMeHardNan DoSoQi +DoUEvenTank +DoWerkSonn Doadles Doajiggi +Dob Au Dobar +Dobby Hanzo DobbyGotPwnd +DobbyTheSock Doboner Dobster +Doc Doc +Doc Heart +Doc k i n g +DocDingle DocGiggles +DocMonocle DocVamp +DocYouSign Doc_Hershey +Docere Docs Docta +Docta Mantis +Docta dean +Docter Brule Doctor +Doctor Ace +Doctor Bubca +Doctor Exx +Doctor Fail +Doctor Funk +Doctor Fuzz +Doctor Iron +Doctor Krieg +Doctor Luck +Doctor Oby +Doctor Swag +Doctor WormP +Doctor Wylie +Doctor Zeh DoctorCoc DoctorHeiter +DoctorKraft +DoctorNutz +DoctorRex +DoctorSquat DoctorTsom DoctuhDrew Docxm Doddi +Doddy8D Dodge +Dodge Feet +Dodger995 DodgersBRAH Dodgy +Dodgy Player +Dodgy Todge Dodjomaster +Dodko Dodo134 Dodokipje Dodol Dodose +DodusNet Doefos +Doeidoei +Doep Doesnt +Doesnt Trade +Doetje Dofric +Dog Fart Net +Dog Myrnac +Dog The Frog +Dog did Meow +DogDiet DogFlyRatCow DogLogNogJog +DogShitter1 DogSoldier29 +DogTag Dogan +Dogannn Dogax Doge +Doge Caravan Dogecoin100x +Dogesaurus +Dogessa Dogestyle +Dogfruit1555 Doggiezz Doggoat +Doggshit +Doglinsheran Doglips +Doglover7004 DogmanJones +Dogplaceman Dogpoop +Dogres Dogs +Dogsh1t Main +Dogshit Rick Dogslayer420 Dogsume +Dogtogod Dogzie Dohace +Dohdee Dohenus Dohero Dohski +Doin It Raw +DoinGodsWork Doiran99 Doiu +Doja Chompy +Doja Shark Dokarius Dokdo Doken +DokeyPickle +DokiToast +Dokter Klok +Doktor Onion DoktorBarber +Dokuganryu +Dokuhime +Dokusei +Dol +Dol Alt Dolce +Dolerkyo +Dolf Dolham Doll +Doll of Evil Dolle Dolly Dollynho +Dollynho Bro Dolomite Dolormight Dolph DolphinAnus DolphinPucci Dolphinl1ck +Dom R +Dom Wong DomGaz +DomLaurencio DomYouAll Domanater105 Domantass +Domatic +Domccas Domeeee +DomiGothMomi Domiinant Domika Domimic +Dominate Jr Dominaton +Dominator541 +Dominatorrz Dominikus67 Dominionmake DominoTerry Dominos +Dominus Omni Domiros +Domixin Domke25 +Domknit +Dommie 07 Dommy +DommyDucky +Domo Teddy +Domoralized Domoszlo Doms +Domstad Slay +Domtoren +Don Abuja +Don Bob +Don Boki +Don Con +Don DingDong +Don Dotta +Don Huono +Don Matt +Don Moochie +Don Persian +Don Robb +Don Sebitas +Don Serrano +Don callum +DonB0t +DonBroco DonDennis94 +DonMarcino +DonThinKill5 DonWonTon420 Donair +Donair Dude Donal Donald Donald Dumps +DonaldTrump Donaldfact DonaledTrump +Donantelo +Donate Here +DonateBond Donato Donchz +Donda +Dondd +Donderschok +Done enough +DoneThat Dong +Dong Chan +Dong em Down DongActual +DongCowboy DongEater +Donger Lord +Dongi Donging +Dongolark +Dongs Ahoy Dongsalad Dongu Dongus +Donkerblauw Donkere +Donkernick +Donkey Kink +Donkey Squid DonkeySocks +Donkhu DonldTrumpet Donnatello DonnieAssie Donnieduke Dono DonoWho +Donology +DonovanRS +Donsalt Dont +Dont Be Pked +Dont Heal +Dont Sir Me +Dont You Shy +Dont do dat +Dont skill +DontBeMad DontBotNerds +DontDieMase DontDieSans +DontEatMyDog DontGetDrops DontHoldBack +DontJump +DontPanicPlx DontSassMe1 +DontStarve2 DontTellFeds DontTouchIt DontUseFKeys +DontWarnMe +Dontneedbp Dontyoudoit1 Donuhtzz Donut +Donut181 +Donutman +Donvys Donwcpot +Doob Doobe +Doobie Doo +DoobleDecker +Doodle Bob73 DoodleCraver DoodleTheGod Doodled +Doodledash +Doodoolist Doodslag +Doof Doofe +Doofensmirtz Doofy +Doogl3 Doogyplumm Dookami Dookers Dookie Doom +Doom Bar +Doom Metal +Doom Raiser7 DoomDoomDoom DoomFruit Doomblade Doomed +Doomed Necro +DoomiShroomi +Doomkid50 +Doon +Doooooobie +DoorDshGamer +DoorTech +DoorToLight +Doorknob +Dooz 12 Dopamemes +DopaminAbxsr Dopamine +Dopamine OD Dopatopia Dope +Dope Doc +Dope Plugs +Dope Sweater +Dope btw DopeAnteater DopeCalippo +DopeDrop Dopedrift Dopeturtle Dopeules +Dopey Iron +Doppa +Doppleganger +Doppleladler DopplerDank +DoraDaExplra DoraSweetass +Dordin Dore +Dorede Dorg +DorgonPocket Dorgoroth Dorito Doritomancer Doriva Dorkydevil93 Dorman Jr +Dormant Evil DormiNdaExp Dorohedoro Doronn @@ -6080,39 +12522,126 @@ Dorp Dorse DorseHong Dorthea +DortyKil Dorvagten +Dory364 +Dos STI DosEquis DosKadenas +Dosia Dosk Doss +Dostalgia +Dot Death +Dot Head Dot_Tea Dothalican +DottySloth Douane Double +Double CupMc +Double Drop +Double Take +Double agent +DoubleBrowns DoubleDeezus Doubleb011 Doubledonk +Doubt +Doubt It +Doubted Pyro Doug +Doug Salt +Douglasotto2 Dougoboy Doujinmoe Douq +Douyin +Dova_sage Dovahkiintim Dovahkyng +Dovitello Dovydas54 Dowatnow Down +Down Vote Me +DowniePatrol Downland Downlifter Download Downtown +Downworld +Dowzi +Doxus Doxxme Doxy Doye +Doyer1 +Doyers Dozck Dozerdayne Dozerrrr DpittmanIM Dqzi +Dr 7 +Dr Atsum +Dr B3rry +Dr Bading +Dr Barty +Dr Butt Love +Dr Caccon +Dr Camembert +Dr Cremaster +Dr Crumpet +Dr DO0M +Dr Edy +Dr Flipflops +Dr Gainz +Dr Geyseks +Dr Glottis +Dr Gotham +Dr Gulak +Dr Harry Nut +Dr Ivar +Dr Jago +Dr Jerry +Dr Kenchi +Dr La Scotte +Dr Lulu +Dr Madv +Dr Mawffle +Dr Melons +Dr Mikey +Dr MonaLaser +Dr Mustacho +Dr Mustard +Dr NFC +Dr Neuron +Dr No Life +Dr Oreo +Dr PFAFF +Dr Phil +Dr Plebeian +Dr Quirke +Dr Rave +Dr Robster +Dr Rum +Dr Shook +Dr Siesta +Dr Slayer +Dr Stamps +Dr Swaggins +Dr T e a r +Dr Tanner +Dr Volts +Dr Will MM +Dr Yosty +Dr Zeby +Dr Zeh +Dr Zimm +Dr obZen +Dr smithing2 +DrAsTiiC DrBeast DrBen50 DrBigSang @@ -6121,96 +12650,197 @@ DrBlumpkinz DrBuckFitchs DrButter DrC0X +DrChezz DrCrunch13 DrDRespect +DrDankMan +DrDankRip +DrDemitrius +DrDennisMD +DrDitalini +DrDoddi DrDruen DrEfficient DrFlobe +DrFognog DrHugecookie +DrJoose +DrKayzed +DrKevinn DrKiloGram +DrKush69 DrKushBurner +DrLoomis +DrLuckyacorn DrMatthie +DrNachtiga DrOly +DrPeppermmm +DrPhil2019 +DrPhineas DrPoopstein DrProfess0r +DrRift DrRipStudwel DrSevens +DrSkunkPhD DrSquanto +DrSwag +DrWodahs DrWoolyNips Dr_Olusegun DraCoNiiaN +Draacaryss +DraakSeviper +Draakmonkey Drac0claws Dracarus Dracaryys +Draccnor +Drache104 Draciel Drack3d Drackon Draco +DracoGhost Draconian111 +Dracote Dracts Dracula50125 +Draeghem +Drag Puff +DragSyndrome Dragen +Dragen Ballz +Dragers DraggSlayaa Dragnarok Dragneel Dragnipurake +Dragnkllr233 Dragon +Dragon Boots +Dragon Brew +Dragon Gras +Dragon Imp +Dragon Not 6 +Dragon Sword +Dragon Those +Dragon7998 DragonAxePlx DragonDrew +DragonKlaas DragonPrime +DragonSpayer Dragonbait4 Dragonboy691 Dragoncore74 +Dragonfeir +Dragonflew Dragonheat46 +Dragonkin892 +Dragonkingiq Dragonlear1 +Dragonluv16 Dragonmake DragonoidA2 +Dragonrains Dragonrune16 +Dragons Iron +Dragonslayaz +Dragonstompy Dragonstone Dragonvirse Dragonz +Dragonz Fury Dragoon +Dragoon0517 Dragoonalfa Dragoonhuntz +Dragoonnoth +Dragoscale03 +Dragq +Dragster5300 Draind Drairi +Draiserman Draithus Drakanelf +Draken Feest +Drakenwold Drakesh12 Draket +Drakhom Drakken Draknar DrakoVamp01 Drakonid +DrakosWrath +Drakuonis Dramyre +Dranasty Dranty Drap Drapht +Draugadroid +Drava +Drawbridge72 Drawde Drawll +Drax +Drayden Drayheart +Draynth Drazar Drazart5 Drazhe +Drazzo Drbeto11 +Dre Skrila Dread +DreadPandora +Dreadfvl +Dreadnott173 +Dreadnough77 Dreadnoughtt Dreadnuts +Dreadzie Dreagation +Dreak Dream +Dream Deeply +Dream Delve +Dream Plan +Dream Queen +Dream Realm +Dream Tempo Dream-layer DreamJT Dreamboats +Dreamcatcher +Dreamchasr +Dreamfreeze Dreamguy +DreamingLily DreamingNote +DreamisBack +Dreams Real Dreamscape Dreamstain +Dreamvil +Dreamy Ku DreamzRs Drecy +Dredd Dreddshott Drednok Dreek +Dreepy885 +Dreeww +Dregulle Drei +Dremarial +Drenthe Drenz Drenzek Drenzi @@ -6221,78 +12851,167 @@ Drew89 DrewNG DrewToshiro Drewbber +Drewbob24464 +Drewby Drewcas Drewfuss32 DrewsHotMom +Dreww +Drex +DrezaR Drezilith Drfannypack Drgreenthumz +Drie Fristi +Dries D-P +Driesca Driest Driewieler Drift +DriftTap DriftVolvo Driftzzilla Driger +Driger F +Driink +Drijf Hout Drikett Drikon +Drill n Fill Drink +Drink 4 Loko +Drink Empty +Drink Local +DrinkCheap DrinkPapaMlk DrinkSlinger Drinkability +Drinker +Drinkin Pete Drip Drip To Hard +Dripping Gut DrippingSack +Drive Stick Driver193 Drivious +Drizzy Drake +DrkMstr89 Drkfirelord2 +Drlime +Dro0 +Dro268 +Droefto3ter Droge +Droge Dackel DrogeBanane +Droid Dromedario Drommy Dromy +Dron Iick +Drone Reed Drone347 +Droog Meneer Droom Droopy Drop +Drop Acid +Drop Brews +Drop Please +Drop Rates +DropGetter DropMeUrPet DropTheFlop DropTopWizop +Dropko +Dropletics Drops DropsWhen +Drosaire Droski +Drouter Drri Drrrrunk Drswole DrtyBusDr1vr +Drtyhnddog Drudenhaus +DrudgeMunkey Drug +Drug Test DrugProblems +Drugged Out Drugonaut +Drugs Hurt DrugsArBadMK DrugsHere +Drui +Druknr +Drukzah +Drum +DrumBarrel +Drumaz Drummaboy276 Drummadr Drummerz Drums +Drums X +Drums of War DrumsSpace +Drumz Drunk +Drunk CCTV +Drunk CJ Drunk Jake +Drunk Mimic +Drunk Pastor +Drunk gaming +Drunk n High DrunkAssassn DrunkDriving +DrunkGhillie +Drunken +Drunken Monk +Drunken org Drunkfam +Drunkiin +Drunkn Fun Drunknerd Drunknhiiiii +Drwe +Dry 4 Hilt +Dry Cleaner +Dry Dong +Dry Hard +Dry Hardcore +Dry Soup +Dry Trip +Dry on stuff +Dry so I Cry +Dry x DryBandit DryWolf Dryhump +DryksMuseum Dryness Drynx +Dryron Man Dryskies +Drysol +Dryune999 Dryya +DshubaMisfit +Dsk 10 DssHimself Dstroyed +Dt2m +DtWoofles Dtjenl Dton +Du +Du Old Pker +Du lourd Du5tin 3 DuTson DuYorick @@ -6300,231 +13019,489 @@ Dual Dualerz Dualicious Duaneker +Duarterecife Duathlon +Dub Season +DubC Brownie +Dubalonius Dubber +Dubbers15 +Dube Dubie +DubieDebies Dubios Dublestuffed Dublet Dubs +Dubs_789 Dubsake Dubspeck DubstepsDead Dubu +Dubu Dahyun Dubz4Dayz Dubzy91 +Duc +Ducid Lream Duck +Duck Sucker +Duck Tape +DuckEnte +DuckNoSmoke7 +DuckSick Duckcited +Ducklovesyou Duckreas +Ducks Quac +Ducks U +DucksFatha +Ducky HVIII +DuckyTears Duckzi11a Dudash Dude +Dude Come On Dude12677 Dude9103 DudeAtHome +DudeItsMikey +DudeWD40 +Dudefish64e Dudeimblazez +Dudenmi Dudetastic +Dudification DuelKing +Dufendr Duff +Duff Daddy +Duff Groupie +DuffHeavy Duffmanas Duffs Duffy234 +Duffybroh Dufwha +Duggie Dugong1338 +Dugsie +Duh Kota +Duhstin Duhul +DuiBuQiShaBi +Duindorp +Duk Me Hard +Duke Ag +Duke Babylon +Duke Roland +DukeBaird +Dukino +DukkuTzi Dularian +Dulezburg Duli +Dullskie Dulwich +Duly Ignored +Dum n dumr DumFuknIdiot Dumb +Dumb Alien +Dumb Ass Dan +Dumb Drunk DumbDog DumbMatt DumbThiccAss Dumbaneering Dumbass +Dumbass 69 +Dumbass Tony Dumbells Dumber Dumbfounded +Dumbfuk +Dumbi +Dumbledore +Dumesday80 +Dumfries Dumle +Dumoo Dumpert +Dumpsterjed1 Dumwood +DunJunn Dunadane +Dunbahn Dunc95 Duncan +Dunco Dundasso Dundefeated +DunderHonung +DunderLadd +Dundiez Dundonian Dundrift +Dundrturken +Dune dain +Dungfung Dunghead Dunizz Dunjins +Dunjun +Dunkbox Dunked +Dunked on +Dunkies +Dunkle Sonne +DunknDink +Dunkston Dunlaf DunneDone709 Dunnill Dunwall +Duo Armadyl +Duo Elysian Duodenum Duoing Duoli DupaMuck +Dupe Holder +Duper +Dupey Duplicated Dupy007 Duqq +DuraDoobs Duracell Duracell321 +Duradad Duradal Duradels Duradyl +Durag Pat +Duramax +Durant Duravillidad Durex Durexslayer +Duri Durial Durial32won Durialives Duriel1 Duriul321 Durkburt +Durlz Durni +Durns Main Durocher Durooo +Durtsa +Durtsamang +Durtstar Durty DurtyFish DurtyFish HC Durukah Durumfe Durumoomoo +Durza Spy +Dus1O Dusansss Duseballs2 +Dushie +Dusk Summers Duskel +Dust in Dusted Dusters Dustielle +Dustin Rush +Dustinant5 Dustinn +Dustins Main Dusto56 Dustpan18 Dustt +Dusturbia Dusty +Dusty cones +DustyNoods DustyPope +Dustyin Dutch +Dutch Diablo +Dutch Dog +Dutch GOdz +Dutch Genius +Dutch Quin +Dutch RvG +Dutch girls2 +DutchEnergy DutchStuff68 +Dutchbobby +Dutchie +Dutchtin DutchtinOS +DutchtinsAlt DutchyCrazy +Duty Dutzu Duuni-Pete Duva Duvel +Duvelicious Duvl +Duwua Lipa +Dux Sauce Duxt Duztin Dvaergen Dvdasa831 Dven Dvlkid +Dvn Dvsk Dvst +Dw b happy +Dw ight +Dwagos 2 Dwake +Dwaki Dwarf DwarfSailing Dwarfoox Dwarfson +Dwarve Mage Dwaybe +DwerlzCH Dwibbel +Dwight Sn00t +Dworf Dxnnis Dxscoveries +Dxue Dxukko Dydapynk +DyePhix +DyinToLive DykeMenace +Dyl Dough +Dyl Gates Dyla +Dyla n +Dylan Du Sol +Dylan Iron +DylanCarl DylanFx DylanWad Dylanimal Dylanm504 Dylann070 +Dylano Dylbots +DyldoGreat +Dylectable Dylian +Dyllann Dylrex +Dyls Dylshanwang +Dylson +Dylsy Dymass Dymenshun Dymosh DynamicDuo +Dynamicdan47 Dynasty Dynloris Dynomite +Dynstyreborn Dyonutborne +Dyonysos Dyoung116 Dypso Dyrakos +DyreBatt +Dyreshot Dyrus +Dysae +Dyslexic gg DyslexicTree +Dyslexual +Dysliexc +Dyspnea Dystopias +Dysturbed Dystxpian +Dyth +Dyvv +Dyy Dyzurah Dz03 +DzRz +Dzakar Dzangg Dzentelmenas +Dzievan +DzintarsOls +Dzoseris +DzsungelTyuk Dzud +Dzun +E D V +E Fox +E MB +E N I M A +E R A +E S H +E SL +E V 0 L +E Z I O +E hm C uee +E ldest +E lixor +E lvarg +E lves +E mni +E mpathy +E njoy +E nvy +E p i i +E r ic +E th +E thy +E volve +E-Dawg478 +E-Grill E-Hubble E-S-T19XX +E1K E4as EA888 EARLYoCUYLER EBDB EBIDABLAY +EBZ ECCIES ECH0 +EC_Legends +EDATERHG69 EDGV1L +EDM Erik +EDM Playlist +EDMJo +EF tanq +EFFlClENT +EFILLAICOSON +EFL EG6808 +EGA EGIRLSIMPER +EGirl Marcy EHPause EHstro EIGRP EIessar +EIithi +EJ 207 +EJackUL8 +EL BULLYS +EL GA TO +EL Guuapo ELCAMI ELFlikeaBOSS ELITE +ELJosh ELUSIVE +ELVD +EMIYA Alter +EMPER0R95 +EMaes32 +EN X ENAC ENimmo +EOCscape +EOD20 EODdv EPLS +EREXI0N ERGENEKON ERJ145XR +ERRIE HERRIE ERRORMONSTER +ESCEDDIE +ESP Zone ESPARG0 +ESPORZUL51 +ETE76 ETHIOPIAN ETurns +EV6A +EVA ELFlE EVE0 EVScape EWFPLMFRLRLF +EXECUT0RZ +EXTT EXpoZuR +EZ Tag +EZ Till Dead EZ-Y EZBar EZnvm +EaTZyourOReO Eac63 +Eadgars Ruse Eadles Eagel89 Eager Eagle +Eagle Eye EagleSafari EaglesWentz +Eairj Eajk +Eara1 +Earendil Earl131 EarlRico EarlVincent Earll +Earll Ragnar EarnNest +Earth rune +Earth1ing +Earthling Em +Earz +EasY FraG Ease East EastEnders EastSyde +EastWho +Eastlakeclub +Eastment Easy +Easy Girls Easy1 +EasyDingMike EasyFro +EasyJet EasyNoRoids EasyRNG EasyTurbo EasyWhale +Easycore +Easyskillszs +Eat Crow +Eat God +Eat Hot Chip +Eat Tacos XD +EatBrick Kid +EatMoreGlue EatNutsGegex EatSand EatSleepPlay @@ -6532,43 +13509,84 @@ EatULive_666 Eatbananana Eathan EatingBigD +Eatpiebro +Eats Pant EatsPoop Eatu Eazie Eazy +Eazy AF +Eazy Rat +EazyGam3 Eazy_Peazy16 +Eazymon +Eb Marah Ebbitten +Eberebus Ebgame2 Ebinki Ebisumaru +Ebola +Ebolapaska Ebp90 Ebrahem2004 +Eburr +Ec0 +Ecahs +Eccles Alt Ecdubs Echo +Echo GIM +Echo Justice +Echo Slam Echo4211 +Echo_XVII +Echte Belg +Ecko RS Eckou Eclardyne EclecticDern Ecnubsirhc EcoLite +EconPhD +Ecs Nick +Ectuu +Ecxes +Ed Dobalina +Ed Si +Ed Word EdEddndEddy +Edd Gein Eddapt Edde7000 +Eddi e +Eddie GGs +Eddie MLG Eddie1402 EddieMercury EddieTross EddieVanHalo +Eddoz +Ede n Edelbae Edelweise +Eden XD Edga64 +EdgaRyto Edgar EdgarAlnGrow EdgarKing +Edgarr Edge +Edge c dr +Edge51 Edgelord +Edgerunner Edgevill Edgeville Edghill +EdgingGod +Edgy Boss Edgykid Edgynald EdibleChickn @@ -6576,22 +13594,48 @@ EdibleSnow Edisx13 Ediverse Edje +Edjob +Edmund +Edn +Ednnnx0 EdoKirurari +Edocsil Domi +Edocsil IRON EdotheJew +Edoxa +Edpls_o Edson Edspresso Edsy +Eduardo II +Eduardoo II Eduasia1 +Edunu +Eduzey Edvin +Edvius GO Edvyno1 Edwald0 +Edward Teach +Edward phish Edwarriorx Edwin Ownz +Eeeeeeeman Eeeeera +Eeekpenguin +Eeepen +Eek The Nub Eeli EelsUpInside +Eem lekker EenViezeVent +Eend btw +Eendsaurus +Eernegem Eeveeeee +EeveyBee +Eexhausted +EfORya Efendi EfficientBot EffinNips @@ -6599,63 +13643,147 @@ Effril Efnie Eform Eftur +Egg Boy +Egg Olmlet +Egg rolls +EggInTheRain Egganator1 +Eggs 11 +Eggs N Bacey +EggscapeRoom +Eggspert +Eggssmells Eggsy Eggtooth1 Eggy +EggyChipz +Eggzotic +Eglerz +EgoTeri Egoistic Egoran Egorous Egotistixal +Eh MapleTree Ehdjsnd +EhhFK +Ehms Ehnra EhpEhbGrind +Ehpatrick +Ehpriori EhrenSpoon Ehunter +Ei hekille +Eidolonvool Eientei +Eigenspace +Eigenvalues Eight +Eight_10 +Eigma +Eihwaz EikAyZ Eikel +Eilfs Eimp +EinBerlin3r Einar Einaras +Eindbaas +EindelijkMax Eingebildet Einsteins +Einswarior3 +Einyel Einzelkampf Eirik Eisen +Eisengor Eitsei Ejiogbe88 Ejjj1000 Ejma +Ejx +Ekali Ekim +Ekim117 EkkoThresh Eklof +Eklofs Ekonomisti +Ekovo +Ekstra +Eksynet +Ekwendeni Ekxo +El Arana +El Blame +El Blaze +El Boppo +El Chip +El Ghost +El Guapo +El Panache +El PapiTrump +El Pato lOko +El Patolino +El Pinguino2 +El Podger +El Scouse +El Smurf 370 +El WarLord +El Znorro +El-Fahoum ElBlancooo91 +ElGatoGris +ElGreg_4 +ElHash ElJReezy ElJohnny ElOso ElPoyoSenpai +El_Pickle69 Elaedor +Elano Elasticy +Elatedscarab +ElationArrow +ElbartoOSRS +Elbowd +Elbows Out Elbs Elchapo24 +Eldasero +Elder Coal +Elder Siroj +Elder nerd +ElderMoth ElderRyu Eldereon Elderpliney +Eldest Sense Eldia +Eldin Eldonskii Eldoubleyou Eldrek +EldridPenny Eldritch +EldritchMage +Elduz Eleandil Elebit Electr0lysis Electric +Electric Mud +Electric cat +Electrics Electrike +Electro Beat +Elektr0nas Element +Element Sk8 Elementality Elementhur Elementiix @@ -6668,57 +13796,97 @@ Elendaro Elenion Elephanten Elephants +Elephantz Elephent Elev +ElevatedLife ElevatedSoul Eleven Elevennn Elevil Elevo Elexuitt +Eley Elezar Elf King Leg +Elf u +Elfess Elfie +Elfinsocks Elfire626 ElfsWordFly +Elgifted Elgingo1 +Elgstant +Eli Ancients +Eli Fe +Eli Junior Elia135792 Eliass +Elice +ElichikAyase Elicit Elif +Eligos +Elijah Who Elilia Eliot Elipson Eliptats +Elirond Eliseuh Elit +Elitaire Lul Elitarisme Elite +Elite HIT +Elite Moscu +Elite Sendi +Elite Slayer Elite387 +EliteJager ElitePvmer EliteScaper +Elite_Quests Eliteisftw ElitesEyes ElitesFinest +Elitist Weeb +Eliwin Eliwood225 Elixir Elizabethboy ElizeRyd Eljaaa +Elkanath Elkias +Ell1eScape +Ellakazam Elliebus23 Elliot727 Ellise29 Elliterate Ello +Ello Ron Ellphie +Elly Dog ElmSpringsTN Elmatron Elmo +Elmo Narca +Elmos Wrld +Elmswood +Elnaphant Elnuma +Elo Luigi +Elo Solo EloJimmini Elocuente +Elodie +Elon M9sk Elons +Elox7 +Elpis Elppu Elqnaattori Elrebririand @@ -6728,56 +13896,121 @@ ElroyFTW Elryeth Elsa Elshak +Elsheshima Elshi +Elshire +Elsworth +Eltader2 +Eltry Eltuu +Elucidation +ElunedsSong +Eluniel Elusive +Elusive Drop Elusive818 +ElusiveOne +Eluti Eluw Elve +Elve Alt1 +Elve Elve +Elveiq Elven +Elven Durant +Elven Lamp +Elvenborn Elverum Elvey Elviax +Elvin Elvis +Elvis Crespo +ElvisArt069 Elvs +Elvyn Frenzy +Elvz Elwood +Ely the Man +ElyGoulding Elyam +Elyaris +Elyas5 +Elyas_Max +Elycal +Elyes Elyixa Elynescence Elyphosani +Elyqs +Elyrion +Elysi Elysian +Elysian Brew +Elysian OSRS ElysianError ElysianOP ElysianTank Elysianlove Elysianz Elysion +Elysiuhm +ElysiumFalls Elyte Elyxr Elyysian +Elyzarin +Elz +Em il +EmTvLive +EmaBeast OS EmaRae +Emacity momo Emad EmagndiM11 +Emalexa Emanated +Emanuel Emasterone +Ember +Ember of Ash +Embereus Embossis Emce +Emeowtion Emerald +Emerald Jack +Emeraldx Emergency Emericanpkur +Emerickb93 +Emeritas EmeritusD +Emhrys Emiel +Emiel Btw EmielM +Emielos +Emiit Emilharen Emilis +Emilliio Emilozz +Emilozzz +Eminem Yupp +Emirdagli Emirdagliii Emithyst +Emiya Shiro Emma +Emma Main +Emma Q1 +Emma epsi Emma1020 EmmaCn132 EmmaEmma EmmaRose +Emma_RC Emmaes Emmalitarosa Emmet1156 @@ -6785,28 +14018,52 @@ Emmet20 Emnay Emnicious Emnitylol +Emo Bee +Emo King Emoness Emoticon Emoyy +Empathy TKE Empathys Emperor +Emperor Elo +Emperor Xau EmperorBuggy Empery Empire +Empire State +Empireglorth Empirix Empty +Empty Box EmptyB EmptyBox Emptyhalo +Emptynogin Empyre +Empyrius882 +Emriat +Emu War +Emumafia Emus +Emylia En Jernmand +En ki +En oo vajaa En99omgangen +EnCue Enabled Enabler Enanthat +Enbrel +EnbyDeal Encrypted +Encryptiron +Encyclopedie +End Goals +End Grind End1ess +EndOnDeath Endanged Endem1c EnderMart @@ -6814,134 +14071,266 @@ Enderofwar Endgame Endgameplzz Endgegner +EndingTime Endir Endl3ss EndlesNights Endless +Endless Dawn +Endless RNG +Endlingg Endo Endor +Endos +Enedal Enemez +Enemm Enemyboy +Energie +Energise Energy +Energy Dave +Enert Enes Enfers +Enfes +EnforcerOP Eng1and Engage +Engagement EngelNacht Engen Enginaer Enginarc Enginear +Engineer Sam +Engineered Enginerd09 +Engl1sh Englandwon Englebassen +Englehr English +English Sir +English noob Enhtitled EnigmaCoder EnigmaWR +EnigmaZen +Enis Kanter +Enivid Enjoi EnjoiAssault Enjoy +Enjoy It +Enjoy Today Enjoymydhide Enjoys +EnjoysQuests +Enk rypted Enkaidu Enkeltje +Enkh Enki +Enkidu260 EnlargedNads EnlargedNut +Enmios +Enora Nyx FE Enoran Enormous +Enormous Hog +Enos EnoughGfuel +Enoux Enphadei Enraged +Enraged Crow +Enraged Lamp +Enranged Enrich Enrico Enrik Enroza Ensanguined Enshu +Ensnare +Ensomhet +Ent Sapling +Ent1tle Enterprise +Enthusigasm Entitled +Entiy Envello +Envidius Envied Envil Envious Envvi +Envx Envx1 Envy +Envy S +Envy lul +Envyctus EnvyouS Envys Envyy +Enza Denino Enzed +Enzel Enziguru Enzyme EoMeri EocBlowsNuts Eodwyn +Eol Ivan +Eos Adamm +Eos Mark Eostrix +Eowy +Ep1breren +Epaah Eperz +EphermalGoat +Ephi +Ephrayim Epiales Epic +Epic Nom +Epic Popo77 +Epic Specz +Epic Star +EpicGamer69 EpicReefer +EpicSalmon +EpicSpasms EpicToaster9 +EpicTomato EpicX Epic_Knight0 +Epicderk Epicoz Epicurus4 Epicvoid Epicx +Epigraphs Epiixx +Epikki Episodic +Epitohm EpitomeSlay Epix_x Epiyon Epods WifeY +Epoinen9 Eponas Eposs +Eppdawg Eppers Epping +Epson Eco +Epyll +Eq Equilibria +Equilities Equnox Eqwity +Er0l +Er1kasss ErBr +Era EraJorma Erabeus +Erad Eradicus +Eragon 1 Eragondragen Erase +EraseThat Erased Eray +Erbal ErbearIV +Erbiboar Erbyss +Erdi Erebus +Erect Chair +Erect Diglet Erectus Croc +Eredln +Eren The Nub +Eren Yaegar Erg129 +EriUmi Eric +Eric Brad +Eric Dingus +Eric Hansen +Eric RS +Eric V +EricN7 EricPrydz +EricR95 EricTheNoob +Erica +Erican Maxos Ericc +Ericgone13 +Erichilles +Erics Pixels +Ericsurf6 Eriction Erie Erijk Erik +Erik Ryatal ErikProbably +Erikaugust Erikci Jr Erikito09 +Erikkert +Eriknau +Erikoisjouko Erikoiskahvi +Eriksen14 +Erikske89 +Erikv28 Erinus +Eriscord +Erixzo Erkki +Erkki Pers +Erkkiks Erlid +Erlin Erlksson +Erm its me +Ermac +Ermafrodita Erna +Ernestaiii Ernesto056 Ernsour +Ero Erock2828 Erocktastic +Erodel +Erodoris Erony Eros Erosei +Erotic Maid +Eroxtroy Error +Error 510 +Error X Life +Error812 +ErrorSeven Errric +Errrr Ersei Ershayz Ershayzz @@ -6950,29 +14339,44 @@ Ertsu Eruni Eruptingcat Erwin +Erwin J ErzaGames ErzaScarlet +Es0x Luc1us EsArTee +EsJayW EsXP EsbenViking Esbuh +Esc anor Escalation Escaline Escanor1994 EscapeMaIron +EscapeWhere Escension +Escha Escnirp Esconex +Escot +Esd +Ese Burrito Esham +Esheme Sen Esimies +Esinaahka Eskalt Eskandar Eskeleto9 Eskett +Eskett II +Eskib0y Eskii Eskild Eskimeme +Eskimo EskimoFro +Eskizzibur Esko79 Eslamm Eslihero @@ -6985,10 +14389,16 @@ Espuky Espyria Esquelito Essencehour +Essex RS Essylle +Est Bellum Estafeta1 +Estar +Estebaan +Esteedee Esteeme Esteet +Esteffano 3d EsterKai Esterbrook Estetica @@ -6996,20 +14406,33 @@ EstevamStain Estiem Estonia9184 Estra +Estrogenizer +Estus Estusin Esya +Etakenai Etardoron EtchaSketcho Eternal +Eternal Envy +Eternal Max +Eternal NEET +Eternal Orb +Eternal Qt +Eternal Riw EternalGuide EternalHeart EternalPants +EternalSin9 Eternalfury2 Eternalgod99 Eternity +EternityAP EternityEndz Ethaan Ethan +Ethan Hunt +EthanMcSexy Ethanol EthansMain Ethel @@ -7018,157 +14441,304 @@ EtherBunny Etherealist Ethereous Ethernet3 +Etherscan Ethoxide +Ethread Ethwin Etikk Etis Etkzera +Etna Etnie0 Etobicoke Etrengereid EttLitetHus Etuovi Etyaz +Etymology +Eu_Matheus Euanx Eucaryptus Eucleides Euclidian +Euclipenguin +Euf +Eugenepickl3 +Euhem +Euhh Eukaryote +Eukko +Eulers Eagle Eulogise Eunbiii +Eunie Xeno Eunx Euphael +Eupharu Euphorion9 +Euphoriotic Euro +Euro Centric +EuroGarden Eurovizija Eusheen Eusiriito Euthia +Euxii +Euxy Eva-O1 Evadari +Evaiv EvanWilliams +Evanz40 Evaptix Evawe +Evdog +Evelynn UwU Evemarner +Even2000 Even3518 EvenMater +Evenepoel Evening +Eventyrlig Ever +Ever so Dark +EverSingular Everglow +EveronSky Eversiction +Every Color +Every Word +EverybodyZuk +Evette Evictus Evil +Evil Buu +Evil H +Evil Inari +Evil Kenevil +Evil Lizard +Evil Lord +Evil Nishiki +Evil Oak +Evil Twin +Evil Zayne +Evil-Mind69 Evil3yez EvilCopycat +EvilDeeds +EvilDegen EvilFootLong EvilH4mmy +EvilOwen01 EvilTriumphs Evilaz +Evildoer +Evilegod2 +Evilelfy Evilhammer +Eviljay Evillized Evilstar34 Eviltroll648 +Eviran Evirane Evnn Evo9 +EvoSlacker EvoSlayz +EvoeHalt Evoke Evolooner Evolution Evolved +Evra Evrs Evrybodypays Evse Evuk +Evultion +Evylix Evytt Evzmac +Ew Its Mike Ewan BTW +Ewang +Ewiiyar Ewmu Ewos +Ewya +Ex Files +Ex Holy +Ex Port +Ex Sythe +Ex-Slur Ex3rt Ex903 +ExHCMangy +ExMachina +ExMaxxed ExPro +ExPsi +ExQ Bratan +ExSevenTech +ExShiron +Exa OuO +Exaalt ExamJ +Exambient +ExamineCoins +Examines Examon +Exanso Exarch +Exasperation Exaz +Exbos Excadrill Excaria ExcelIsLife Excellarate +Excellini +Excinium Excise Exclude Exclusic Excody0 ExcuseMyStr +Execrating +Executed Executes Exella +Exem Exercise Exero Exflacto Exhaust Exhibition Exhumed +Exi Sisukas Exia Exile +Exile Vision Exile88 +Exile_vChad +Exiled Noobi +Exiled Peon +Exiled Slay Exileeeee Exiquio Exiriam Exiting Exmigrant1 +Exminer +Exo25 +Exoden Exodusty Exonaut Exor +Exorcism Exoristic Exorzist Exotic +Exotic Xenon +Exotica +Exotick +Exp Jesus +Exp Nerd +Exp Wasting Expaaja Expansa Expansce Expanse Expensive +Experience +Expl0it Explaindeath ExplicitPvm +Explodet +Explodium +Exploiter +Explorer +Explorifice Explosia Expochan Export +Expozz Expressed +Expressen Exright +Extella +Extended C Extile Extinct +ExtinctDecay +Extinguished +Extortionate Extra +Extra Chance +Extra Droog +Extra Poor +Extra Shadow +ExtraRNG ExtractorX +Extranjer0 Extreemkills Extrem3b0y Extreme +Extreme JeJe +Extreme Moo +Extreme Pray ExtremeJokeR +Extremterms Extrim Extrovert Extubation +Exty Exultia Exume Exus +Exus De Exustron Exwalker +Exxtinct Exynyt +Exz0 +Exzacly +Exzactly Exzakly +Exzian +Ey1 +Eye patch +EyeBDaMan EyeHaveToPoo EyeMakeYouQQ Eyeless +Eyelessjohn Eyeofdeath3 +Eyeron E +Eyes Inside EyesLowIndo EyezClosed +Eyggs Eylix Eymox +Eyrfire +Eyup xD +Ez Klaplong Ez4Peru +Ez4u2nv Ez4u2say EzBot EzCashin +EzSlayEzLife EzUnReal Ezarc HCIM Ezdrae +Ezero Br Ezey +Ezfart Ezia Ezra Ezup @@ -7177,117 +14747,299 @@ Ezxkiel Ezzardx300 Ezzi Ezzuna +F 3 4 R +F 0 N Z Y +F 3 R R U M +F A C E +F A N TT I +F E L I CYA +F For Flash +F I X E D +F L A T +F M L +F R A T +F Ribeiro F SONY +F T P +F You Bro +F athlete +F e e b s +F l a n Cat +F l u f fy +F l ux +F loofy +F reeze +F u z Z e +F ury +F-16 +F-ck Bleed +F-ck Irons +F00DCOMA F00F +F0O F0REIN F0ZI +F0cus Me F0rtune +F0sta F0xBr34d +F1 Mercedes +F104 +F19 +F1REWIND F1nalHour F1rst F1skemann +F1tn3ssWorld F20z F23A +F2L +F2P Waifu 07 +F34r My B0w F34rcr4ds +F3ARCE +F3LINA +F3lo F4DE +F4TB0Y +F4ust F4xi F7VD3 F80Scott +F8n +F8tz +F9 +FA DY +FA Joel FA1Z +FAILED ZEUS FALLGIRL1029 +FASHl0NSCAPE +FASTBLAST I FATHER +FATHER RANCH +FAlRWEATHER +FBD +FBGM 101 +FBGMi +FC Groningen +FC Liverpool FD3S_RX7 +FE AltScape +FE Cerise +FE Endeavor +FE Mazoku +FE Smore +FE wretch +FE80 Seal +FEJMBE FER00 FER0C1OUS +FERTILE DONG FEstlkerpeng +FFA +FFA Everyday +FFASplit +FFIE go brr +FFS Sam +FFV FF_GhiLLi +FFelidae FGHTIN +FHV +FIDADDY +FIFG Phat FILLME +FIRE 0F FIRESlTE +FISHY au +FIV3 FIying +FJ +FK Corp +FK TURAEL +FK1 +FKGlory +FKN RAPTOR +FKRA +FL jit +FL0CK FL3XPL3K +FLAPPYLIPZ +FLC L FLOR1DA FLYGOD FLYING FLgoob FLoKii +FM DOOM FMGbrien FMLshes17 FMarshalBill FN2187 +FNA +FNEkkGKGKWGK FO-LAZY FOES FOLEM FONKY +FONNlX FOSTEEEEZY FOUO +FOUR GATSU +FOV90slider +FOXBRAH +FP Engineer FR1T +FRAQSTAR +FREEBABA +FREED0M 1776 +FRIENDSHRIMP +FROM ICELAND FROO00OO0ZEN +FROSTYFOO +FROXBURG +FSK Gaz +FSW 2JZGTE +FTI FULGRlM FUTRHNDRX FUTillIFU FVChallenger +FW HYPZ +FX Teddy FXF_Tails +FYXON +Fa k er FaBeSCa FaNNtastix FaZe Faabio +Faalk Faardo +Faarihn +Faathos Fabario FabiScape Fabiann +Fabidjann Fabiiano +Fabioso Fabled +Fabled Fox Fabreezy +Fabretzio +Fabsitz +Fabulence Face +Face Seat Face9 FaceHook FaceTheFacts +FacedBased Facehuntter FacelessBoyd +Facilis Facing +Fack Russia +Factual +FadaPDF Fade +Fade Lightly +Fade zz +Faded Crook +Faded Focus +Faded Lungz +Faded Past +FadedFace Faderfouras Fadfats Fadge7 Fading +Faeanaro Faebat Faeles Faerindel +Faested +Faf FahQ +Fahim +Fahrbot +Fai1ure +Fail Be Dont +Fail Friday +Fail Stacks FailFish +FailedNoob FailedZerk Failing +Failocity +FailsauceFTW Faint +Faint Dallas Fair +Fair Folk +Fair Luck +Fairburn Fairex FairiesBane +FairlyDecent Fairr Fairr Enough Fairwolf139I FairyFeind FairyVeiler +Faith xd Faiu Fakdo Fake +Fake Chad +Fake Dylan +Fake ID +Fake Levi +Fake Pobble +Fake Suffer +Fake Will FakeBallots FakeGirl +FakeNews_CNN FakeNudez Fakent +Fakeppa +Fakez07 Fakezgen +Fakn Oats Faknius +Faku +Fal +Fal7 Falabar247 Faladalore Faladas +Faladoor +Falador +Falador Sq FaladorabIe +Faladorks +Faladussy Falcon Falconf1 Falconr Falconz420 +Faleis +Falestine Falkenberg +Falkuntpunch +FallOfSolace +Fallacy i Falladis +Falldyl Fallen +Fallen Dark +Fallen Hopes +Fallen Noble FallenBlur +FallenGods FallenOutlaw FallenSlayer Fallenchamps @@ -7300,152 +15052,395 @@ Fallon Fallout Falloutah Falls +Falls Apart +Falls Road +FallyFiddler +Fals FalscherHase False +False 9 +False Boon +False Divine +False News FalseGod Falsemorels Falubo +Fam Fam Chi Boy +FamIso Famcloth +Fame is +Famexx1337 +Famfrit +Familia +Familie +Family Crest +Famished Fe +FamishedNine Famjam +Famoose +FamousBowl +FamousBowls FamousPixels Famuel +Fan +Fanatic Est Fanatiker Fanawr Fancys +Fandri Fanfiction +Fang Dude +FangJo Fangsie +FannyPaca +Fantasieloos +Fantastik Fantikerz Fantomine +Fantrix +Fany Pack Fanzi Fappel +Fapperd +Fapple Bees Fapricorn Fapworthy +Far Alone FarAke FarFarOut +FarNear +Farages Army +Faragi Farah +Faramir +Faran Farao Faraolorddd +Farcry25 Fareham Farelinho +Farenru +Farewell Bud Farfire +Farid Lord +Faridi +Farigno Farkle +Farkwar +Farlz Farm +Farm Strong Farm11m Farm3r +FarmHub +FarmRun Clay Farmance Farmay7 +Farmelot +Farmenheimer Farmer +Farmer Blake +Farmer Crab +Farmer Dannn +Farmer Jayy +Farmer Johnx +Farmer McGee +Farmer Santa +Farmer Wull +Farmer Zach +Farmer Zratz Farmers Farmertree Farmin Farming +Farming Arma +Farming Moe Farmingfoxx +Farmingtool Faroeallstar Faron Faror Farpoint09 Farqin Farrier +Farron08 Farseer +Farseer Hat Farsight2 +Farssi +Fart Gunner +Fart Shartly +Fart Weed +FartInMyGob +FartSymphony +Farthinder +FartinLKing +FartinLuther +Farting cat +FartingCow +Farts2Wet +Farty Ass +Farukoo FasTLT Fascia +FashionBTW +FashionPig +Fashy Fast +Fast AF +Fastenal Fasterman Fastly Fastmagepk1 Fastmaniac +Fat Bawlsack +Fat Boobs +Fat Cat +Fat Clouds +Fat Fur +Fat Goombah +Fat Jonny +Fat Leb +Fat Maniac +Fat Mat +Fat Moron +Fat Nymph +Fat Rackz +Fat Ralph +Fat Salesman +Fat Swaggy +Fat Thin +Fat Waddle +Fat Wirgin +Fat Wrath FatBIunt +FatBurgerKid FatClock FatGreasyGuy FatITguy +FatKidBrett FatKidHougie +FatMonkey +FatSlutKing +Fatafeat Fatal +Fatal Cazual +Fatal Psycho FatalReign FatalXfire FatalisRS +Fatalsystem Fataltorment FatboislimOS Fatboy6 +Fatcav2 +Fatceps +Fatdogs11 +Fate Gu +Fate Z +Fateq FatesWarning +Fatez Fathead Father +Father Of 3 +Father Of M0 +Father Tacos Fathey +Fatmat +Fatrekt Fatso Fatstinkysak +Fatterhead +Fatty Combat +Fatty Park +Fatty-Kent Fatty380 +FattyIsntFat FattySupreme FattyTerps +Fattybanger Fattymcdugal Faultty +Fausto +FautleferQC +Fave +Favelador +Favion +Faw OCE Fawka516 Fawn1460 Fawz Faxon +Fayl Fayumi +Fayv FazTazTic +FazeQ FazeSkilling Fazebook +Fazed Imp Fazist +Fcape +Fcbfan1994 Fctillidie +Fe AND17 +Fe Adex +Fe Alma +Fe Anakin +Fe Bastok +Fe Carter +Fe Clay8 +Fe Cremator +Fe Dahje +Fe Dentyste +Fe Dopamine +Fe Gangsta +Fe Grom +Fe Gson Fe Hellpuppy +Fe Hucks Fe KabooM +Fe Kiteman +Fe Kyle Fe +Fe Liquid +Fe Logix +Fe Louis +Fe MGTOW +Fe MagicMan +Fe Monkey +Fe Mulks Fe Nail +Fe Nini +Fe Nocturne +Fe Nylost +Fe Oakdice +Fe Papi +Fe Patrick +Fe Pvm Tiger Fe Pyles XV Fe Qlimax +Fe Republic +Fe Rex +Fe Sav +Fe Setting +Fe Skilleye +Fe Slammed +Fe Sten +Fe Tentacles +Fe Thijssie +Fe Tomie +Fe UIM +Fe Viraxic +Fe Werty +Fe X AE A-Xi +Fe Xems +Fe Zachpnnc +Fe Zelta +Fe anor +Fe ared +Fe depressed +Fe elsBadMan +Fe il +Fe lonies +Fe lungs +Fe lyne +Fe r a t +Fe rgy +Fe ta Fe-ranator +Fe0xi +Fe20 Fe26 FeBriZley +FeCapedSloth FeCrab FeDestroyed +FeDyl FeFiFoFum FeFireTruck FeFlo FeFox FeIII +FeJonnisjoen FeKyle +FeMale Chris FeManlett FeMattsheets +FeMoist +FeMudcheck +FeNote FeOx +FePash FePinkviini FeReelix FeShane FeSolaris FeSynical FeTaeliah +FeUIMIronBTW +Fe_Schrute69 +Fe_StarLord +Fe_Symphony FeaR +Feaaar FeagMeister Fear +Fear Fun FearKev FearMyTM26 +FearOfChange +FearSamurai FearTheBear FearThyDoom FearTurkey Fearengineer Feargasm FearlessFudu +Fearmaker1 Fearrod +FearzebuJr Feasted Feather +Feather Bug Feathereli Febelz +Febreezio +FecesFyrHose +Fedad Feded Federal +Federated +Fedji Fedo +Fedooool Fedt Feebee Feebz +Feed Forward FeedMePlants Feedback +Feedle +Feek 1 +Feel Ya +FeelMyBirdie Feelin +Feelin Fine +Feelin It FeelinHappy Feelmygame Feelosophy Feels +Feels Lonely +FeelsDuBis Feelsbadkapp FeelslronMan +FeelzBradMan Feen +Feet Watcher +FeetFunGoose +FeetPic Fefe3 FefilleLaDur Fegicaly @@ -7453,48 +15448,96 @@ Fegoob Feint Feisty Feit +Feitn +Fel FelNeck Felamar Feldip Felgenhauer +Feli-Marie +Feliaff Felinaed +Feline Feast Felix2 Felixa +Felixigor6 +Feller Crus +Feller Magic Fellow +Fellow Fool +Fellowships Felmyst +Felon +Felonies +FeloniousHam +Felony Ruler +Felted Female Henry +Fembo y Femboi +FemboyFloppa +Fementedspaq Femister Femke +Femke Bol Femkekos +Femstiq Fencig5 +Fencingduck Fencko Fender +Fender Axes +Fender Twin +Fendoral +Fene77 Fenerbahce +Feniks366 Fenix Downs +Fenix Kiros Fenkat Fennikel +Fenny RS Fenomeno11 +Fenothiazine +FenrilasIM +Fenrirs Fall Fens +Fenshy Fenske +Fented +Fentenal Fenternal Fenyxgreen +Fenzo +Fenzy +Fequites +Feral Wiki FeralFiddler Feralblood +Feraligatr44 Feraliigatr Feratzu +Ferbzy FerdaWoox Ferduh Fereekelor Ferlide +Fermeon Fernando-Frv Fernie Ferny Fero217 +Ferocious J Ferocious97 +Feroos +Ferousity +Ferpderp Ferrarezi +Ferrari +Ferrari Enzo FerrariScape Ferrat +Ferrdie Ferreklop FerretFoSho Ferrex @@ -7504,117 +15547,216 @@ Ferring Ferrinheight Ferro FerroPlanty +Ferrothan Ferrothorn Ferrous +Ferrous Frog +Ferrous Hugs +FerrousBoii FerrousWheel FerrousWolfe +Ferrowing Ferrum +Ferrum-56 FerrumPawn Fersapian Ferus +Ferus Ferrum +Fervor Ferynys Fesan Fesenko Festis Festiva +Fesu FetaCheese Fetetchie Fettisdagen Fetus Feudal +Feunk Fewest Fewideahide +Feydx Feyenoord36 Feylon Ffilteg FfsImAfk FgtBob +Fhil +Fhk Trudeau Fhpure1 +Fibeer Fiberlight +Fibix +Ficc Ficomon +FiddlesLeaf +Fidds93 +Fiddy Ate +Fiddy Bag +FiddyDuddy FiddySweens +Fidelity Fiege +Fielacius +Fielde FiendinLo +FiendsDream +Fierce some Fiero Fiets +Fiets opa Fietsen +Fiff Fifflaren Fifth +Fifth Herald Fifty +Fifty 5O +Fifty Cent FiftyFive FiftyForty +FiftyStones FigaroTheCat Figes Fight +Fight 04 +Fight For Jk +FightMiIk +Fighta +FighterSE +Figless Duck Figmentx +Fignootters Figpig +FigsNotPigs +Figure +Figwit Fiiderino Fiiggy +Filed +FiletOFlesh FilipTelford Filippia Fillifjonken FillyFilly12 Fillzu Filmmaker +Filo Legolas +Filofteia +Filoksenia +Filson-zzZ +Filth0 Filthy Filthy Bird +Filthy Clam +Filthy Pesnt +Filthy Santa +Filthy Weeb +Filthy istik Filthy4Iron +FilthyDane FilthyDingus FilthyOreo FilthyPixels +Filthy_Stew Filz +FimiWolf +Fin Vader +Fin219 FinPunisher Final +Final Redux +Final playz +FinalBossUIM +Finalbang Finalbrk +FinalityB Finally Finaltank Finch +Fincher Find +Find mucking +FindTheTeemo Findawg56 +Finding Dory +FindingDory Finding_Mary +Fineillspoon +Finem Mundo Finesse Finessing +Finex FingerBang +Fingerdfilly Fingered Fingerlegs FinickySquid Finish +Finish Flash FinishedLog Finishzuelan Finklestein FinkyFink Finlan Finland +Finlanderi Finlanders Finlays +Finlunch Finn1309 FinnelCake Finnica Finnish +Finnkie Finral Finrufa Finsho Finsta +Fintiaani +Finutty Fiola34 Fiora +Fipimuesi +Fir3bird85 Firat +Firben Fire +Fire 745 +Fire 961 +Fire Captain +Fire Chiller Fire Fiesta +Fire Fist +Fire Galley Fire Kaped +Fire Kittie +Fire Tune Fire10910 FireAF FireAnRescue FireGiant +FireKornez FireOnRs +FireReid FireTruckBoy FireWolf28r +Firebelly Firebuggy +Firebwans +Firecan1314 Firedevil +Firedrake658 +Firehawk746 Fireheart470 +Firein12 Firejax Firekirbyeli Fireknight0 Fireman +Fireman Sam Firemanzz Firemutt Firenova @@ -7624,116 +15766,201 @@ Firesmash Firestarone FireyDragons Firko +Firnik First +First Bozz +First Up FirstBathTub +FirstBlood 1 +FirstIron +FirstRS First_Viking Firulay18 Fish +Fish Cow Dog +Fish Keeper +Fish Nibba FishFingerz FishGoBlub +Fishcake +FishesBmine Fishey Fishie +Fishling Fishoii Fishstickz +Fishsword389 +Fishvaulter FishyBrines Fisicas Fiskhue +Fisna Fist FistMeTrump Fister +Fit Jr +FitAid +Fitdis Fitis Fitsit +Fitty Tyson FittyBuck +Fitzy Smalls Fiurio Five +Five Demands FiveManSplit FivePaws FivePointOh +Fivee Skinn Fiveskin FixationRS Fixed FixedCost FixedMain +FixedWing Fixions Fizbin +Fizg0d +Fizz Khalifa Fizzed Fizzle +Fizzy Glizzy FizzyGuzzler Fjala +Fjala r Fjalee Fjollan Fjolle Mate Fjomp +Fk RS L +Fk W Da Woo +FkingEzeKial Fkking Fklostmybnk Fkluzac +FknDeece FknDreaming +Fkuru +Fl y FlLTHYYYYYY FlNARKY FlTTY +FlTZ +Flabaghast +Flaboogles Flaccid +Flaccid RNG +Flaccid Semi FlaccidWhip Flacid +Flackyo Fladra +Flagaria Flagrance +Flagrant 2 +Flagz Flaherdog FlailTheKing +FlailingGoat +Flair Viper +Flakelar Flakey Flakeydude Flakkas Flakto Flamaha +Flame Lurker +Flame0fUdun Flame29 +FlameSoother Flamed Flamel Flamepistol +Flames4 Ever +FlamingPee +Flamingfox +Flamingguy7 +Flaminold Flaminrofls +Flammbam Flanelli Flap +Flap Slap +FlapJackals +Flapple +Flapsian Flare Flare Grylls +Flareblade Flareon +Flarez Flarp Flash +Flash Voyage Flash3200 FlashYellow Flashbane +Flashbang +Flashcards Flaskepost Flat +Flat Eric FlatAssPlank FlatEarth361 +Flatback Flatlandah Flatorbrush +Flaunt Flava Flavaaaaa +Flavie +Flavour Trip +FlavouredDav Flavur Flaw Flawd Flawed +Flawed Bliss +Flawless xD Flawnn Flawzin +Flax Pickerr Flaze Fleaa +Fled 6ymcric Fleeson +Flemingo Flemino Fleruas +Flesh Forest Fleshgod +Fleshpound Fletch2 Fletched0 Fletcher +Fletcher 06 Fleton +Fletz Fleurescent Flex +Flex Wayne +Flex1bel Flex1bility +FlexCity FlexSeal Flexatronic +Fli pper FliPancakes Flick FlickMyTick +Flicker 06 FlidFlop Fliga Flight FlikAwrist +Flikker +Flikker Kind Flimmyflan Flimpy Flimsywhale @@ -7741,83 +15968,147 @@ Flimzy Flinch FlingDragon Flint +Flint RS +Flint Water Flintstoned +FlipDaddy +Flipdam +Flipje Flipman24 Flippa +Flippa Monk Flippar Flippers Flippin +Flipsen07 Flipzzzup Flirz +Flit Wick Flix +Flixy +Flizz xd Flllllllllll Float +Floater eyes Floatzelo Floballer Flock43 +Floeter +Floki loki +Flomple Flonza +Floody +FloofyTurtle +FloofyWaffle Flooga Floogan33 +Floopyboople FloorTwenty Floot +FlopLord Flopez Floppy +Floppy Boaby +FloppyDongle Florian +Florian_1988 Florida Floth +Flover Flow +Flow it +FlowMafiaaa FlowState Flowah Flowen0ne Flower +Flowerm00se Flowiey +FlownbyFire Flowtown +Floww-Grown +Flowwar Flowzyy +Floxin Floy Floyx +Fludds Fluenz +FluffPandaSr Fluffafluff Fluffalo +FlufflePluff Fluffy Fluffy chair FluffyTater Fluffypony44 Fluga +Flugel25 Flugenhorn1 Fluid +Fluid Voyage +Fluke Jr Fluminense Flunc +Flunt Capz Fluoroform Fluorophore Flupbaster Flurius +Flushiz FluteBand Flutlicht Fluxee Fluxery +Fluxion +Fluxx V2 +Flvd +Fly an High +Fly by N7ght +Fly in Fly-TheW +FlyLo FlyPap3rr FlySunyQuest Flyboyray Flydol +FlydonWayno Flyeeee Flyer +Flyer TMT +Flyer W Iron Flyern Flyguy13 Flyhll Flying +Flying Pingu +Flying Swede FlyingBobcat +FlyingIrish +Flymi +Flymzy Flynny Flynsquirrel Flynt Flyonwings Flyvende +Flyvende Ged Flyy +Fml IronMan +Fml Its Adam +Fml Its Carl FnHit +Fnatic +Fo Ring +FoRbeZiiLLa +Foam Corner FoamDemon1 +FoamShrimp +Foamshire Fobu Fockwolf1 Focus +Focus73 FocusOnGoals Focusor Foen @@ -7830,78 +16121,157 @@ Fohmie FoiledSoftly Fojin Fokjefe +Folayyy +Foleshill +Folesy Folfox +Folieo Folk Folk169 Folktale FollieRS +Followed +Follower Folwifuswalo +Folxi Fomble +Fomid +Fondle FondleMyIron Fong Fonnis FonsJ +Foo I I Food +Food For Me FoodEmperor +FoodStampGod +Foodfoodfood Foodie +Foofickle FookOffNerd Fool +Fool Senpai +FoolFighters +Foolery +Foolingling +FoolishHeart +Fools +Fools Errand +Fools Switch +FoolsErrand +Foomp Foooman Foose Foosyy Foot +Foot Ball242 +Foot Magnet FootLocker Footaphiliac +FootlongMike Fooz +For +For Karamja +For My Block ForDaScratch ForKrimpt ForNostalgi +ForRusssia ForWeAreMany Forbe ForbiddenCry Forbids Force +ForceZero +Forcekid Ford +Ford Racing Forearm ForeignBoris Foreigner Foreknown +Forerunner40 +Forescimitar Forest93 +Foresteris +Foreva +Forever Wild +ForeverAlone +ForeverClone ForeverLost Foreverett ForgetThePet Forgetmenot Forgetpluto +Forgettios Forgive Forgived +ForgottedPin Forgotten ForgottenRNG Forkbomb +Forkers +Forkmitt +Forks Out Forma +Formal +FormalPotato Formaldhyde +Former Nub FormerDivine +FormerSeaman +FormuIa 1 +Fornuis +Forresten Forsaken +Forsakens Forsworn66 Fort +Fort Chronos Forteh +Fortified +Fortify +Fortimuss +Fortis Lupus +Fortjent FortniteRox Fortran95 Fortress +Fortunes Forty Forza +Forza Derby ForzaGTx +Forzam Fosh +Fossa69 +Fossil Rock +Fossul +FosterXP Fostret +Fosz +Foton Fotty Foumy6 +Found Prawn +Found3Groots FoundABaby Four +Four One 6 +FourB FourZone3 Fourlifee Fourloco Fournlock FourthChance +FourthPower +Fowke +Fox Enjoyer +Fox Two +Fox Zebra Fox243 +FoxStevenson FoxTherapy FoxVex Foxall @@ -7909,152 +16279,281 @@ Foxe Foxerx1 Foxes Foxfiend +Foxfire +FoxfireStyle Foxi +Foxing Foxtrot +Foxx OG +Foxxwild Foxy +Foxy Rebel +Foxy SuzyQ FoxyBaphomet FoxySquid +FoxzHound +Fozbert64 +Fozie FpsMichael +FpsWheelerrx +Fpsallday +Fr anci5 +Fr ankie +Fr0 Fr0zEn111 Fr1ckingH3ck Fr1xioN +Fr3Pa1est1n4 FraJoLaaa Fraagile +Fraazzy Frab Frac +Fractals Son Fractuality +Fraggiux Fraggle FragmentedX +Fragmentizer +Frags Frail Framed FramedJunior +Frames Wolfe Framingham +Franche420 Francine1225 +Francis0wns FranciscoJ32 Franco Franf10 Frank +Frank Donner +Frank Is Dog +Frank Lin +Frank White +Frank-sama +Frank836 +FrankMadeME FrankTTank Frankers FrankieFlow FrankiesAlt +Frankinspank Franklin1O1 FrankyFish32 +FrankyLeGros FrankyyTanky +Frantiks +Franwan Frappacholo +Fraqqer +Fraser +Fraser840 +Fraspex Frassboss Frate Fratto +Fratty Flows +Fraud Thurgo Fraught Frauwz +Fravvomaxx +Frayhalla +Frazer Frazia Frazoo Frazze +Frazzlewagg Frazzt +Frchtzcker +Fre d Freaak Freak +Freako07 Freako09 Freaks Freakxx +Freaky Peet +FreakyWajt Fred +Fred J Frost +Fred Solo FredMaxedALT +Fredagsgroda Fredanbetty +Freddi Freddiep +Freddy CEO +Freddy ownz Fredericton +Frederizz Fredla +Fredleif +Fredo Fredric Fredriks +Freds Breads Free +Free Dumb +Free Minded +Free O9 +Free lootkey FreeFreeze FreeFryBread FreeHongK0ng FreeKoolaid FreeTeli2Lum +FreeTheRealD Freebooterv +Freeczs BTC Freedom Freedom06 FreedomJust FreedomUP Freee +Freehky +Freek 1 FreekALeak Freekkittens Freelo Freeman Freepop +Freerangee Freesoul Freest Freestylin Freeway Freeze +Freeze M E Freezes Fregion Frei Frekitohh +Freky FrenchBuoy +Frendi Frenek +Frenkurt Frenmiir Frenzy +Frenzy4 FreonPays Fresaaaa Fresco Fresh +Fresh Cheese +Fresh Pesto FreshPotsRS +Freshly +Freshske +Frette Freud Frevlin Frewdy Freya +Freyas BTW +Frez +FriarNation Fricas +FriccKip Frickin +Frickn Playa FridayDa13th +FridayMojito Fridelis Fridfoolium Fried +Fried Erik +FriedRicePls +Friede Friend FriendlyJo Frietjecurry Frieza +Frieza Saga +Friezerik Friggn +Friggy +Friibag Friisby +Fris +Frisdrank Jr +Frisky Lime FriskyBiznaz FriskyJews FriskyPainal +Fritszon +Frittered Fritz Fritz94 +Frix Frkn +Frnds FrobroSwagin +FrochioRS Frodo +Frodo Bagger +FrodoBagGims FrodoBogues FrodoRS Frodoinc1 Froemelke +Froemeltchhh Froez66 Frofuzz Frog +Frog Blog +FrogBoySlim +Frogfish12 +Froggiefish Froggit +FroggyBro Frogmann +Frogone9 +Frogsforjp Frogtelllow +Frogtoken Frogwork Frohobo Froloox From +From Beyond +From Florida +From Lebanon +From Nz FromNewWorld FromSoftware Front +FrontBottoms FrontierEdge +Froobing Frooby Froomey +Froot Loop +Frootata +Froppy Tsuyu Fropul Frosht42 Frost +Frost JTS +Frost Mages Frost_PvM Frostbiter +FrostedBow Frostmourne Frostserpent Frosty +Frosty E +Frosty Gay +Frosty6570 Frosty751 +FrostyPea43 +FrostySurge Frostyfuz Frostyyyman Frote +Frotzr Frovz Froya Froyotech @@ -8062,221 +16561,604 @@ Froz09 Frozah Froze Frozen +Frozen Crown +Frozen Rain +FrozenKing FrozenMosin +Frozencarrot +Frozenn Dusk +Frozty Feet Frrrozn +Fru Katt Frufoo Frugal Frugtmanden Fruh +Fruit Crepes +Fruit Dryer +Fruit Munch Fruit1824 Fruit1846 Fruitbooting +Fruitje +Fruitloop8 Frunk FrunktheHunk Fruta Frvnk +Frxnk White +Frxnklin +Fry B +Frysta +Fsaze +FtheFrench73 FuAiluue FuNrikoz FuRiouSs +Fubar3d Fubini +Fubuki +Fubuking +FucDPS FucNorfKorea FucaDuc +Fuchsiger +Fudeath36 +Fudg3 Fudge Fudgie Fuel +Fuel Ex Fuertote_17 +Fuetakishi +Fug +Fug sakes FugDisFugDat Fugedit FuggleQuest +FuggnIronBtw Fuglemanden +Fuhni Fuhrerengel Fujimator Fujk FukYeaChina Fukahi Fukinnnn +Fukn Lit Btw Fuktflekken FulMomentum Fula FulgBTW Fuliss Full +Full 3A +Full AD Vlad +Full Boost +Full Moot +Full Tilt +Full of Wo0d +FullGraceful +FullSendGoat +FullTimeNerd FullTryHard FullerACL Fully +Fully Mobile Fullysick Fulsh +Fumblebag Fumblers Fumbles12 Fumin +FumingMe +Fun Guy mhm +Fun Sucker +Fun1nFunera1 +FunHotBox +FunWithFire +FunctioningC Fund Fundo +FuneRune Funeral Fungi Funk +Funk Head +Funk Mastah FunkBondMule Funkafiend FunkiPorcini Funkiboy2 FunkiiMonkii +FunkleRoy +Funkr +Funkshun +Funkworks Funky FunkyBoy4444 FunkyDiddler +FunkySlut +Funky_Hunk +FunnelCaker Funni +Funni Memmer Funny Funny-King03 +FunnyAndEpic +Funobu Funpeople5 +Funrun123456 Funzip Fuorra +FuqAgility FurMissile Furbs +Furi Potion Furious FuriousPower Furiri Furo Furox Furry +Furry Wall FurryDemon Furrykins +FursonaHaver +FurtleTurtle Furty Furu Fury +Fury DnT +Fury Lord FuryJunky FuryL0rd Furyian Fuse +Fuse is HARD +Fuseton Fusiiion +Fusion Aurum +FusionGT2 +FussyParter FutchDuck Futex +Futss Future +Future Tense FutureKaiden +Futureruler9 Futures +Futures Main +Fuuwah +Fuxley Fuze +Fuzz Man FuzzManPeach Fuzzums4 Fuzzy +Fuzzy Sox +Fuzzy jaw95 Fuzzy1918 FuzzyDonkey FuzzyFudgey FuzzyMWV +Fuzzy_NooT +Fuzzybear65 Fuzzyblaa56 +Fuzzykitty Fuzzzy +FvS Love +Fweafwe +Fxked +Fxob +Fxrgus +Fxrret +Fy six Fy12e +Fyitz +Fylberg +Fylize +Fym +Fyr +Fyr Tornado Fyresam Fyri +Fyrinlight Fyron +Fyrox Fyszz +Fyzio Fziaa +G +G 0 A T +G A F F E R +G Alfansos G Ape +G B S +G Check +G Fruit +G GAMER GIRL +G I M Danny +G Iron Adam +G L E N +G L H F +G M B +G Man9822 +G Mauls +G O O D +G O O S E Y +G R E E N +G R I L L O +G Terminator +G X F C +G Zus +G a r t y +G a t t s u +G ante +G dot C +G e n g a r +G eeb +G i j s +G i l b o +G iG +G imme +G iooo +G l R L +G laze +G no Z +G o G G u +G o h o +G o th i X +G oldd +G oldeen +G oofy +G ozz +G rafix +G ronimo27 +G root +G shi +G u a m s +G unitt +G-F-M +G-IronKuv +G-Thug Nasty +G-knowww +G-rivs +G0AT JUICE G0ATWRANGLER G0D Richard G0DLY +G0LD3N G0LDC0AST G0LDEN G0LDENB0Y G0LDIE G0NGSHOW +G0OEY +G0TH ANGEL G0TTY +G0blineer +G0dr3kt G0dsnotdead G0ing G0ld G0lden +G0rillaJesus +G1C G1adiador G1edrelis +G1izzyGob1in +G1m Luna G3RM4N +G3ZZ4 G4M3OV3R G4RG0YLE G4UAFS +G4YLORD G4de +G59 Awol +G6E Turbo G6Wizard +G80 +G99s GAAANNNGGG GABBAGE +GAGGED N +GALO9A GAMMAGARD +GAMxJAKE +GANONd0rf GAOKNMxzHR +GARDlNER GATECRASH GATTl +GB Amarok GBJackieWang GCMidlane +GDG +GE IS WACK +GE to FE GE0RG3WKUSH GEARLE55 GEEZ0 +GERANUS GERRIEE GEtItFrAnK GFHL +GFe Aang GFmanbearpig +GG Joe +GG McCloud +GG Sofie +GG Wped GG6HJA9KSDHJ +GGGGGGGGanta GGGskywalker +GGW Limit +GGW Thanos +GGf1cation GGtoHH +GH05T DUDE GH95 GHEEESE GHETT0JESUS +GI GN +GI Lewis +GI Lucky +GI Madras +GI Mohib +GIANT HENO +GIANT ITIOLE GIBBO96 +GIGAGUMPH +GIM 0dawg +GIM 2nd +GIM Albin +GIM Aperture +GIM BTWW +GIM Ballak +GIM Barkless +GIM Baylis +GIM Bunzz +GIM C J +GIM CgIsEasy +GIM Composer +GIM Conkers +GIM Cris +GIM DareDev +GIM Derek +GIM Dionysus +GIM Dormant +GIM FatLion +GIM Fearzzy +GIM Ganther +GIM Glalie +GIM Globi +GIM Hatred +GIM Hola +GIM LWE +GIM Lasse_ju +GIM Lazyguy +GIM Lxxs +GIM Lyon +GIM M0FFY +GIM Madac +GIM Magneto +GIM Malphite +GIM Martas +GIM Maudi +GIM Mcstro +GIM Me STD +GIM Mecknon +GIM Mirasei +GIM Moith +GIM NewPorts +GIM OatBloke +GIM Obvious +GIM Or715 +GIM Philrat +GIM Player02 +GIM Qtpie +GIM RWT +GIM RagePope +GIM Raheem +GIM Rakfaan +GIM Ring +GIM Schaa +GIM Schnei +GIM Sense +GIM Snax +GIM Stinks +GIM Stompy +GIM Stoney P +GIM Stu +GIM TUT +GIM Terix +GIM Tman +GIM Tobi +GIM Toe Pic +GIM Ved +GIM Viklok +GIM Wife +GIM Zork +GIM atomic +GIM bad ass +GIM brutal +GIM kerma +GIM poy249 +GIM sabinsky +GIM xDist +GIM-Topsu +GIMAerospace +GIMButcha +GIMFunder +GIMME CLAW +GIMP Crystal +GIMP DlCC +GIMP Jonny +GIMP Suns +GIMP Toast +GIMP Will +GIMP Zuzu +GIMPlayer69 +GIMRavenKing +GIMTruck-Kun +GIM_NoRun +GIM_Snowwolf +GIM_tybraun +GIMcardellio +GIMonster +GIMp Brian +GIMpope +GIMxH2 +GIRTH CHECK +GIronPPVibes +GL GETTIN IN +GL on Purple GL78 +GLG Sophie +GLUS GLWeAllDie +GM Matt +GMEMan8000 +GMKirby GNULinux +GOAT GOD 420 +GODSOMBRA SL GOGETA +GOLOVOLOMKEE GOOD +GOODGAMEGGXD +GOP DUMB +GOZERGAST +GPA +GPWASTER +GR0OOT +GR1NCH GRAB-A-LEAF GRAN1T3 GRAND GRAPHISTED GREIV0US GREIVUOS +GRIMSTAIN +GRINGOLAO GRUMPY +GRUMPY BSTRD +GRUMPY PAPAW +GRYGRY GRiMZ +GRiMZ 420 GRlM +GRlM REEFER +GS Concerta GSAileen +GSW Shane GSwolls GT350 +GTA SA GTFOIMGAMIN +GTOD +GTRKingZilla GUBIDUBII +GUCCI SENPAI +GUCCl GUJ0 GUNMAN683 GURRD GUUMBY GVSU GYDtown +GZA +GZX +Ga l +Ga7ba Gaara +Gaara Sand Gaarden +Gaarise +Gaarlokiin +Gab al Ghul +Gabagoo l Gabber +Gabber NaTaN +Gabberboy15 +Gabble Gabe Gabe020 +Gaberoks Gabesz Gabo +Gabrahanth Gabriel61198 +Gabris +GabyabyxD Gacha Gaddgedlar Gadrak Gadwall Gaerolth +GaethjeKO Gaga +Gaga Iron +Gage S +Gageks +Gagne Gahbo Gain +Gain exp +Gainful Grey +Gains alot +Gainz Godz +Gainz Nerd GainzForHire +GainzWorld +Gainzvill +Gainzville GaiusTavi Gaiy GalGadotsBF +Gala G Galamx Galandorf1 Galar Galava Galaxia +Galaxiancam +Galaxies Galaxy +Galbazeek1 +Galderr Galdysa Galgenbrok +GalickGunner Galilee Gallaxy Galleta Gallium +Gallowbell +Galon Garuda Galon1 Galow +Galton +Galvatron Galwic +Galyam +Galzuk +Gam Gamaiiron Gambinahuora Gambino +Gambit +Gambit Ghoul Gamblerz Gamboy46 Game +Game Clown +Game Name +Game Of Olms +GameBot2000 GameOvaries3 GameStop Gameboto4 @@ -8284,36 +17166,63 @@ Gameboyjr Gameboylight Gamelia7 Gamer +Gamer Log +Gamer Worded Gamer4Life +Gamercutie Gamerplaya7 +Gamerr +Games Rigged +Gameshow Gamesman Gaming GamingLover GamingVapor +Gamir Von Gammel Mand Gamorrah +Ganandalf +GandaIfNoir Gandalf +Gandalf staf +Gandalf3602 GandalfBalle Gandhi Gandolf +Gandolpeeni +Gandon12840 Gandulff Gane Gang +Gang Goblin +Gangbarang Gangnrad +Gangris +Gangry Gangsta Ganj GanjaGhandhi GanjaRhino +Ganjoefarner +Gankicus Gankster +Ganna Bogdan Gannicus Gannicusproo +Gannnon Ganooch Gansa0 Ganta Gantee Ganthorains +Gantre +Ganzaxuz +Ganze +Gap Tester Gaping +GaratholX7 Garbage +Garbage Life GarbageEater Garbagexd Garbar6 @@ -8321,140 +17230,268 @@ Garboh Garbug Gardenia Gardening +Garder1968 Garena Garfinator Gargano Gargaspoon Gargath286 +Gargathon Gargleon Gargoyle79 Garlic +Garnat Garnet Gust Garp +Garrb3ar Garrett Garretttt Garrothis Garthoon +Garvis Gary +Gary Ghee +Gary Giggles +Gary Guldske +Gary Linkov +Gary Wang GaryDabs GarySmokeOak Garyjayjay Garysson +Gasconade x +Gash Pasher GashBndicoot Gashtag Gassy +Gassy Cat GassyFlaps +Gastje888 Gastronaught Gate Gateofdoom +Gath Gato GatoNaranja Gator +Gator Bob Jr +Gator Papi Gatorboiz +Gatorian176 Gatorslyr GatrsNTaters +Gau Cho Gauntlet +Gaur Gura Gauss Gautstafer +Gauvin Gavbin Gavi Gavii +Gavin Dance Gavita Gavrot +Gavussy Gavy +Gawd Bodi +Gawk5000 Gawkes Gawkss Gawt Gawz +Gay 4 Guthix +Gay Bear +Gay Bear Cub +Gay Farm +Gay Fieri +Gay Framed +Gay Holly +Gay Impling +Gay Liam +Gay Male69 +Gay Snake +Gay Squire +Gay Vermin +Gay Wimp +Gay450Bucks +Gay4Ketchup +GayWalrus69 +Gayblade +GaylsHaram +Gayme Gayron +Gaz GazGoon Gazaman11 +Gazan Gazd Gazed +Gazed Soul Gazelle2211 +Gazru Gaztok +Gazza +Gbax-Style Gdey56 Ge0rgeburton GeChallengeM GeTLeFt1 +Gear 5th +Gear Carried +Gear Fear +Gear Sekando Geard +Gearfried +GearheadSTL GebwellB +Geck-o +GeckoDad +Gedmuush GeeHasMews GeeStreet Geeb Geebs Geebster +Geef Bier +Geegles Geeker Geeknip +Geeman125 Geen +GeenBankMan Geera +Geerin GeertWillows Geestig +Geeving +Geewd +Gefilus666 GeggaMoya Gehrman GeilTijgerke GeilePaddo Geitekaas +Gekido GekkaJohn Gekke +Gekke Farmer +Gekke Nelis +Gekke Pablo +Gekkesmurf +Gekoh Gekolian +Geks GelZmog Gelawynn +Gelderlander Gelezis +Gelijk Geliquideerd Gellaitry +Geller Bing Gelly +Gelmar +Gem +GeminitusII +Gemlingur Gemsbok +Gen Kokopuff +Gen4 UU GenCoupeGang +GenFormat GenGraardor +Genabackis +Genann +Genaron +Gene Shorts GeneBelcher GeneDenim GeneKapp +GeneVieve_SL General +General Aldo +General Bigi +General Iroh +General NL GeneralJosh GeneralLudd +GeneralMcRib GeneralMo GeneralMoist +GeneralNASTY GeneralPlay +GeneralStore Generall +Generall_xx Generalton Generol55 +Genesee +Genesis G80 Genetiics Genetiz +Genga r Gengahr Gengerbred Geni +Genie Magick +Genie Talls GenitalsHead +Genix +Genjitatsumi +Genk Gennie +Gennu Geno +Geno RS Geno2566 GenoJuice Genocidal +Genovan Genres Gensha Gentileza Gentle +Gentle Death +Gentle Gypsy +Gentleman J Gentlemanfox Genty Genuine GenuineDude Genus +Geo Fe Geo Geo GeoDuuud Geoculus Geodark +Geof Sux 666 +Geoff_Failed Geoffry +Geography +Geoguess +Geoide Geologistic +Geomatic Geonde Geordie George +George 36th +George F M +George Vv GeorgeJx93 +GeorgeVork Georgey +Georgezs +Georgies +Georgopol Geoso Geotechnicki Geovanna GerAmi +Gera1d Gerald +Geralt Nivea Gerb3 Gerberos Gerbs @@ -8465,47 +17502,92 @@ Gerjan GerksShirts Germaan GermanGuyRS +Germanic Germaphobic Germimo Gernoazi +Gero Geroko +Gerr Hurka +Gerrido Gerrmz +Gerroes4GIM +Gerry Bud Gershboon Gert GertrudeSimp +GertrudesAss +Gery07 +Gesaldo +Gese Geskar +Geso Gesoz +Gestetner +Get A Life B +Get Back Son +Get Bread +Get Exp +Get Fukt Pal +Get Pho +Get Syked Get0nMyHorse GetABeerInYa GetATapWater +GetAclick GetDatXp GetMeOut +GetMeOutHere GetOnMyLvl +GetOverlt +GetPets12 GetSkipped GetThatUpYaa +GetTogether GetUrWild0n GetWreckdSon Getdolphined Getfck3dup Getlow777 +Getplayed Getsu +GettinTanked +GeudensK +Geuld +Gew Gewoon Gezang +Gf g Gf4tiuser GfRsIGotAGf +Gfi +Gh3t0 T4nk3r Ghafir +Ghaipol +Ghandizy Ghandy +Gharron Ghckkrchkrer Ghda +Gheed Ghentiana Gherkins Ghetto +Ghhjgwsr +Ghidorah +Ghillie Suit Ghilly Ghoosted Ghorraka Ghosnik Ghost +Ghost 311 +Ghost Ahoy +Ghost Fe +Ghost XP +GhostAralein GhostHouse +GhostOrchids GhostTank GhostXD Ghostas @@ -8513,305 +17595,675 @@ Ghosteeen Ghostfice Ghostflips Ghostiami1 +Ghostly Taco GhostlyFetus Ghostlyowns Ghostninja +Ghostsu +Ghostwish492 +Ghosty +Ghoul Intent +Ghoul Zeta +Ghraz Ghruntsarokk Ght179 +Ghurrix +Ghuuneiboi Ghxul +Gi Lew +Gi bbo Giallo Giant +Giant Ego +Giant Gochu +Giant Killer +Giant Peenos +Giant Plums +Giant Trunks +Giant spider +Giant235 GiantConker +GiantShafty Giantesss +Giaveri +Gib bread GibMePets Gibbed Gibberish Gibboh +Gibbon +Gibbon girl Gibby Gibby0712 Gibbzzy +Gibsky +Gibsmeister +Gibson Giddy Cowboy +Giddy Yup Gidejong Gidionn +Gidle Soyeon Giebu Gielinor +GielinorGage +GielinorGoat +Gielinord +Gielinored +Giena +Gier Gierige +Giffaro +Gifgas GigaBinary +GigaChad FSW Gigabit +Gigantic Nut +Gigantic Owl +Giganttio +Gigashit +Giggel Boy +Giggety +GiggleFailer +GiggySmalls Gigi Gigime +Gigs x0rz +Giiblo Giiirtz +Giitzy Gijoe184 Gijs Gijsbart +Gilan Gilbert +Gildart_91 Gilded +Gilded Gucci +Gilded Robes +GildeddGuppy +Gilenoth +Gilesy_93 GilgaGaming Gilindur +Giljom Gillan +Gillbert44 Gille Gilles Gillisuit +GillyChop +Gillyjj Gilnash Gils +Gilthresa +Gim Balboa +Gim Mayhem +Gim Reaper x +Gim Rickard +Gim Sahara +Gim Synicals +Gim ckn +GimJonel Gimaralas Gimbli102 Gimlocke Gimme +Gimme Pixels GimmeDatWAP +Gimmie 500k +Gimp Charona +Gimp George +Gimp Rachau +Gimp Sage +Gimperfect +Gimpgas +Gimptan +Gin N pizza +Gin Theory GinValid +Gina Linetti Ginekologs +GingaFe +Gingaaaaa Ginger +Ginger Elvis +Ginger KG GingerUnit49 GingerZ94 +Ginger_Men Gingerbeefe Gingr +Gingr Snaps +Gingyge +Ginjaah +Ginko Sora Ginny Ginobeatsss Ginyuu +Gioarcher69 Giorgi +Gios Ladder +Giovanniam Giovano +Gippeo Gipson Giraaa GiraffeLord Giraffeneck Girl +Girl10116 +GirlGamer420 +GirlLoveeee Girls +Girls Add Me Girlygurl420 Giroza +GirrthBrooks +Girsu Girth +GirthBeast +GirthMatters +Girthy Bunny GirthyBaboon +GirthySack Giskardr +Gist Gistermorgen +Git Ducked +Git Gudr +Gity +Giuuntas Give +Give Advice +Give Er +Give Me Kith +Give Purple +Give Purples GiveMeMaul +GiveMutagen Given +Given Bow +Given Power Givera0 +Giville Giving Givox +Gixerikan Gizmoed +Gizmoo247 +Gizzy-71 +Gj nice Gjerloew Gjonunaki +Gktr +Gl Bob +Gl Im Dandy +Gl Im Tom +Gl0ver GlLDARTS +GlM Sam +GlMKingCole +GlMP Blue +GlMP Purpp GlNGER GlRLS +GlTHUB +GlUwUten +Glaceon Girl Glacial +Glacial Fog GlacieredTig GladePlugIns +GladeSONPT Gladeandy +Gladiator12 Gladiator4x4 Gladpootje Glads +Glaeser +Glaive Rush Glance +GlasMelk +Glasabarn Glashute +Glass talons +GlassIsrael +Glassblow Me +Glassface +Glava Glavas Glazmeister Glazyy +Glcnn +Glcnn II +Glcsw Gleassi Gleddified Gleep +Gleesoman123 +Glejak Glen +Glen Cook +Glen Kenobi +Glen OSRS +Glenbobis +Glennis25 Glennitals Glennyboy Glennzii +GleuberBTW Gleythar +Glicky +GlideWho Glierieman GlitCH1221 Glitchfather +Glitchxd +Glitterix Glo-Tank +Glob Master +Globalled +Globby Gloc Glock +Glock 48 GlockHoliday Glockford +Glocktopuss +Glocs +Glod Gloei +Gloei Lampje Gloom Gloop Glopyz Glorfsaus Glories Glorious +Glorpy Glorp Glossay Glou +Glough Gloves Glow +Glowing Dawn +Glowing Ray Gloyer +GlucGluc9000 Glue +Glue Scroll GlueInhaler Gluehbirne Gluest1ck +Gluhh Glukoosi Gluons Glut +Gluteeni +Gluten ei Gluteous +GluteyIM +Gluurbuur Gluurder +Glyn Glyo Glys +Gmackie1 +Gmic +Gnaes +GnakNim Gnarkotics +Gnarled Gnarles +Gnarly Nacho Gnarlysurfer Gnarmato Gnarnold Gnarwhal +Gnashit GngBng +Gnge Gnight Gniles Gnoblin Gnome +Gnome Ass +Gnome nz GnomeBustas +GnomeChompii +GnomeFN +GnomeScarf +Gnome_child1 +Gnomeball Me +Gnomedalf Gnomeopathy Gnomeplay Gnomeputone Gnomerex Gnomeruno +Gnomes +GnomesDid911 +Gnomonkey +Gnomuim Gnon +Gnoob Gnorc Gnos +Gnosticz Gnotyep +Go Already +Go Die Go Do One M8 +Go FF +Go Outdoors +Go Outside +Go Rogue +Go Thanos +Go ask Wiki Go2HornyJail +Go4Stonks GoBearsUA GoBiiii +GoDhAsCoMe2u GoDrinkWater GoGGu +GoIsland GoPlayOutsid +GoSlow +GoToBedKids Goads Goal2Max Goalkeeper54 Goals Goat +Goat Toes Goat512 GoatAteMySon GoatOfWar GoatStank +Goatbigboy Goaticorn +Goatman Goatmelk +Goatrilla Goats +Goatsky Gobbie Gobiasinds Goblin +GoblinBreath GoblinLevel1 Goblinborn +Goblinchips +GoblinxSlaya Goby358 +Gochancee1 +God 126 +God Aye +God Bjorn +God Flax +God Forgave +God Like PvM +God Of Chips +God Of Hatrd +God Of Lamps +God Of W13 +God Pandora +God Ranger90 +God Tier +God of Walls GodDmntNappa GodEmpsTrump GodHalfMercy GodKingJT +GodLovesG4ys GodM GodOfCats GodOfTorment GodSaidGrind +GodSaved GodSlayer422 +GodSoge +GodTierAcct GodTormentor Godaa Godcody +Godd Is Good Goddaz GoddessAmaya GoddessHylia Godenzonen +Godeso Godezzo +Godfather TR +Godfather9 4 Godis Godkip +Godleh +Godlike Nico GodlikeOne Godly GodlyLeecher GodlyThug GodofAhri +Godofore +Godofyou2 +Godric777 +Godrics Gods +Gods Madness +Gods Plans +Gods Savage +Gods Taint +Gods Word GodsBlackSon GodsSniper GodsSyndrome GodsZombies +Godsent GodsentHero Godspade +Godss Angel Godstrong +Godswordl +Godte +Godumas +Godvermomme +Godwar Godwise GodzFear Godzilla Godzilla1282 Goed +Goed Gedaan +Goed stinke Goedaardig +Goedgemutst +Goeie Sannie Goeman Goes +Goggoli Gogo +Gogo Gorilla Gogojuice +Gogoud GogurtYogurt Gohan +Gohanski Gohler +Goiij +Goilin +Goin +Goin Slayin +Going HCIm +GoingBald130 +GoingBonkers Goinvokeman Gojam +Goji Berries +Gok Wan k +Gokillanoob Goku +Goku 420 +Goku Nazz Goku3ss3 Gokuu +Gol +Gol D Stocks Gold +Gold Avocado +Gold Devill +Gold Golem +Gold Lynx Gold M40A3 +Gold N Mole +Gold Ox +Gold Ruler +Gold Scrap Gold-Ileana GoldTracerR1 Goldclaw30 Golden +Golden Acorn +Golden Dunes +Golden Eyes +Golden Power Golden2Aim GoldenArm647 +GoldenGoose GoldenMinion Goldendev +Goldendrgn GoldfarmCOX Goldie47 GoldieOne +Goldiekk +Goldkimono Goldless Goldmagic +Goldmagic 1 +Goldminer727 Golds +Golduck +Goldy Mox Golem +GolemDuoGIM Golemantium Golembaby Golf +Golf Socks Golfcarts Golfje92 Golfkarton Gollito GolloSam +Gomardo Gomham Gomsugo Gomut +Gon GonDaba GonFeeshin +Gonah Gonapappa Gondort Gone +Gone9237 +GoneClear +GoneFarming +GoneInDry GonjaMon +GonnaSleep +Gont Gontr +Gonyor Gonzalo +Gonzra +Goo Cat GooMoonRyong +Gooball Gooberz +GoobledeGoop +Goobtacular Good +Good Bull +Good Creb +Good Cuxt +Good Darts +Good Duck +Good Ironman +Good Natured +Good Pho You +Good Potato +Good Voodoo +Good lol GoodFight +GoodGuyJosh +GoodOlBussy +GoodSkinCare +GoodTalk BRO +GoodVibes Gooda4 +Gooday2uall Goodbye +Goodbye game Goodcents +Gooddeerend +Gooder Album GooderB0aty +GoodlyKi56 Goodole Goodpizza +Goodriver Goodwin +Gooey Bace Goofy +Goofy Kitten GoofyLlama +Goofzillers Googagoogago Googie +Googii Google +Google Plus +Google THC Googleisme Googs +Gool164 +Goomy +Goon Galore +Goon Rangoon +GoonRNG +Gooner Gooneshy Gooney Goooby Gooochy +GooodO1dDays Goopbandit +GoopityGlorp Goose +Goose Field +Goose World GooseAlmyti +Goosebottle +Goosecaboos Goosely Gooshus +Goostafus Goothan Gooziky Goph +Gopherpaws Gophurr Gopuppy +GorGorDon16 Goragtong +Gorak +Gorastaman Gorathe +Gorazdus Gord Gordi Gords @@ -8819,68 +18271,133 @@ Gore GoreTexZ Gorehogthot Gorg +Gorge002 Gorgeous +Gorgeous Vin +Gorgeous War Gorgonsolo +Gorgoth +Gorila911 +GorillaChad +GorillaHaze GorillaMon3Y +Gorillr Goriox GorkOfGuthix GorogSmash Goromi +Gorons Ruby +Gorpie GorskiGG +Gortron +Gory Figment +Gorzie Goshiki Gossip Gosustyle +Got Mad Nugz Got my DD214 GotABigDoing +GotItAll99 GotTheTool GotchuXL +Goteborg Gotemburgo +Gotham Steel +Gothic Mommy GothicHippy Gothicking70 +Gotta +Gotta B Dope GottaSlay Gottaburn +Gougar Gountor5 +Gourd GourdPicker +Gourmandise Gourmet +Goy Boyy +Goy Oy Vey Gozi Gozpot Gp On Me +Gr OO7 Gr0tti +Gr33n +Gr3at Noob +Gr4naat Gr4p3 +Gr4y W0lf Gr8Legacy +Graaf Mol +Graardad +Graarp +Graav Grab +GrabAColdOne GrabbaLeaff +GrabsPeePee +GraciousHeeb +Grade I Graenmeti Grafie Grafvs Graham47 Grain +GrainUhSalt Grainfedbeef Grainter +Grainwave Grainys +Grakron +Grallham +Gram othy Gram0fDabs Gramalio +Grambo Grammar +Grammar Naxi GrampaDreami GramsaySan Gran +Gran t +Granbyboys69 Grand +Grand Magpie +Grand Tree +Grand mb GrandErected +GrandSlash +GrandVince +GrandWizard +Grander LTU Grandikid GrandmasterT Grandmasters Grandpa +Grandpa H Grandwarlike Graniitti +Granite God1 +Grannolegs Grannt +Granny Tiddy +Grant +Grant LLKL Granto +Grantos1993 Grants2004 Grape Graphics +Grappleshot Graros Grasp +Grass Nugs Grasshoppper +Grassman-420 Grast1z +GratefulFunk Gratefulfunk Gratis Gratitheode @@ -8888,178 +18405,360 @@ Graudalin GraveDiqqer Gravecan Graveless +Gravenor Graves Gravew0rm +Gravitrons +GravityPulse GravyTugboat Grawgar Gray +Gray Goo +Gray Icon +Gray Nine +Gray Owl +Gray Sails +Gray Wolf31 +GrayXOF +Graybanns Grayden Graymarrow Grayola +Grays Peak +Grayv +Grazalay +Grazia Grazing +Grazing Goat Grazium +Grazuz +Grazy Killah Grazzak GrcRevisited +GreFunky Greally +GreasierNerd Greasy +Greasy Nerds GreasyGoose +GreasyKnucks Great +Great Catto +Great Dain +Great Sneeze GreatBritain +GreatFambino GreatGinGin7 GreatNorth +Greater Rev Greaterbeing +Greaterwang Greatgranpa Greatwhite62 +Gredhkj GreedyFox GreedyG4me Greek +Greek Bust Green +Green Floyd +Green Gh0st Green Guru42 +Green HoHo +Green Molly +Green O +Green Theory +Green noob Green0ktober GreenBstard GreenClue GreenCortex +GreenMonstah Green_Matcha Greenbeens1 +Greenboy638 Greendor +Greene Daeye Greenikulas Greenmusiq Greenwell Greenwolf666 Greg +Greg Bcknghm +Greg M +Greg NM +Greg Why +GregLAD Greggery Gregley +Gregobeast69 +Gregor itos GregorJesk Gregornaut Gregory +Gregoryxo +Gregreg Gregsdabomb +Gregy165 +Greh Greig +Greil +Grej Gremlin Gremoir GremorysPawn Grena +Grenadev Grenenjah Grenthyl Gressaker +Grewal +Grey Beards +GreyCheddar GreyStation2 +Greyballes +Greybird +Greyhound00 +Greyhounds Greyhunter +Greytness Grider Griefstonks Grieve +Grieve r Grieve4Nieve Grievedd +GrifSpice +Griff Please +Griff6GG Griffey +Griffeydor Griffimano Griffin +Griffin 900 +Griffinerr Griffoo Grifo Grifwin Grihm Grilby +Grill Bears +GrilledNem Grim +Grim Lahey +Grim Reapr Grim1O GrimR GrimRequiem Grimalkinn +Grimby +Grimescene +Grimey17 +Grimfeather +Grimhimblem Grimm +Grimm Malice Grimmauld Grimmij0w +Grimmjaww +GrimmjowCero Grimmlie Grimms Baane Grimnitro Grimple Grimreaper22 Grimsomebody +Grimwar Grimwold2 Grimy +Grimy Elf +Grimy Ghetto +Grimy Guamay Grimy H +Grimy Lord +Grimy Oppie GrimyBuchu GrimyIndica +GrimyPussy +GrimyRanarrs +GrimyTorstol +Grimz Reapin +Grimzyy +Grinchy Grind +Grind 4 Max +Grind 4 Pets +Grind Time Grind4Life2k +GrindAndGame +GrindFaster Grindcorr Grinder GrinderTo99s Grindin Grindinator Grindius +Grindlwald Gringotts GrinoReigns +Gripzakje +Gris Moor +GrittyTacos +Griz mobile +Grizmatik Grizzley +Grizzly +Grizzly Rock GrizzlyCares GrmblGrombl +GrnBstrdO_o Grobar20 Grobaz Grod15 +Groen Hertje Groene Groesbeek Groet +Grog Dog +Grog Mobster Grogget Groleo +Gromada GrommrUK +Gromp Love Gronk Gronky +Gronky Mutt +GroogeN +Groot Lol GrootPool GropeJelly Gros Gross +Grosyte +Grot I +Grotegelds Grotkop Grotty Grottyzilla +Ground Hawk +GroundGolem GroundRanarr +Group Int +Group Pig +GroupAaronMn +GroupSexyMan +Groupie Hugs +GroupieSheep +GroupyCoopy +Groves +Grow Culture +Grow a Set Grown +Grown ups 2 Grrh Grrim Grrr17 Grrrrrrr +Grubbfoot +GrubbyNative +Grubumas Grucci Gruglio Grum Grummmy Grumpy +Grumpy Bear +Grumpy Dane +Grumpy Rock +GrumpyBean GrumpyFire +GrumpySkelly +Grumtuque +Grunderzz +Gruntlife +Grupopo Grwl Gryff1n Gryygeri Grze100 Gschlez Gsef +Gsuz +Gtacoolz GtheSquid Gtotgt +Gtr Zilla +GuBoki Guadanha Guak Guaka Guala Guam +Guam Autism +Guam Extract +Guam Leaf +GuamFarm +Guapify Guar GuardMaze Guardhakan +Guardiaaan Guardian726 Guardy Guason Guataca Gubrew Gucci +Gucci Print +Gucci Sheets +Gucci Skrrt Gucci0 GucciBalboa +GucciChris GucciDang GucciDragon +GucciMedHelm +Guccifi GucciiFlops Guckle Gudfad3rn +Gudge +Gudginator +Gudmen Gudomligt +Gudown Guelph +Guernicaa +Guess I Did Guest738 Gufix +Gugaru Guidebook +Guidefox +Guido Bwana +Guildboss Guile Guilles123 Guillotine Guilou3 +Guimmy GuineaHorn +Guizompaz +Gukkiman GulTraktor Gulf +Gulmek +Gulpar +Gulpin Gulsaft +Gum +GumGum B +GumGum Fruit +Gumat0s +GumbleChunky +Gumbygerkin +Gumbygrump Gumbygusher Gumbypriest Gumiibear @@ -9068,12 +18767,19 @@ Gummibier Gummy GummyTushie Gumpie123 +Gumri +Gun +Gunalations Gunci +GundarV Gundrace Gundrak Gune Gunfire +Gunite Gunjamini +Gunman +Gunn a Gunna Gunnar Gunnawr @@ -9082,156 +18788,351 @@ Gunnolvur Gunny GunnyGuest Guns +Guns Up +Guns n Rozes GunsN +GunsN Roses +Gunshow36 Gunsmith95 GunsonGurner +Gunta Guy +Gunter +Gunteria GuntherNese Gunthie Guntilius +Guntown Gunvald1 Gunwil +Gunzyx +Gupto3 Gura GuraChan +Gurahka Gurchh Guren +Gurenz Guri77 Gurilovich +Gurke Gurkes Gurnie GurningPills +Gurnsy Gurog Gurp +Gurp Gork +Guru Pathik GuruOz3 +Gus is Maxed GusMagnel +Gushing Thot +Gusmamba Gustav +Gusten +Gustice Gustie1 +Gusty x GuteArbeiter Gutenberg +Gutenberger +Guthiccz Guthix +Guthix Boss +Guthix San GuthixIsBae GuthixVapes Gutti +Guuds +Guus geIuk +Guusman Guwaap Guwapp +Guwgle +Guy Shishioh +Guy Williams +Guy in hat +GuyBillNye GuyDude GuyHarvey GuyInReaLife GuyOnaBear +GuyOverThere +GuyintheChat Guyringo Guzas +Guzman Loer Guzzle Gvjordan Gvzy +Gwaas Gwas +Gwas BE GwasMaster Gwasha Gwasing +Gwaztec +Gwd Gweav +Gween Dwagon +Gweeve Gwellz +Gwenchanaa +GwigMate Gwimer Gwinter225 +Gws 2 +Gwu +Gwublin Gwyn +Gwynrwyn +Gxhost Gyanzin +Gyga +Gym Beam +Gym Is Home +Gym then GYG +Gymming Gymp +Gynn GypsyAvenger +GypsyTears Gyrati0n Gyro Gyroman +Gyrotta Gytisr9 Gyts Gyym +Gz Parsec GzBs +H 0 U N D +H 2R +H A D O +H A I D E S +H A M M E H +H A R L S +H A T +H A X 3 D +H D M P +H E A L E R +H E J S A N +H O L M E +H Q Killer +H S 7 +H U L K K +H U N A J A +H a t y +H a w n y +H abs +H alo +H ch +H e c t o r +H i n e s +H l E U +H obbs +H owl +H rekDoer +H uff +H-tsi H0B0 H0DEX +H0LINESS H0NA H0PES H0RSEFIGHTER +H0RY +H0j +H0j00 H0lyPorkyPig H0me H0nestyBe +H0wy H1GH H1gh H1gs +H2 Ninja +H20magic H22a H2GivesUTheD H2HO H2Okt +H2R H3AV3N1Y H3NNESSEY H3adBurner H3ll H3llg0g H3nti3 +H3rbMaXD H3rbs H3rioon H3xxar +H4RD P V M +H4RD PVM +H4wk0n H501 +H61 +H8 +H8rry +HA RD HACHE HADYYY +HAHA CODY +HAMMY P0TTER HANDLEwCARE HAOKIMALONE HARVEY HARYWERNASDA HASA +HAUS DOSAN +HAWGCRANKD HAXERFUGGv2 +HBPandox +HBTFD HBTurpin +HC DVS HC Diego +HC H R A D +HC HALLEN +HC J P +HC Lone +HC Nitsy +HC PogChamp +HC Tehl0rd +HCByTheWay HCIM +HCIM Freak +HCIM Telmo HCJynkky +HCTHB HCaturbate HCgenes HClM HCmunchies +HCquitter HCsndr HDGamerLewis HDarcticus +HEAD TURNER HEADLlNES HEAVYWElGHT HEAVYWORK +HEJNUS HEL1O HELPPOLOTO HELl0S +HEMSKl +HEMULIN LADA +HER0X HEREforPETS HERYWERNASDA +HEWlTT +HEXISZ7N510Q +HElMDALLR HElSENBERG +HFH141 HGCduke +HGHZ HHans +HI IM XP +HI lM SATAN HICK +HIHIHl HIKI VALUU +HIM thespaz +HINEaKIN +HKD HL8ight +HM-O3 +HM01Urself +HM01Yourself HM02YouFools HM05 +HM05 Flash +HMFIC +HMR9 +HMS Bass +HMTickle +HMWRCKR +HO NK +HOB0MAN +HODL DEEZ HOKIE +HOKIE II +HOLDUP +HOMIE_SNKE HOOD HOOLlGANS +HQ140 +HR palvelut HRVRD +HRZ Dennys +HReversti HT Hero King +HTKBeast HTTP HUGE +HULKSMASH +HULL CI TY +HUMANATSIGHT HUMPING HUUTIS HVSG73373535 +HWFG Jordan +HYDROPWN1C +HYPEHYPEHYPE +HYPERTAIKURI +HYPOXD +Ha Tsjoe +Ha Yea +Ha rrison +Ha ss +Ha1fWayCrook HaClintondix +HaKooro +HaMwise HaNamer Haaaa Haaaydeez +Haar-Xil-MES +Haarde Knud Haardest Haarvey Haavard Habaneros +Habbitatt Habib HabsWin2021 Hachune +Hacien +Hacis Zone +Hack McGraw +Hackdash Hacked +Hacked Here +HackermanJS Hackett116 Hackie +Hacklang Hacky +Had Enough +Had2hurt HaddlingOS Hadeees Hadei Haderlumpen Hades +Hades m8 +Hadezzz +Hadhod46 +Hadies205 +Hads MC +Hadyen +Haelendur Haell +Haemogobl1n +Haertyew Hafco Hafcos Hafdis @@ -9241,22 +19142,42 @@ Hagaar Hagedis Hagenau Hagenees +HaggisChaser +HagridGone Haha +Haha noob +HahaBonk HahaYes Hahaha +Hahalord888 HahnSuperDry +Hahru HaiDiLao +HaiHai +HaiIZaros Haiaf +Haiden Haidynn Haighy +Hail to Pitt HailYeah +Hailie Jade +Haio Hair +HairNotFound Hairy +Hairy Batman +Hairy Dery +Hairy Hobbit +Hairy Hooker HairyCave +HairyGirls76 HairyLatino +HairysJungle Hairyteddybe Haissi20 Haiten +Haitze Haizet Hajduk Hajj12 @@ -9265,28 +19186,49 @@ HakGwai Hakafissken Hakala HakanTheMad +Hakaniemi +Hakattu Hakeem +Hakkie Hakkua Hakozuka HakunaWHO Hakuryuu Hakwai +Hal Jordan +Halaal +Halal 1 +Halal Burger HalalSnakbar +Halaladdin +Halbrand3791 +Halcony +Halcyon Myth +Haldir Haldir140 +Haldun Hale +Hale End Half Half Volley +Half a Cig +Half a Worm HalfAb0rted HalfHawaiian Halfdanger Halfway HalfwayOkay Haliax +Halibelle Halipatsuife Hall +Hall of Fame Halla +Halla-Aho +Hallako Halleloja Haller +Hallo Knul Halloman71 Hallonkram Hallowed @@ -9294,74 +19236,156 @@ Halls104 Hallucianter Hallucin8d Hallufauz +Halluusio Halo HaloMisfit +Haloboy Haloking176 +Haloman6666 Haloo +Halseys Halsly +Haltrek +Halujo HaluunKeksin Halve +Ham Dip +Ham Turkey +Ham r +HamHawk +Hamada +Hamaken Hamataka +Hambam55 +Hamburgor Hambzy +Hamdulilah Hamed +Hamel Hamii Hamis +Hamlee +Hamm HammZ Hammer +Hammer Man +Hammer4422 Hammer4442 HammerTime29 HammerTine Hammered +Hammertime Hammond +HamnerTime HamoodyShimy Hamp +Hampton Bays Hampus +Hamrocks Hamsterslayr +Hamstr Hamudiy +Hana the Mad +Hanashee +Hand Puppet HandTuggy Hande +Handecapped +Handex Handicap HandleofJD Handley Handphone Hands +Hands Hurt Handsome +Handsome Rob Haneet +HanekawaSimp +Hanfkeks Hang +Hang em high HangChowCrow Hangin +Hangin Nuts Hanhen +Hani +Hanikala +Hank Jackson +Hank T Tank +Hank343 HankTheTank2 Hankanini +Hankk1 HankoAJ Hankzilla Hannah Hannh +Hannibal GIM Hanno Hannu +Hannu Poika +Hannu Soolo +Hannys Main Hanoi +Hanoi Rocks +Hanoob btw +Hans Glans Hansen Hansern +Hansiil +Hansonville Hansy +Hantarded Hanwi Hanzino HaochengZ Haole Haphazzardz Hapoton +Happ1RS Happier Happiikhat Happy +Happy Beluga +Happy Dappy +Happy Feet +Happy Josh +Happy Kitty +Happy Light +Happy Meal +Happy Prayer +Happy Tj +Happy exSlut +Happy2DaCore Happy420 +HappyMeds HappyPandaXD +HappyScape +Happydud01 Happyfrog12 Happyguy +Happypurpday +Happytoy +HapuApu Hapukurk HarKieren +HarO Reborn +Hara YEP +HaraHachiBu Haraket Harambe +Harambro +Harash Harassment +Harbix +Harbor 2567 Hard +Hard Chance +Hard Clue +Hard Filmur1 +Hard Kinta +Hard TeK HardFormed HardHatJeffy HardMannetje @@ -9370,13 +19394,22 @@ HardRazer Hardc0reBruh Hardcome Hardcrux +Harde Pik HardeSnikkel +HardenedRS Harder +Hardeschijf Hardie +Harding Hardlesas Hardman +Hardon hank +Hardstyle IM Hardwaring +Hardwell420 +Hare Danger Harem +Harem Isekai Harja Hark Harka @@ -9384,122 +19417,236 @@ Harken Harken21 Harlekin Harlem +Harley Nz +Harleyrox +Harlie Harlot Harm Harmala Harmentje +Harming +HarmlessTwig +Harmon Angel +Harmoniiumm Harmonized Harmony +Harmonyy Harmr Harms +Harms Whey +HarpoonMyAss Harraggen Harresvela Harri +Harri Hylje Harriganrace +Harris0n Harrithon +Harrods Fish Harrris Harry +Harry Bucket +Harry Dirty +Harry Hendo +HarryPoppa HarryTheGOD HarryTheWhte Harryalt +Harryguy23 Harryindacut +Harses +Harsh Times Harshhashh HartIess Hartlepool Hartree +Hartreni Haruka +Haruka Meh +Harus Ranger Harutikk Haruto Haruuki +Harvahammas Harvardista +Harveytec +HaryLongWood Has2BeSHiFtY +Has547 +HasOneLegacy Hasballa +Hasbullah Hasek Hash +Hash Browns +Hash House +Hash One M8 +Hash katchum Hash1 +Hash1Aussie HashHund HashIsLife +HashTagYou Hashh Hashiiirama +Hashimm +Hashlife HashtagGOALS Hashtagz +Hasloa Hass +Hassall Hassis Hassoni Hastings +Hasty Power +Hat i +Hat tis HatchetOG +Hatchkat17 +Hatchling +Hathrow HatiFnattt +HatoradeJack Hats Hatsune +Hatsune Miko Hatsy Hatte +Hattibagen Hattnn +Hattuviilari +Haubjerg +Hauki0nFive Hauki0nIron Hauki0nNoob Hauki0nUlti +Haunleff Hauntedfury Haunter12123 Hauntya HausHausHaus +HautaNorsu +Hautboi HavU Havac +Havard Havawk Have +Have Sabr HaveAGood1 +Havendare +Havenmeester +Havi k +Havidex +Havoc Grasp HavocRavage +HavocThomas Havok Havottaja Havzzter +Haw +Haw4iiankush Hawaii +Hawaii Ice HawaiiMadez Hawaiian +Hawasser Hawes Hawk +Hawk Driver Hawkear Hawkes +Hawkeye87 Hawkit HawkofLight HawksMama +Hawkwound +Hawkzrael +Hawler12 Hawolt +HaxY Haxd +Haxident +Haxixero Haxn Haxnoiz Haxoonie +HayHay Hayabusa +Hayaku Hayasaca +Hayasaka +Hayboo Hayden3 +Haydenl451 Haydenss +Haydern Haydor Hayesy Hayfield Hayirlisi HayleyQuinn Haylz +Haynex +Haz-zy +Haz2 HazDownz Hazade +Hazardless Hazardouss +Hazards Haze +HazeCloud99 +HazeMePls HazePGN Hazed Hazeley +Hazezor Hazla Hazsle +Haztraz +Hazy Sparrow HazyHerb +HazyHour HazzFive +Hc OffWhite +Hc Oh Wait +Hc Toleranss +HcFlex004 v4 HcGon HcHoopla +HcimTironade Hcimdiot +Hckie +He Adventure +He Pinky +He Who Iron +He nry He11zdone HeSmokesBud Head +HeadBear HeadHuunter +HeadOverseer +Headache +Headenforcer Headgaskets Headleya +Headliners Headlines +Headlines v2 +Headshotting +Headwipe +Healers +Healty Heard +Heard Chef Hearne +Heart Please Hearted Hearten +Heartlesdude Heartlock Heartquake Hearts @@ -9511,154 +19658,299 @@ Heat HeatSeekr187 Heated Heathen +Heathenry +Heather x3 +Heatmyser HeatproofIM Heav7n +HeavenIyGard +Heavener HeavenlyBlue Heavens +Heavens Feel +HeavensDao HeavensStorm +Heavensdown Heavy +HeavyBowGun +Heb0 +Hecec Heck +HeckIron +HeckinWoofer HeckingFish HecklerNKoch Heckstrm Hecote Hectic Mic HecticGinger +HecticHerb +HecticKebab +Hectoplasma Hedge +Hedralx +Heebie Heedbo Heee Heel Heeling +Hefboom HeftyFlan HegXDXD Hege Hegelund Hegert Hegesy +HehtoLerssi +Hei Kneuter +Heifetz +Heightenings HeikkiPentti Heil +Heil Pierce +Heil Vegeta Heilios +Heill Ragnar Heinamies Heineken +Heinekentje Heinered Heinzzel +Heir HeirHead +Heisbergh HeisenBergW +Heisenber9 +Heist Music +Hej hej +HejBrink +Hekaton Hekdik Hekla Heko +HektikBadger +Helbur Heldip HelemaalMooi Helesta Helium +Hell ETC +Hell Kitt3n +Hell ffa HellAngel HellBlood Hella +Hella Tonk +Hellabad Hellafly +Hellagaybtw Hellandnz Helldog946 Hellhaunted +HellianV Hellinferno4 Hellixx64 Helllblazer +Hellmo Hello +Hello Bel +Hello Friend Hello6 +HelloBot9000 HelloDottie Hellodummy Hellrain962 Hellrazorr +Hells 10hp +Hells Chance +Hells Godz +Hells Puppet +Hells doggy HellsRavage2 +Hellwater Hellz Helm Helmoid Help +Help Autism +Help I Gay +Help my +HelpImStupid HelpLahh HelpTheNoobs +Helpful +Helpless Ale Helson Ryse Helta9 Helx +Hema roids Heme2 HemeSupreme Hemiptera Hemmii +Hemmur HemoGlobe Hemp +Hemp product Hempopotamus +Hempwick Hems +Hen Ac Araf HenaQ +Henbane0 +Hendo Au Henee +Henehh Henfami Hengecobdig +Hengggga +HenkDeTanker HenkdePlank +Henkka Btw +Henkka242 Henkkawaa +Henkkiiieee Henkleebruce +Henko420GB +Henktius Henlo +Henners Hennesssssy Henni Henniejj Hennssey +Henri380 +Henry Fe +Henry XV Henry14 Hens +Hensel +Henslord +Hensta +Hentai Daddy +HentaiMaiden +HentaiMusic +Henu OG +Henzone58 Heolis HephaestusRS +Her Gay HerAddiction Herb +Herb Deen +Herb Lab +Herb Quest +Herb box Herbacist Herbaderb HerbalKing +HerbalTeabag Herbalicious Herbby Herbilicious Herblore Herbmania +Herbmatic Herbogus +HerbsnSpicer HerculesLoyd Herculooo HereFor_Beer HereSomeDank HeresALlama HeresySlayer +Herk +Herkko +Herkko32 +Herkku Herkules Herky Herm10ne Hermanni +Hermaus M +Herminator0 Hermit +Hermit Jack Hermitian +Hermot palaa Hero +Hero Extreme +Hero Kid +Hero vs Hero HeroDan +HeroGenos HeroToby Heroed Heroic +Heroic Hope HeroicDesire +Heroicjesus +Heron Bird Herp Herpa HerpaGnome HerpesNo Herpesbek +Herpito +Herr Gaucho +Herr Luc Herra +Herra Beavis +HerraBonsai Herrits +Herrmann3 Hesienberg Hesitation +Hesmander Hespori +Hespori KC +HesporisSeed Hespus Hess Hesson +Het Heden +Hetdorp +Hetebeir +Hetehaan +Hetimos +Hets Capture Hetumo Hetzer Heuha Heur +Heuro Heuvel +Heuvel Reus +Hevenlys Hever Hevi +Hevi Luumu Heving +Hewy +Hex Is Maxed HexMage Hexadecimal +Hexagon Heat +Hexalogy +Hexedited Hexenblut666 Hexenkonig Hexication +Hexos +Hexphase Hextale Hextra0rdnry +Hexun Hexxjan +Hey B +Hey Bob +Hey Cheems +Hey Im Dylan +Hey J +Hey Jase +Hey Jay +Hey Mills +Hey Ubba HeyBeautiful HeyBigDaddy HeyDaddy @@ -9666,42 +19958,103 @@ HeyFonte HeyHowsLife HeyItsLachy HeyLuffy +HeyThatsLife +Hey_Duck +Heymakerz +Heyman Heywaddup +HeyyDivine Hezbullah +Hezr HgH2 Hhmm45 Hhmora +Hi Cookie +Hi Im Ant +Hi Im Duncan +Hi Im Emil +Hi Im Frak +Hi Im Ken +Hi Im Pei +Hi Im Stevo +Hi Im Vitao +Hi ImMrRight +Hi Lvl Ideas +Hi Opal +Hi Ren +Hi Suka xD +Hi Tyler +Hi im Gin +Hi im Savage +Hi im Shar +Hi im Yellow +Hi lm Paul +Hi lm Sk8 HiDyvvnBDP HiGHFLYER +HiHowAreYa HiImIronRick HiImNicole HiLumbridge +HiNebb +Hiarii Hibbetts +Hiben75 +Hibernal Hick Hickery Hicu Hidaki Hidden +Hidden Power +Hidden one1 Hiddenn +Hiddinkiwi Hiddy +Hide Ink 207 +Hide Ya Kids Hidekia Hideo +Hideopenend Hider HidesHerEyes +Hidi Hidole555 +Hidro Hieroglyfic Hifter13 Higgens High +High Content +High Halpert +High Hustler +High Knight +High On Cake +High Ronnie +High Score +High Snorse +High Up Here +High as Zuk +High lm hi +HighAsF Bruh +HighBacon HighMeatloaf HighNoobJhin HighOnPlants HighProbably +Highbury Highcaalibex +Higher Force +Highestarchy Highfish +Highjacurmum +Highland +Highly Faded Highmountain HighonCash +Highs Highscaping +Hightierian Highway2Hell Higlen Higu @@ -9709,144 +20062,253 @@ HihoMenono HiiddeN HiipFiire Hiisgreat +Hiit Man Hiiz Hijack778 Hijsbergh Hiker Hikiukko Hikizato +Hikmet +Hilarious +Hilda Garde Hildr Hilge +Hilipilli Hilk +Hillhouse +Hillpker Hillram HilltopHick Hillzy Hilo +Himala +Himaster +Himtheguy +Himy +Hina Suguta Hincarpie +Hinchers Hindi +Hindle Hinny +Hinss +Hintai +Hiopeer +Hip Fe Hop +HipSlippers Hiphop Hiphopdude0 +Hipiguy48 Hipnodiskd4 Hippeis HippieLexy Hippies +HippoBlunts +Hiqhlife Hirae2 Hiria1 Hiroble Hiroticus +Hiroyuki Isa +His Faithful HisHungness HisLordship Hisano Hisblore +Hislordship HisokaX4 Hispeeed +Hissi-Timo +Hit U +Hit By Car +Hit Points +Hit The Guam HitMyVape HitOnRun +HitOrange HitTheVape Hitagi Hitch350 Hitchens HitherDither +Hitman Style +Hitme8 Hitmonchans Hits +Hits Like +Hitsumaru Hittimestari Hitz +Hiva Hiya Hiyouri HjaIIe Hjaldr HlKEN HlMBO +Hladomor +Hlata Hldz Hlep +Hlnub +Hm +Hmg Hawj Str +Hmm Fr Bruh HmmKoekjes +Hmmer Hmmingbird Hmmk Hmmm +HntrBTW +Ho Chi Meme +Ho LiFuk HoButter HoFkee +HoLeShite HoarderMan +Hob Ralford +Hobbi Hobbit +Hobby Jogger Hobex +Hobgoblinas Hobgoblins +Hobgrot Hobie Hobo Hobodude67 Hock Baws +Hockney Hocky Hocpuck +Hocus POTUS HodamOS +Hodeman +Hodge5 Hodgetwin Hodort Hodvik Hoffmanator +Hoffmanbmx Hoffsworth Hofus +Hog HogPacker70 +Hogboar +Hogboy Hoggormen +Hognag Hogo Hogsen Hogskoleprov Hoheti Hohhenheim Hohhoijjaaaa +Hoi An Hoilam Hoix Hokage +Hokage Jason +Hokage Sama HokageRS Hokiako Hokie +Hokiee +Hokies HolaBurrito Holbox Hold +Hold My Gun Hold3nMc +HoldMyShrimp +HoldenBallz Hole HoleNewName Holenes Holidayz Holiest +Holiidayyy Holisti Hollar Hollington24 Hollow +Hollowed One Hollsyy +HoloTheDrunk +HololiveOS +Holoubek Holsey3126 +Holt +Holtsen +Holunder Holy +Holy Cheetos +Holy Druid +Holy Jandals +Holy Moses +Holy Plan +Holy Rock91 +Holy Scrotum +HolyChrist HolyColt HolyDugong HolyElixir HolyEntity HolyGhost HolyHerb +HolyIronmoly +HolyMould HolySaints HolySkittles +Holycaw Holyfuk Holyhonza Holykana Holyshmokez Holyzuk Hom3r +Homage48 +Hombelkei Home +Home Boy +Home Office +Home Page +Home Plug +Home Run26 Homealot +Homebad Homefront Homegrowe Homelander Homeless +Homeowner Homepage Homer +Homer LT 0_o Homestead Homicide Homie Homies556 Homingstats Homlepung +HommeDeFer Hompski +Hon Honaz +Honchcrow +Honda Coupes +HondaXJ20 Honden +Hondo Ohnaka +Hondsvot Honest +HonestThomas +Honestben +Honestidade Honeytrippin Honeyyyy +HonkMyClussy Honket HonkeyKong Honkitonki1 @@ -9854,37 +20316,61 @@ Honko Honkys Honler Honor +Honourable Honq +Honra Honru +Hoo Lee Fook Hooba Hoobloob HoochFighter Hood +Hood Rat HoodBrothers Hoodaloo Hooded HoodedDeath Hooder Hoodieninja +Hoodless +Hoodlum_94 Hoodrat +Hoodstar XD HoofHarted +Hoogbegaafd +Hook +Hook N Arrow +Hookah Hookin4GP Hookr Hooleys +Hooofer Hoooka HooorrraaaH +Hoop Snake HoopaLoopz +Hoopdie Hoopre Hoopti Hoorus +Hooryu +Hootenanny +Hooyaah Hoozio +Hop Loser HopNowNoob Hope Hope4TheBest HopeSmolDicc +Hopeless +Hopelite22 Hopeu98 Hopian Hoppa +Hopper727 +Hoppip +Hoppipolla +Hops World Hoptilicus Horatio Horatioat @@ -9893,27 +20379,60 @@ Hord Hordalad Hordaland Hordelli +Horey Horizons +Horizons End +Horme HornDawgx Horned Horns +Horny4Herbs Horny4Hunlef Horozu +Horppi +Horrific Rat Horriser +Horros +Horrow jr Horse +Horse Tock Horselord +Horshock +Horsley park Horstel +Horus Hyla Horus1701 HoshizoraRin Hospitaliano +Hoss +Host Proctix HostileBoss +HostileCloud HostileEx Hostiles +Hot Ass +Hot Box +Hot Boxing +Hot Chesters +Hot Choco +Hot Chook +Hot Dog 1995 +Hot Dog Guy +Hot Girl +Hot Glacier +Hot Gril +Hot Hemp +Hot Shop +Hot Since 82 +Hot Stepdadi +Hot nurse HotAsianCuti HotCocoa HotCuppaT HotDoggWater HotManCurry +HotMaxCurry +HotPud HotSaus123 HotSnow Hot_Farmer99 @@ -9922,180 +20441,342 @@ Hotandhorny Hotbox Hotchelli Hotdog +Hotdog Timmy Hotdog655 +HotdogGravy Hotdogit101 +Hotdogwhat Hotel Hotkeys +Hotline Juan +Hotot +Hotputhy +Hotrod-Matt Hots Hotsbo +Hotse Hotsgonwild +Hotshotz61 Hotslol Hotwheeler Houdinski Houndstooth Houowvwvv +Hourlies +HoursAndy Hous House House748 +HouseSniffer +Houseman45 Housewife +Houston713 Houstoned Houstonnnn +Hovis +Hovland Hovmeizter +How do I win +How to quit How2Boss How2username HowAboutNeup +HowDoDisWork +HowHardd HowIing HowIsDis +HowLee +HowSway Howde Howland +Howler Head Howlini Hows +Howsey Howson HoySmallFry +Hoya Markus +Hoyaa Hoyah Hoyiron Hoyryjyra +Hoyyehh +Hp x Hp +Hr Banan4 +Hr CarlSmart +Hr KalZ +Hr Pagulane +HrMystik +Hra Amiraali +HraMajuri +Hraerekkrr Hrafnagud +Hrag +Hrathix +Hrry Hrungiir HshBrwnClwn +Hsilver +Hska HsrFresh +Htine +HuZ Ryan Huaraaturpaa Huard Hub3r +Hubbbzzzz Hubbz216 Hubeeb +Hubie +Hubiera Hubli +Huby K +Huck HuckUsAHandy +Huckn +Huddo Hudsy Huebs Huevote +HueycoatI +Huffers +Hug A Mudkip +Hug my cat Hugakitty Huge +Huge Coom +Huge Mudkip +HugeCcret +HugeCox HugeMike HugeSimp HugeSquanch +HugeXpWaste Hugh +Hugh Jannob +Hugh Jas Hugh Jazzhol HughAreMyron +HughJastle +Hughes Luck Hugo +Hugo Baws +Hugo C Hugodzilla Hugos Hugoslavic Hugotec +HugsTibbers Hugsi +Hugsqtface +Huhi Huhm0ng +Huhmble Huhu +Huidskleur Huiliuiliu Huilu Huinca Hukka Hulagu +Huler Hulk +HulkSmaash Hullcity25 Hulll Hulluke Hulluurpo Hulvatonta +Hulyx Human +Human Knight +Human Reject +HumanMalware +HumanSl0th HumanToxin Humanist Humanityy +Humanoid Rat Humb +Humb RS Humbabe Humberto Humble +Humble Finn +Humble Husk +Humble Otter +Humble RNG +Humble lp HumbleCanoe HumbleCrab +HumbleFarmer HumblePlayer Humblee +Humblegods Humbleherb Humblenobody Humbles +Humboy +Humgrump Humid +Humiliation +Humji +Hummbinger Hummerspeck HumperT Humpletics Humu +Hunajamurune Hundjagare Hundred +Hung Opossum +Hung Pikachu +Hung Zebra HungLow30 HungSolo45 Hungarry208 HungerRee Hungry +Hungry as fk +HungrySponge HuniePop Hunkadoris +Hunks +Hunlef Hunnets +Hunni Bunny Hunpy +Hunt Mike Huntarr Huntdragimps Hunter Hunter10139 +Hunter4056 HunterPandav +HunterXosrs +Hunters Main Hunterz +Huntin Specs Huntindawg Huntindawg2 Hunting HuntingGirls +HuntingPets +Huntinrox Huntinthotts +Huntiritox HuntnCoFTB +Huntsin Hunyadi +Huolon +Hupipelaaja Huppis +HuppuKostaja +Hups +Huqin Hurlae Hurleee Hurley +Hurley24 Hurlock Hurri +Hurrisun +Hurs 1 Hurtigmads HurtsDonut Huscarl +HuseG00SE Huseyin31 +Hush Pup Husker HuskerFool Huskieeeee +Huskvarna +Huskyskills +Hussar1683 Husse1n Husseinn Hustensaft Hustlez Huswan Hutchens +HutchoAU Hutros Huts +Hutula +HuugeCok Huugo35 Huule Huumepoliisl +Huupee Huutiset Huutoripuli Huviksee +Huxley King +Huxtap Huxtin Huzeyfe +HvH Hvale +Hvale Kongen Hvorfor +Hwael +HwbrangerUIM +Hwzrs +Hxc Ironfail Hxcmackin +Hxpeful Hxrm Hxrsey +Hy a Hy3RoGeN +Hy3RoGeN x HyAcey +HyDrooo +Hybernated Hybrid +Hybrid Hurtz +Hybrid Mech HybridSanta HydG +Hydi Hydr0nate +Hydr0p0nic Hydra +Hydra Ikkle +Hydra Spoon +Hydra_Lerna Hydraletics +Hydras Daddy Hydration Hydraxon +Hydrerion +Hydro-Quebec HydroBlast +HydroC +HydroGasMask +Hydrocarbons Hydroe Hydrofiner HydrosFather +Hyemi +Hyfens HyggeDansker +Hyi Hykd HylianLink +HylianLombax Hylkon +Hymy Hyosin +Hyough HypaDunkTv +HypaZestay HypeLad Hyper +Hyper 212 +Hyper Threat +Hyper autist Hypercam Hypercoaster Hyperdeath20 @@ -10103,68 +20784,310 @@ Hypermole Hypersomnia Hypertroll Hypertrophic +Hyperversity Hyphen +Hyphen-ated Hyphenated +HyphyRS Hypn0se Hypocriet +Hyprocrisy Hysteric4l +Hytrogod Hyttynen +Hyula Hyun Hyxbe +Hyze +Hyzers +I M +I Skilz I +I ADK I +I AM DROID +I Am Arun +I Am Calysto +I Am Cicu +I Am Dave +I Am Eugene +I Am Malenia +I Am Mathew +I Am Mizzou +I Am Times +I Am Vexed I Am Vono +I Am Xyience +I Am Yesac +I B Z +I Barak I +I Be Vibing +I Be Yankin +I BenJammin +I Bryce I +I Buy Bulks +I Buy You +I Call BS +I Cant Veng +I Chance I +I Chaz I +I Chop Life +I DanWise I +I Daniella I +I Decimate +I Descend I Dizz I +I Dont Gnome +I Dont Know +I Dont Weld +I Drink T +I Drive Jeep +I Duck Hunt +I ELITE I +I ET BBIES +I Emu I +I Enjoy Butt +I Faheem I +I Farm On Rs +I Flick Bean +I Gem I +I Genesis l +I Go Noob +I Gribben I +I Grind it +I H8 GAGEX +I Haros I +I Have Quit +I Heal DHers +I Herb Store +I Hunt Pets +I Hustle Man +I I ODIN I I +I JANGLER I +I Judgee Yu +I Ko U Lol 1 +I L0ve Lolis I LOTR I +I LV PEACH X +I Lezima I +I Liam I +I Liamz6 I +I Like Cake +I Like JoJo +I Lov3 Pho +I Love DILFS +I Love Kinja +I Love Kylie +I Love Muff +I Love You +I Luci +I Luhhya +I Luv tSwift +I M A P nuss +I M Ket +I M S N Y +I M The Weed +I Maxed OSRS +I May Be +I MoF +I Mograine I +I N D I A N +I Need 1M +I Need Succ +I Need aBeer +I Novato I +I Nz I +I OX +I Owning +I P0 +I P0KY I +I Parry I +I Peter I +I Pk In Monk +I Plank Lots +I Play Aegis +I Pod335 +I Pri +I Q T I R N B R U +I R O N 99 +I RC +I ReAPeR I +I Roll Need +I Ron Man +I Ruin Holes +I Run East 2 +I Sharted +I Smiteyou I +I Smoke Irit +I Specs I +I Spied +I Strangles +I Taka Hujit +I Teller I +I Tricky I +I Tuscan I +I Valknir +I Vape Lube +I Viral +I Want 60FPS +I Would Rage +I Xl I I Xl +I Yogurt +I Yoshitsune +I am Anyone +I am Bryce +I am DB o +I am Elk +I am Future +I am Glynny +I am J M E +I am Jedi +I am Niels +I am Nyheim +I am Olive +I am Ry +I am SHODAN +I am Saitama +I am Shiny +I am Shogun +I am Simon +I am Soloing +I am Twiggy +I am a wreck +I am aRusher +I am drunk +I am groot B +I ate +I bad Guy +I desire God +I do be Iron +I eat peach I h8 farming +I have egg73 +I have poon +I have rng I ll fail +I love me +I love yew +I m Dave +I m Kenpachi +I m an Angel +I matchjad I +I mpling +I n b 4 +I ndy +I nspire +I rvin +I sak +I smell zaza +I so pale +I squared R +I t I s +I tbag cows +I used to Rc +I van +I vinrox +I w4ste xp +I wana dew u +I want wings +I-IEEBO +I-Iulk I00OOOOOO00I +I2P +I2m +I2ocky +I2ossiiii I3ET I3WANA +I3ooth +I3ow Hunter I3ox I3rucex I3ubbles I3ulow +I7I +I7iablo +IA +IAM HARDWELL IAMBillNye +IAMDouble_C IAlwaysBurn IAmArcade +IAmArchangel IAmBabyYoda IAmBinx IAmEcliptic IAmFaptastic IAmFrampt +IAmJacbo IAmRichard IAmSlimShady IAmStyle IAmUnbound IAmWaffles +IAreTazz IB4I +IBB Baskani IBIoodRose IBaIance IBangBBWs +IBardak +IBloodwing +IBuyGF5GP IBuyPowers +IBuyShungite +IC 3 +IC XC NI KA +ICE GIANTT ICNK +ICantFit ICauseRage ICrazyCamelI +ID theft IDEPOCIEBIE +IDSilver IDark IDiabloI +IDustie IEATEDYU +IFALL3NI +IFIFIFFIFIF +IFIFIFIFFIFI +IFIFIFlFIFIF IFRC IFRS +IFRS 9 +IFartOnBaby IFernedYou +IFistBonk +IFoundABaby +IG0R II IGN0RANCE IGoogledIt IHQueenI IHasHips IHaveAWifey +IHaveChicken IHaveToQuit +IHobbitI +IHopFromNo1 IHuntKoalas +II Fabi II +II Gots Piie +II Mossy II +II TurMz II0III II0v0II IICyRaNoKII +III SLAYR +III jin III IIIBCIII +IIIGavinIII IIIel0n +IIIusionist +IIKOO +IIPAC IIPrincesaII +II_Blanx_II IIamaman IIflemishII IIlIIAS @@ -10174,24 +21097,119 @@ IIlllllIIlIl IIndy IIrisviel IIsaac +IIx Link xII +IJzer Bal IJzermeneer +IK Pegasi +IKotol +ILL M1ND ILLUMINATIS ILOVEUBRAT +ILVI ILike +ILikeKorone +ILizzy +ILostMySock ILostMyTalk ILoveAstolfo ILoveSeaFood +ILoveYasmin +IM Adept +IM BLUE DA +IM Bazlish +IM Big N8 +IM Bjakke +IM Bolle Ui +IM Butchh +IM CSI +IM Cares +IM Chaudoin +IM Corita +IM Dahak +IM Damy +IM Dislectyc +IM Dodgypig +IM Donactro +IM Drone +IM Dutch Dog +IM EL Clawo +IM Envy +IM Erlandu +IM GERRALD95 +IM Gekko +IM Gokhan +IM Guilty +IM HEEM +IM Hail +IM Harnas +IM Hulkeen +IM Infested +IM Jap1 +IM Jenskee +IM Kat +IM Knol +IM Krona +IM M U R P H +IM M0A IM Maccy +IM MajorRat +IM Maninja +IM Musa +IM Noddy +IM Ong Gia +IM PVM BRADY +IM PapaBless +IM Peach Man +IM Pepekage +IM Perp +IM Phubz +IM RICO_1 +IM Rampage +IM Reiner +IM Rome +IM Ruinscape +IM ST0NED +IM Sebaa +IM Soad +IM Spooned +IM Super AFK +IM Tank OG +IM ThiccSucc +IM Tipz +IM Toon +IM Walnut +IM Witt +IM Zoot +IM a pansy +IM blazeit +IM sanderve +IM spen IMAEATURASSS IMAFKNNONCE2 +IMGOKU1 IMHankey +IMHky IMJeffG +IMMezzo +IMNagrom +IMPERlO IMPlayerjohn +IMSOULSHADOW IMSausjegeit +IMSkrt +IMWaldorf IM_Queeffing +IMa Planker +IMakeUBegKid +IMevil yoshi IMissNieve IMnotQ +IMoIVoxide IMsmits +IN A FERRARI +IN PRISON RN +INCEL839273 +INCreate INDICA INFERNALMAX INTERMEDlATE @@ -10199,130 +21217,249 @@ INYOURTS INeedABump IOHBOY IOnSpacezI +IP6 IPkdYourBank IPlayForPeso +IPlayHigh +IPonderosa +IProGuthix IPumpkin IPunchKids IQUICA +IR Hardcore IR0N +IR0N BOND IR0NMAN +IR4Q +IRL Femboy IRON +IRON BYRNS +IRON DlOXlDE +IRON NOT HOT +IRONMAN ADO IReallyLikeU +IRework IRidePipe +IRoldy IRowForUCD +ISAPOOPS +ISO PEE ISOMAN12 +ISQQC +ISTRA +IScottGame +ISjorsI +ISmokeABit ISoLaTIIon +ISquirk ISuperStarI +ITIB +ITIISERY ITIOMME ITIace ITIaddy ITIagicka +ITIagicks ITIajestic ITIallen ITIasKilleR ITIassacre +ITIatty ITIerica +ITIiko ITIoj +ITIoosh ITIr ITSPYRO +ITV X +IThe Beatles +ITrimGlories +ITurtlekunI +IUR IUntradeable +IV Luke +IV skin +IVI V G IVICMXCIII IVIE0W IVIacaroni IVIaybe +IVIeesa +IVIeredith IVIesprit IVIetallica IVIidget IVIooN +IVIowlzy IVIugginz +IVIush IVIxtthew +IVOXYGEN +IW Lytheria IW4M +IWGP +I_Eat_Ass04 +I_Inity +I_Noodz_I +I_make_noise +Iacto Iaculch Iaffan Iafs +IaintHiding +Iam Bald IamAjewBoy +IamBowser IamBruun IamCheesin IamCrazyBoy IamDuru IamErect +IamGossip IamNSFW +IamNotHodor IamRichPutin IamSneak +IamThaLiquor IamXerxes +Iambadhaha +Iamcruxer Iamearth Iaminsanemax Iammooted Iammtpjr Iamstepbro +Iamthestars +IamthyPope +Ian Beale +Ian Rush IanT Ianalan Ianbird Ianeke Ianeke4 Ianyaboii +Ianz +Iax 2000 +Ibanezx88 Ibanezx99 +Ibans Fe nix IbansPheonix Ibarbo +Ibb +Iberis +Ibexleave Iblushh +Ibn Ibrahimovic +Ibugppl Jr +Ibunaaru Ibuprofen800 IcEyCuDa Icanfixthat +Icarius Fell IcarusRS +Icaruz Icculus1 +Ice 9112 +Ice Barrage +Ice Caves +Ice Gengar +Ice King +Ice clap +Ice giants Ice in Vodka +Ice5566 IceBarraging IceCreamDog IceDesert +IceFoxZero IceH +IceIceChooky IceNineKiIIs +IcePrisonMe IceSparro Iceb Icebeam Iceburghomie +Iced 0ut IcedOutDrip IcedScrabble Icedeadmage Icee +Icefirezz Icehound Iceid +Icejawa Iceland Iceleag Iceliang530 +Icelight +Icemonkeyz +Icen Icesoze Icespeller +Icetaylor Icey +Icey Lunaris +Icey M Iceyou90 Ichi Ichi6an +IchikaNagano Iciclez +Ico n +IconPara +Iconiic Iconoclasmic Icookpeople Icoz IctCat +Icy Duck +Icy Tires IcyFear IcyTowerr Icyene +Icyene Hero Icyenicblood Icyflowers Icyx +Id Tele Too +Id Yak It Idaho IdahoTaters IdcGoAway Idea +Ideaal Ideekay Idepredad0rI Ididit33 Idk Why PvM +Idle GE +Idle Melvor IdleWhale +Idlibi +Idna Supafly +Idol Namib Idont Idontlikejad +Idopk1 Iecysoda +Ienjoisk8ing +Iern +If I Succeed +Iffi Iffyz +Igge +Iggy Ontario Igloocold +Igmere Ignace Ignent +IgnisDraco22 +IgnobleSolid +Igor Krutoy +Igor Mang IgorBogdanof Igorr Igot99failin @@ -10332,87 +21469,261 @@ Ih8myRNG Ihan Ihana Ihme +Ihnigmakage IiIy +IidaEmilia +Iilqtforeva Iimel IisRaDiO Iisalmi Iivomon Ijoinedthis Ijusheadshot +Ijzer tekort +Ik Geef Bon +IkBenWeg Ikastovizski IkeJEI Ikhela Ikillu247 IkkeVincent Ikkle +Ikkle Hydra +Ikkle v Pain +IkkleHorvick +Il +Il MrBorn lI IlIBooieIlI IlIIIIlIIIlI +IlIIlIllIlII IlINard0IlI IlRisklIlIlI +Ileeze Ilija +Ill Ko You +Ill Effect Illbeyourcat +Illegal Char Illest Logic +IllestEver +Illinoisan +Illithid69 +Illlenium Illumee +Illuminatorr IlluminumRS +Illusionist +Illusivezz +Illustration +Illuzory Illwil +Illyrian +Illyrian TSX +Ilmer +Ilotalo Ilovethewar IlpOG Ilsaldur Iltasanomat Iluredyou +Ilusm +Iluvahrim +Iluvitar Eru IlyrianBlood +Im 85 Slayr +Im A Saint +Im Am Die +Im Ami +Im Anabolic +Im Annoyed +Im Artur +Im Ash +Im Asking +Im Aspergers +Im BackUp +Im Baguette +Im Barlow +Im Behemoth +Im Benough +Im Blastoise +Im Bo Licht +Im Brills +Im Burnz +Im CG +Im Chal Im Christian +Im Courage +Im Dino +Im Dr Afk +Im Easy Exp +Im Elyk +Im Excalibur +Im Fabulous +Im Fever +Im Finnish +Im From Jax +Im Gainz +Im Gippin +Im Gutfor +Im Hawkward +Im Hersh +Im Huck +Im Hunta +Im Hussain +Im Iron +Im Iron WTF +Im Jags +Im Jokers +Im Jovian +Im Just Ken +Im Krazy +Im Kyle Btw +Im Legacy XD +Im Los t +Im Luis +Im McGriddle +Im Missle +Im Moist 4 U +Im Moore +Im Mr Josh +Im Nate +Im Nathan x +Im Newschool +Im Nice +Im Not Okayy +Im Not lron +Im Nzmitch +Im Off Chops +Im On A Yak +Im On Point +Im Only +Im Orc Im Outt +Im Pogi +Im Qwerty +Im Ron BTW +Im Rus +Im Savage +Im Scoob +Im Secor +Im Shambles +Im Single AF +Im Smexy +Im Snake A +Im So Vayne +Im Songs +Im Spirit +Im Stig +Im Symb +Im Tainted +Im Tame +Im Temppay +Im Terrible5 +Im TheBeast Im Tibbz +Im Travis +Im Triz +Im Tyl3rr +Im Whey +Im Ya Papa +Im Your Babe +Im Your Dad +Im Yui +Im Zac +Im Ze 0wner +Im alex btw +Im just Cody +Im not FBI Im relapsing +Im tall af +Im wokeup +Im-Crowess +Im2good4u2nv Im45defence +Im4everlucky ImALilPigBoy ImASthhnake ImAdam ImAl0ne +ImAn Ironman +ImBaldFromRS +ImBobbyrayj +ImBoredOfRS ImCharky +ImChuckBass +ImClueless ImCravenTim ImDaPlugLLC ImDaved ImDaviie +ImDirtyyyDan +ImDoctaWhom +ImEmilyy +ImEric ImFinnish ImFlizz ImGodd +ImGodly ImHavingFun +ImHellaHigh ImHighASFSry +ImHisBae ImIncredible +ImInfested ImIntense +ImJames ImJebbe +ImJinxed +ImJordon ImJustLonely +ImJustRaging +ImKnotSimple ImLarge ImLeeuwarden ImLikeRlyBad +ImLukesGIM ImMAdBro +ImMajesticAf ImMaxy ImMilky ImNewbie +ImNoobK ImNooblit ImNotAfriend ImNotHumble +ImNotLost ImNotThien ImPaul +ImPaulAlt ImQuorra ImRyboy ImSane ImShreksDad ImSixteen +ImSnoop +ImSoGodlyy ImSoVulgar +ImStormmm ImTaegan ImTayla ImTinyRiick ImTipsy ImToFrosty +ImTooGucci +ImTwisted +ImVanilla +ImWargasm ImWilbur ImYourDadBTW ImZe ImZorp Im_Stone126 +Ima Guy +Ima Lil High +Ima Maleman +Ima lron man ImaCraftHor +ImaMainbtw Imack Imafore Images @@ -10420,17 +21731,33 @@ Imaginable Imagine Imakuni0 Imalooter +Iman103 +Imangry20 +Imanity +Imanubnoob +Imar Pussay Imasecretspy Imasin Imawizardm8 Imazamox Imblim +Imblim Area +Imbrochavel +Imbue +Imbued Haert +Imbuing Imbune ImeshuggahI Imgrazy +Imhellgracio Imidril +ImiteBurDADY +Imitus +Imm Mad Bro Imma ImmaSkill +Immaturity +Immediate W Immense Immer Immerseus @@ -10439,60 +21766,126 @@ Immortal Immortal91 ImmortalK12 ImmortanMike +Immxnse Immys +Imnotahuman +ImoChase +Imoinu +Imotay ImpactPewPew +Impale Her Impared Impeccable Impedance +Impede Imperdoavel +Imperfecto Imperfekt ImperialQc +Impietyy Impish +Impish Ace Impishhh +Imposter Jon Impriznd Improv +Improved +Impulsive Au Impurest678 +Imql +Imre Imsain Imsokwtie +Imstratss +ImtheAnimal +ImtheCARRYv2 Imthick Imtoob +Imuhbeast +Imuripieru Imus +ImxricK +In Game Life +In Menu Andy +In My Shadow +In Recovery +In Seconds +In2cept InCyson +InDaCouch666 InDespair +InFemous InGameLies +InTawlerable InThe90s +InTolu +InTransition +InXanee +InYaShower Inaaya +Inactive Acc +Inar +Inavi Jones Inbow Inbred Incapacitory +Incendia Vir +Inch95 +Incin3rat3 X +Inco-san +Incoherent +Incomes IncomingBeef IncomingGank IncredblDino +Incumbency Indain IndawrCrwdad Indcsn +Indecisive +IndecisiveO +Indemise +IndexNull Indian +Indian Chad IndianCat +IndianaJones Indicates Indicator IndieGarri Indigo640 +Indivi2you +Indoktrinera +IndominusAsh +Indoor Scape +IndoorsOnly Indoorsman Indrado Indrias1 +Indy Ju +Inecstatic Inedibles IneedPVM +Ineff icient Inefishient +IneptEwok +InfIuenced Infaam +InfallibleX2 InfamousAB InfamousEvil InfamousMain +Infantiel Infase Infectus +InferiorRNG InfernOwl Infernadev Infernal +InfernalChef +InfernalLuke InfernalPRO +Infernax Inferneo Inferno InfernoTism @@ -10501,18 +21894,23 @@ Infero Infesmati Infin1te Infinate +Infininth InfinitiGX InfinityMan Infirme Inflnite Influx Info +Info Kiosk Infobese Infor +Infora Treat Ingeb +Ingenious G Ingeniously Inglane Ingleburn +Inhaled Inhinyero InhumanBTW Inimene1020 @@ -10522,38 +21920,68 @@ Iniys Inkedsaint Inko Inksane95 +Inkwes Inner +Inner Brian +Inner Peace InnerBliss Innvision +Inori xdd +Inosuke xo Inqku Inri Insafi Insane +Insane Iron InsaneBobbie InsaneFruit InsaneIee InsanePerson +Insaneglutes +Insanewolfy Insaniack InsanityNix +Insanityx Insanityzz +Insatiate +Inse +Insectkoala InsertGold Insluiper +Insomnia Insomnist +Insomnity Inspection +Insta +Insta Spec +Instabox +Instagrem Instail Instinct Instro +Instruct Insucc +Insulter Insulting +Insulting MF +Insurgence Insurgent Int0mieli Integration +Intel6 +IntelManiac +Intellectual +Intendi IntenseRage Intensifyyy Intentional Intercept0r +Interchange +Intermk Internal +Internal Max Interracial +Interronator Intherial Intier Intimate @@ -10563,154 +21991,542 @@ IntoInfinite Intoner Intresant Intresenting +Ints Intubator Intuition Inubashiri +Inukal +Inuouk +Inur InvTagsBad Inva Invalar Invercargill +Inversives Invert +InvertedDuck Inveterate +Invierno Invisa +Invisa Scav +Invisa-Veng Invisioners Invokers Involk Invoryy +Inwu Inxo +Io Jah Pul +IoB Sylarke +Iock +Ion Benny Ion870 IonCannon Ionia Iono +Iou689 Iowa146 IowaCJ Ioyal +Ioyins IpeeInTheSea Ipod5412 +IpotYouDrop Ippe +Ipswich +Ipswich FC +Ir JWWillem +Ir Phys Ir0n +Ir0n Bot +Ir0n b00k Ir0nMammoth +Ir0nMish +Ir0nPuma Ir0nRagnarok IrDA Iralimir +Irha Irid Irie IrieLuDa Irinichina +Iris Elea Iris_1904 Irish Irithe +Irl Baller Irmak Irobar +Iroff SGDaht +Iroflman +Iroh Bison Iroha +Iroic +Irom Typo Iron +Iron 0lm +Iron 2DWaifu +Iron 2b +Iron 3 Hit +Iron ABC +Iron Achael +Iron Aeolian Iron Alabama +Iron Alee +Iron Aloha +Iron Aloodum +Iron Alpha +Iron Anaerob +Iron Anno +Iron Anonymo +Iron Antzz +Iron Areolas +Iron Arnoud +Iron Arzka +Iron Assface +Iron Ayen +Iron Azshara +Iron B O D Y +Iron B0yx +Iron BDN +Iron BLK +Iron Bart +Iron Baskan +Iron Bawlsak +Iron Bawsss Iron Beabs +Iron Beeto +Iron Besu +Iron Bezem +Iron Bibi2u +Iron Biddys +Iron Bloke +Iron Bogmac +Iron Book +Iron Boomz +Iron Booxia +Iron Borrrby +Iron Brevik Iron Brinnie +Iron BryconC +Iron Buchu +Iron Buckc +Iron Bucket +Iron Bumko +Iron Burrata +Iron Buuh +Iron Byld +Iron Caddy +Iron Calquat +Iron Carly +Iron Carmine +Iron Carna +Iron Cerv +Iron Cevol +Iron Chaw +Iron Chemic +Iron Chkn +Iron Cholby Iron Chombre +Iron Chrisss +Iron Coby +Iron Coin +Iron Coronao +Iron D Luffy +Iron D Natsu +Iron D Zeref +Iron DJG +Iron DSC +Iron DVS +Iron Daniel +Iron Deku +Iron Denal +Iron Deroq +Iron Destr0i +Iron Dipshit +Iron Dixi +Iron Domi +Iron Dumontx +Iron Dylnn +Iron E +Iron E s s +Iron E z +Iron Eagah Iron Elyon +Iron Equity +Iron Excal +Iron Exed +Iron FFrenzy +Iron Fe +Iron Ferro +Iron Filthy +Iron Fioxxu +Iron Fire 75 +Iron Floor +Iron Forgy Iron Franchi +Iron Frodo +Iron Fuhrers +Iron G Zeus Iron G0liath +Iron Gaan +Iron Gamerz +Iron Gayness Iron Ghosgar +Iron Ginto Iron Gios +Iron Go +Iron Godley +Iron Godly +Iron Golem +Iron Goth GF +Iron Greg +Iron Grind20 Iron Griss +Iron Haze +Iron Hoiy +Iron Holub +Iron Hookkan +Iron Hossi Iron Hroth Iron Hugge +Iron Husky +Iron Hydros +Iron Hyger +Iron IPvMI +Iron Insaneo +Iron Jakob +Iron Jal-Nib +Iron Jeref +Iron Jeroen +Iron JimmyJ +Iron Jizzman +Iron Jss +Iron K3 Iron Kalde +Iron Kaleef +Iron Kapkeik +Iron Karjala +Iron Katniss +Iron Kayn +Iron Keagan +Iron Kess +Iron Kiwii Iron Kngs +Iron Knipp +Iron Kodie +Iron Koopsy +Iron Kornie +Iron Krijn +Iron Krikke Iron Laplace +Iron Laxor +Iron Layfe +Iron Letski +Iron Liber +Iron Lose +Iron Lungsta Iron MTUT +Iron Mamma +Iron Mammal Iron Mapes +Iron Marie26 +Iron Marlon +Iron Martin +Iron Masori Iron Masuli +Iron Matt +Iron Matt NZ +Iron Matty W +Iron Matuba +Iron Maxvoid +Iron Mellem Iron Meydon +Iron Miguel +Iron Mikebor +Iron Milan +Iron Mimal +Iron Miro +Iron Moardus +Iron Mossyy +Iron Munted +Iron Mystip +Iron Nap Iron Nellz +Iron Nick +Iron Nimmi +Iron Nobody +Iron Noe +Iron Nuclide +Iron Nuuby +Iron O Brien +Iron Oak +Iron Oboi Iron Ohboy +Iron Ohgodno +Iron Ohzone +Iron Opto +Iron Ores +Iron Pandis +Iron Parkour +Iron Patches Iron Peg +Iron Pge +Iron Phe +Iron Plague +Iron Pothead +Iron Praxis +Iron Pwn +Iron Pwnstar +Iron RNGsus +Iron Rakey +Iron Randall +Iron Randyy +Iron Reedzy +Iron Rekkr Iron Request Iron Rikyu +Iron Rind +Iron Roach +Iron Robsham +Iron Roof +Iron Rushy +Iron Rybread +Iron Ryuuga +Iron S t i g +Iron SSJ +Iron Sagga +Iron Samiria +Iron Santus Iron Scolew +Iron Scran Iron Seagz +Iron Seha +Iron Shaikh +Iron Shavers +Iron Sheik +Iron Shnapi +Iron Siem +Iron Sioux +Iron Skoptsy +Iron Skroten +Iron Skydive +Iron Slash +Iron Slaya83 +Iron Sloth 2 +Iron Smoke94 +Iron Snypah +Iron Sparco +Iron Splat +Iron Stannrs Iron SteveB +Iron Stomp +Iron Stronq +Iron Stw +Iron Sullo +Iron Susu +Iron Svampe +Iron Swaffle +Iron Swag +Iron Takumi +Iron Tango +Iron Tanzim +Iron Tbar +Iron Terboo +Iron Teun +Iron Thi3ves +Iron Tiffers +Iron Tigr +Iron Tigran Iron Tinman +Iron TomT0m +Iron Tonkin Iron Tonski +Iron Tonymaa +Iron Torfi +Iron Toxxic +Iron Trashua +Iron Trixx +Iron Tudder Iron Tutnin +Iron Tweeker +Iron Tyrans +Iron Tyrant +Iron UIM Iron Uakti +Iron Unam +Iron Varuna +Iron Vatti +Iron Venema Iron Vexzed +Iron VickD Iron W1nk +Iron Weather +Iron Wespula +Iron Wii +Iron WindJr +Iron Woofy +Iron Wu5 +Iron XIIIV +Iron Xellana +Iron Xire +Iron YEE +Iron Yangus +Iron Z4ppie +Iron Zephyx +Iron Zeraph +Iron Zerg Iron Zilong +Iron Zinoto +Iron Zoha +Iron Zol +Iron Zrysen Iron Zul Mox +Iron anrowi +Iron d0gz +Iron da ddy +Iron dols +Iron dry +Iron feens +Iron flynn +Iron instead +Iron kitcat Iron l2asta +Iron ona Mac +Iron pappal +Iron werty +Iron whiff +Iron wiper +Iron x wolf Iron xyN +Iron-Ximena Iron10203 Iron2Pickaxe +Iron619 IronAgentP IronAjandre1 +IronAkleiss IronAlblad IronAlufolie IronAngst IronAnnaMay IronApples +IronAsbe +IronAssHole IronAussieM8 +IronAxe +IronBadAtPvm IronBankFull IronBeanz +IronBeerad IronBiGuyBtw +IronBistchul IronBobbyjoe +IronBoink IronBosse IronBound IronBrad +IronBrand21 IronBrick +IronBruBrah IronBuriedNU IronBurnsRed +IronC1aws +IronCagedRat +IronCemile +IronChillii IronChirpOTK +IronChompers IronChrisKin IronClarkey IronCoX IronComedy IronCooter IronCozza +IronCraiger +IronDab 710 IronDakotas +IronDandaman IronDavid IronDeadBoy +IronDefiant +IronDeredas +IronDethaele +IronDodo420 IronDog777 IronDong +IronDravekD +IronDringus +IronDtrex +IronDubble IronDubzy IronDudde +IronDunceCap +IronDurrrrr IronEagles IronEkakerta +IronEso +IronEtch IronFefe +IronFigment IronForFunnn IronForged99 +IronForyn +IronFrenzey IronFrogMan IronFungi IronGalihand +IronGatr44 +IronGear CEO IronGez IronGodsword +IronGoliathX IronGoneNorm IronGow +IronGuh IronHammy +IronHasta IronHomer IronIDKFA +IronInsano +IronIogibear IronIsNoJoke IronJValor IronJakeT +IronJames IronJamesG IronJarod +IronJeffZ +IronJenga +IronJezz IronJoint +IronJosehiha +IronJosephxo IronJuji IronKaboom IronKaiser IronKapp +IronKayodee +IronKest +IronKingdoms IronKukk IronKyloman +IronLadBtw IronLadel IronLaffin IronLankzey +IronLazure IronLegend +IronLegocy IronLepaus IronLifting +IronLionMAIN IronLucas IronLuckPlz IronMadePure +IronMagick +IronMainOx IronMan IronManBow IronManJar @@ -10718,17 +22534,26 @@ IronManSux IronMango IronMarius IronMarty +IronMason +IronMathwin IronMatty +IronMayne IronMetknot +IronMikado IronMinion +IronMitchKun +IronMollusk IronMountain IronMugz +IronMushy IronNWord IronNachos +IronNantt1 IronNateDogg IronNazguls IronNexuss IronNeya +IronNibletz IronNihilm IronNinja13 IronNord @@ -10737,11 +22562,19 @@ IronOdum IronOldBoy IronOnPatch IronOrca +IronOreAgate IronOsiriss IronOxideMan +IronOxidizer +IronPangtar +IronParis +IronPeteMan IronPills IronPrice +IronPrickles +IronProf IronPumitaz +IronQben IronQli IronQueen IronRait @@ -10754,83 +22587,168 @@ IronSantaMan IronSchmieds IronShadow5 IronSikruz +IronSkaro IronSly IronSmurfff +IronSparrow IronSpiderZ +IronSpitfire IronSplats IronSpoNeD IronSpoony IronSpray IronSquidly +IronSteve-O +IronStronky +IronSurf +IronSylar +IronSystolic +IronTarnum +IronTasseron IronTau +IronTedBundi +IronTeste +IronTestedRB +IronTimTim IronToff +IronTulio +IronTyson IronUnkilled IronVegtable +IronVib3s IronVikinng IronVikzo +IronVinda +IronViolette IronW3LEGEND IronWafflee IronWallnut +IronWantsRNG IronWayneker +IronWidovv IronWush +IronYoerik +IronYugo IronZettrox IronZong +Iron_ProDabs Iron_Slippy Iron_Sukulo +Ironarcanic +Ironatica +Ironator Ironblood7 Ironboba9993 +Ironbobsaget Ironborn +Ironborn PVM Ironbutcher +Ironclad Sac Ironed +IronedSwift +IronendJr Ironeyy Ironflox Ironfur +Irongrazvis +Irongusty +Ironiam Vir Ironic +Ironic Force +Ironic Kill +Ironic Name IronicBenson IronicSwag93 +IronicViking Ironicer +Ironiical +Ironija +Ironik 20 IroningB0red IroningSucks +IronishSana Ironkaka Ironmacman +Ironmale Ironman +Ironman Daff +Ironman Jase Ironman Jowe +Ironman Wit Ironman idk IronmanFookz +IronmanHutch Ironmanerno Ironmeme +Ironmeme Cx +Ironmeme Lol +Ironmies Ironmimmi +Ironmorriz23 Ironn +Ironn Yoshii +Ironnesses Ironpasta1 +Ironqa Ironred33 +Ironriwer +Irons suck +Ironshore Ironsoul2 Ironstone +Irontownhero +Ironwind747 Ironwinter Ironwork4eva IronxElite Irony +Irony Nib Ironylion +Ironyx +Ironzi Ironzilla +Irrelevant Irrumated +Iru +Irulon +Irxn Irxnized +Is E_wen +Is Idle +Is Slikker +Is a bich +Is this you IsAlexOk +IsButters +IsChazCool +IsDomIsGood +IsYaBoyDoive Isaac +Isaki Magari Isbjorn Isganytojas +Ishigo1992 +IshmaelDonny +Ishrandom Ishzn +IsidoroM Iskemia Iskolar Iskon Iskra Islaal +Islami Islefalls Isleview +IsmackfaceI Ismelitooo Ismo54 IsoG +IsoKitty IsoP Isoga Isoleucine +Isootoonik Isoptox Isosami IsraVM @@ -10838,51 +22756,141 @@ Israels IssaEly IssaStiffler Issard +Ist M Istanbulite +Istasher Istaxit +Isvig +It Slaps +It is Rex +ItBeJacK ItBurns ItIsWedsDude +ItPol ItWasntMe007 Itaky Ital Italian +Italian roxx ItalianAJ +Itaochi +Itchweedy +Itcoto +Iteyx Ithero Ithlinee +Itik +Itinkinou +Its Absol +Its Almog +Its Arj +Its B0B +Its Brother +Its Canadian +Its Conrad +Its Da J00z +Its Dally +Its Dyl +Its Hash +Its Jon btw +Its Jst Skin +Its Kaylee +Its Libo Its Me Dave +Its Me Q +Its Me Suns +Its Misha +Its Nipo +Its Peter +Its Rigged +Its Sebas +Its Sense +Its Seth +Its Smooth +Its Teddy +Its Wolfie +Its Yama +Its Zammy +Its a Shame +Its claw +Its me Josh +Its me eden +Its rob +ItsAboutTime +ItsAirdog ItsAllOgreM8 ItsAnobrain +ItsBarcus ItsBigNasty ItsBlitzyy +ItsBrtnyBch +ItsBru ItsClout ItsDende +ItsDynasty ItsFinn ItsFlooo +ItsHoggle ItsHosef +ItsInThePast +ItsKenshi +ItsLitttFam +ItsMarc ItsMeBlaze ItsMeDog ItsMev +ItsMrSir2u ItsNiels ItsOleGreg ItsOwenM8 +ItsRainor +ItsSirTech +ItsSkells +ItsSyn1k +ItsTaylen ItsTerpsWrld +ItsUnruly +ItsWeinstein ItsWicked Its_A45c Its_Fonte +ItsaTommyGun +Itse rauta +Itsemurha Itsmeborrid +ItsoktoGIM Itsssjustice +Itsy Bitsy Itupakointi +Itx +ItxJustin +Itz Haydn1 +Itz Hickton +Itz Kodiak +Itz Nate +Itz Scrubz +ItzAtlass ItzElise +ItzJroc +ItzKat ItzLogikal ItzMrNick +Itzla Itzvenom +Itzzz B +Iuc Iuckk Iulz +Iussy Iustrous Iuxio IvIegaDan +IvIr Wize Ivain Ivaink +Ivalice XIV +Ivan Knjklj +IvanEOD IvanMullet Ivanckonia Ivanka @@ -10890,167 +22898,448 @@ Ivansaccount IvelJet Iveljetorox Ivoos +Ivory Tower Ivryk +Iwanbro IxHunt3rxI +IxVenom Ixala IxonnoxI +Ixyc +Iz0p +Izaa +Izac +Izanani Izbec +Izhmash +Izi Claps Izone_Kev Izuria Izvorul Izzy +IzzyBigBoy Izzyboy300 +J 0 S H Y +J 0 S H l +J 4 6 +J 4 K E +J 6 +J A B S +J A I D A N +J A M A L +J A N K I +J A U N U S +J A W D +J Breezi +J C Trousers +J D +J D Ballew +J Dahmer +J E E V E 5 +J E T +J F +J Fred Run +J I M M +J I MM Y +J Kole +J Kribzz +J L A +J MF B +J Neat +J O E G +J O L T I K +J O T A +J O3Y +J R O C +J R V +J Rat Cow J S 2 M +J S Z M +J Saints +J Suave +J U S T A S +J U Z +J a c k a l +J a c k son +J a c k y +J a mie +J a n i +J ackal +J al +J ameper +J anii +J appie +J asnah +J ason +J asyra +J ayson +J bellfortt +J bird shady +J e sse +J eff +J effy +J ensen +J esse +J essica +J imme +J imy +J imz +J ipr +J lMM Y +J o b e +J o e +J o ey +J o f +J o s h y +J oep +J ohannes +J ointz +J oke R +J or G +J oshh +J oshhh +J osie +J u wu +J ung +J unko +J utch +J uun +J uwu +J x B +J yy +J-2tha-R-O-C +J-Man 93 +J-Turn +J-Yeezy J001_jf1 +J0DYY +J0E +J0E REAL +J0EEY +J0NE J0UF +J0YBOY LUFFY J0YRYDE J0dz J0hnnyQ J0ng J0ngeBV J0ppy +J0rdanDv J0rdo117 J0se +J0se Dtown +J0se Dtuwnn J0seph +J0shh +J1MB0H +J1NBE J1ub J2TR J2caine45 J2ck +J328 +J3Ciron +J3JU J3S5E J3rkkuHD J41AL J45e0wns J4QS +J4S J4gga J4my +J95 +JAABASNABBA JACK3DJOHNNY +JACKYOUNG93 +JAG0705 +JAI MA KALI +JAMA Open +JAUH0JENGI +JAVON 9-INCH JAYJ51 +JAYR0CKBABY JAlDYN +JB 2K +JB87 JBGard JBrody JBuck057 JBux +JC-1989 +JCS07 JCole JCon JCutler +JD MD +JD4 JDBass JDEP JDFlaSh JDJM JDez JDlion +JDredd66 +JDuck +JE B +JEEZE JENNY +JENNY DEATH +JERN SVIN TO JETSNBEERS +JF Kennedy +JFB +JFCK +JFK gone AFK JFKautopilot +JFL JField +JFrog JFryGuy +JGIRONTG JGIV JGlen97 JH3305 +JH91xx +JHINitalia +JIGGYWIGGY JIIVEE94 +JJ-M JJ23 +JJAAKKO +JJBW +JJPowers JJROCKETS JJRicky +JJS BBQ +JJSM_Dulker JJchris66 +JJoe +JJumalwelho +JK Rowling JKMi JKTimbo +JKUR ON 40S +JKeM JKingJ777 JKrollin JKuyaa +JLG JLowe +JLsone +JMI NG +JMTaipei JMack JMiddd +JOBBO JOCKO00O0O0O +JOE EROTIC +JOKER 709 +JON3ZYY94 +JORlCK +JORlS +JP Kotsnek +JP17 +JPB at Large +JPI +JPS Daytona JPant1ess JPantless +JPatness JPence JPountney +JPudz JR05E +JR0D +JRBeast +JRC Crypto +JROGU JRxs +JS Xpress +JSL34 JSLatvala +JSPACER +JS_Terminal JSco +JShep23 +JSilvester08 +JSlice94 JSplash JStepho +JT5 +JTAG +JTCS +JTI ain JTIAIC JTM33 JTscape JUGIB +JUIBE +JUICEWRLD9 9 +JULlAN JUST +JUST A HlPPO +JUST Nikk JUSTICE JWRLD +JXJ +JZB JZX1O0 +Ja k ey +Ja m e s +Ja mes A +Ja se +Ja sn JaBouris JaDig JaStraater +Ja_Fireking +Jaaaakkoooo Jaac JaackGP +Jaager Jack +Jaagmu +Jaahee Jaakako Jaalva Jaamm Jaant0 +Jaapievecht +Jaay G JaayC JabHook +JabbaU JabbasHut +Jabbaw0cky +Jaber +Jabesol +Jabiborinoni +JablezGIM +Jablooze +Jabo b Jabopanda Jabroni Jabroniii +Jabrs +Jabuz +Jac o b Jacckk +Jace C +Jacerhapsody Jacey Jacinto Jack +Jack Dyer +Jack Htoo +Jack Hughes +Jack Mac +Jack Maz +Jack Par-O Jack Reipan Jack1 +Jack12Broke +JackBadasson +JackBass4 +JackBlade +JackDanielsH +JackHammr +JackKnight +JackKvorkian JackMayte JackOscar JackRod +Jack_Herer9 Jacka JackandCoke Jackass +Jackass Sean +Jackazzz1 +Jackblaze +Jackbtw Jacke +Jacked Jackie +Jackingten Jackisbanana JacknHookers +Jacko Bei JackoPogU Jackoo Jackos Jackoz Jacks +Jacks0n Jackson +Jackspyrow Jackyboiii Jacob +JacobGhosty +JacobIsTaken +JacobT789 +Jacobb Jacobieus Jacobro Jacobs +Jacobwins1 Jacupy Jacy59 +Jad slides JadMaister Jada Jadakiss Jadavius Jaddok +Jaddy Chill Jade +JadedRapture Jadeine +JadenM Jads +JadsVag Jaecob JaegerBoom +Jaeson Jafacakeman Jafanto +JafarTooHigh +Jaffa Jake Jaffar +Jaffywaffy +Jafsx Jagdpanther JagerBombski +JagerIron Jagermeister Jagged +Jaggen +Jaghatai K +Jagoodiii +Jah toch JahIthBer Jahaerhys +Jahaok +Jaharred Jahbby JahgexPlzzz +Jahmay Jahmerica +Jahngles +JaiSiaRamJai Jaiden184 Jailbreak455 +Jaime 427 Jaimeebear +Jak Maximus JakMetalHead Jaka On Can Jake +Jake C +Jake D Snake +Jake Muzzin +Jake OC +Jake Scapes +Jake Solo JakeState68 JakeSteFarm Jakedajackal @@ -11062,64 +23351,127 @@ JakesSolo Jakesonville JaketheSnake Jakey +Jakey C Jakeyosaurus +Jakeyz +Jaknop Jakrem Jakrojan +Jakuli226 +Jal-Nib-Jmal JalNib Jalduii +Jaleesa +Jales +Jalim Rabei Jalite Jaljif Jalla Jalo Jaloenow +Jalordom Jalou +Jalzas +Jam Flex +JamBandDad +Jamaikietis JamalBobaman +Jamango +Jamania64 +Jamar +Jamaul Jr Jambaica Jamblaster +Jambreak +Jamburano +Jamchu Jameo James +James 6000x +James Comey +James Kakadu +James Kelp +James Poncho +James PvE +James Rolfe +James c +James osrs +James1087 James2709 James9 +James945848 +James9520 JamesBondss JamesCUFC JamesDaWizar JamesHaliday JamesJ2019 JamesLango +JamesMaynard +JamesNI JamesPratt94 JamesShotGG +James_22 Jamesay Jamesbombom Jamesrb1 Jamess Jamesy JamiBear +Jamiboy Jamie +Jamie Tacos +Jamie W +JamieJams JamieOliver JamieXV +Jamilan +Jaminnnn Jamixa +Jamjac Jamlicking Jammie +Jammmy +Jammoose +Jammy Dogger +Jammy Scone Jamn Jamosbondos Jamppa Jampy +Jampyre Jamuli +Jamurazi +Jamwa Jamyroo531 Jamzylockz Jamzz +Jan +Jan Griffith +Jan en Karel +Jan100000 JanHenkD JanVanLeiden +JanXtian +Jananas3 Janar +Jancentp Jandaer +Jandhob Jandie5 Jane Janer Janes +Janes Bond +Jango Style2 +Jango fet310 +Jangsta23 Janice Janikowski +Janissary90 Jank Jankk +Jankko Janksky JannaMain73 Jannanas @@ -11130,81 +23482,171 @@ Jansky Jansz101 Jante Jantex +JantheBear Jaooa Japanese +Japhur Japiohh +Japles1 Japoolie Jappieee +Jappieness Jappo +Jaqen +Jaqquu +Jar Of Pets +Jar Uh Dirt +Jar of Pukes +Jar of Swamp +Jar ofc um Jar3y JarOfCookies +JarOfH0les JarOfSmORC Jarab +Jare d JareZki Jared1234 Jareds134 JarlCantBank JarlEarlKing +JarlVaarg Jarnemelk +Jarnie Dimon +JarnoMirma Jarnte Jarra +Jarre Jarredn +Jarreelll Jarskie Jarsse Jaru Jarvis Jarx +Jas Melody Jasberg +Jaseel Jasey +Jasey Rae +Jashin Jasinador +Jaskanpaska Jason +Jason In Max +Jason73 JasonJ +JasonLRG +JasonRises +JasonSkillz +JasonT20015 +JasonVorheez +Jasonn +Jasonnn Jasperw90 Jaspi +Jasthew +JasuzChrist Jasyre +Jauneri Jaunius +Jav Jave +Javert +Javier Pwns +Javve Javvymuis +Jaw +Jawaloso +Jawgasm +Jawmac +Jawniz Jawntista +Jawor Jaws +Jaws 2 75 +Jawshy +Jax Evasion +Jax Teller +JaximusIV +Jaxy22 +Jay Ayy Why +Jay Baby +Jay Exotic +Jay Hughes +Jay M +Jay RZ +Jay Show +Jay Sparks69 +Jay United +Jay b1zzle +Jay kell Jay024 +Jay357 JayDaddy313 JayEngineer JayFlow +JayJee +JayKay Okay JayLunar JayManzarek JayMaster +JayMe x JayMuthaFknC JayPortal JayRu7 JayTheBurnt +JayTheRunner +Jaybiz Jayden Jayders +Jaydey Jaydia +Jaydo x +Jaydonn Jaydos +Jayeden Jayhawk225 +Jayhawkers Jayi JayjayNeo01 Jayksie Jayman +Jaymeh Lee +Jaymo123 Jaymyson +JaysATank +Jayshuunn +Jayspoks +Jayster Jaytea Jayteaf Jaytee1262 Jaywub Jayy +Jayy Slays +Jayy x Jayzar +Jaz Coleman Jazo Jazpurs Jazz JazzFlap JazzMaster09 +Jazzeh Jazzjr89 +Jazzly Jazzy JazzyFlips +Jb Godranger +Jba123 +Jbevzzz Jblieves88 +Jbob72 +Jbt Jbvff Jc_TheCops +Jcb4646 Jcdelavici Jchn Jcmalone23 @@ -11213,223 +23655,454 @@ Jcourt1 Jdaws Jdidy Jdoggy2018 +Jdp3 +Je nny +Je pppe +JeBoyHiddema +JeIlo +JeIly Man JeJoat +JeK0 Jean +Jean belette +Jean man Jeangaboudle +Jeankeh Jeari +Jeavoni +Jebaited825 Jebiii Jebrim Jebroid Jebroni +Jecht Shot Jecob +JedMosley Jedah JedaiKnight Jedi +Jedi Drue Jeebiez Jeebz +Jeefro +Jeek Jeemis Jeep Jeesuhs Jeet Jeeve Jeez +Jeez Christ +Jef fy JefFamous Jeff +Jeff Aero +Jeff C +Jeff pls go +Jeff says +Jeff the Cat +JeffEHPstein +JeffG JeffMusk JeffWiki Jeffermus +Jeffica Jeffie381 Jeffmyster5 Jeffre +Jeffrey Z JeffreyFNV +Jeffreypoe Jeffro Jeffy +Jeffy xD JeffyTheDahm +Jeffzuaos +JefriEpstin Jefry +Jeft Jefy Jeggesen +Jeguelson Jehdin +Jehobo Jehtty +Jeikeorb Jeimi JeisBtw Jejex +Jekd Jekquesting +Jelbishi Jelbringer +Jelen +Jelenner Jelior Jella Jelle +Jelle Bouma Jellie40 Jellisme_99 +Jellitots +Jellough Jelluh Jelly +Jelly Bears +Jelly Booty +Jelly Dub +Jelly Sucks JellyBeanRs JellyGenix +Jellydonuts Jellyfishes +Jelziin +Jelzini +Jemades Jemelope +Jemile +Jen na Jen0va JenaTulwarts Jenessa +JenfoxxSub +Jenicek Jeniuss +Jenkiins Jenla +Jenna Taylia +JennaHeather Jennacydal JenniTolls +Jennie Jennn Jenny JennyElina +Jensen641 JensenRS Jenskee +Jenten +Jeometri Jepp89 +Jeppe Jeppeonkurre Jeppie +Jepppe Jepppu Jepuzeka Jepz +JerBearGrizz +JerBearOmfg Jerak Jerayou +Jerbelle +Jerbil Jerec Jereh24 Jeremiahlewi Jeremy +Jeremy 2007 +Jeremy Ray +Jergs Jeri +Jerm +Jermothy +Jerms Pro +Jern Jan Jern Tarzan Jerne Jernladden +Jernlund Jernpung +Jero +Jeroen 31 Jerom21 +Jerrbear69 Jerre26 Jerrin +Jerrwie Jerry +Jerry Alan +Jerry Maine JerryChinger JerryMina +Jerryy Jers +Jers Knot Jersh +Jershawerr Jersion +Jertz Jeru +Jerunox Jerusalenm Jerziii Jerzy +Jes2x +Jeseeka +Jesh g +Jesh-mar JeshusChrist +Jesiah Jesk +Jesliq +Jesper Bratt +Jesper135 +Jesperyo Jess Jesse +Jesse Top Jesseq Jessica Jessie +Jessie Jones Jesspresso Jessy +JessyTrip +JessycaOSRS +Jester Head +Jesterbubba Jesus +Jesus I love +Jesus MPhys +Jesus Saved JesusComing JesusRedeems +Jet Jaguar8D Jet3010 JetFlame Jeththe +Jetlag Jetma Jetridder11 +Jetski Jetsmoke +Jettiesimp Jettrider +Jeugd Jev21 Jevel +JewFroBro Jewbaaca Jewbakah Jewbang +JewishRob Jewy +Jexlad Jexlo Jeyos +Jeyzuz Jezeus Jezkoz Jezuux JezzaripHD Jezzie +Jezzx +Jf-n03 Jfleeze +Jfrith +Jfuzzy Jglove +Jgus88 Jgy1889 +Jhackal +Jhb Jhebs Jhny +Jhonlovin +Jhoocy +Jhoocy Moot JhormanCovid JhosS +Jhow +Ji bs +Ji m m +Jia Lissa Jian +Jiara Jibajaba Jibberflexed +Jibbllyy +JibinSui +Jibneh JibrilMaster +Jiffee +Jig Bugs +Jiga Chad +Jiggalagg JiggerJoe +Jiggity Jigglyboy Jigglywoo +Jiggypufff +Jignite +Jigoogly +Jih +Jihe +Jihne +JiiU +Jiiko +Jiim Lahey +Jiiraiiya JikdarShark Jikkurr Jiklim +Jill Hyde +Jille Man +Jim +Jim Sauce +Jim Shorts Jim0k +Jim2k1 Jim38iron JimAdler JimTheGing Jimb0bMaster +JimballSlice +Jimbeamtndew Jimbi Jimbly +Jimbo Sween JimboJamzAF JimboQuan +JimboSlice21 Jimbob3005 Jimbogun Jimboi +Jimbub JimcakeKong +Jimdawgy Jimi Jiminuatron +Jiminy49 +Jimm JimmahDean Jimmerik Jimmi +Jimmi Lipper +Jimmmm Jimmy +Jimmy Jumper +Jimmy Plays +Jimmy Scimmy +Jimmy Wooo +Jimmy1408 +Jimmy3rdBase +JimmyBullard JimmyBuns +JimmyCarter +JimmyGrimble +JimmyStubble JimmyValmer7 +Jimmybe +Jimmygk +Jimmylovecox +Jimmynyge Jimmyo Jimosine Jimpertje Jimpiix +Jims Goon +Jims Ironing Jimsterjim +Jimver Jin Oh +Jin R n G JinDoritos +JinJ0 nJuice +Jinb +JingleBiloba +Jingy Jinimy +Jinjaman Jinkers Jinko +Jinkys +JinnyChatBot +Jinpa +Jinsinny Jinte +Jinxed Jake +Jinzo Doku +Jinzo Jinzo JioGetsMoney Jion +Jions Alt +Jipser +Jipske Jiqonix +Jiqura +Jiraiya +Jiraiyeah +Jirakh Jiren Jirka Jirou Kyouka +Jisska Jitaxia Jithra +JiveChompy Jixoxx Jixr +Jixx0x +Jiyool +Jizt +Jj Dynomite +Jj Jerk2 Jjar127 Jjjjjj210 Jjozzie +Jk Esq Jkdogg Jkhby +Jkl Kalja Jkolrur +Jkrexx Jku45 +Jl-SOO +JlGA JlLLY JlMMB0 JlZZB0SS Jlarge Jlova Jmagelssen +Jman021 Jmar Jmaster402 Jmbryn Jmca +Jmca Savage Jmen Jmies Jmjake Jmonelite Jmudford44 +Jmz Jnas +JnrSeneca +Jnsthenx +Jnup Jnwp +Jo Pain +Jo de Coeckh +Jo h 2 +Jo iron +Jo rd an +Jo shua +Jo we Jo0l +Jo3 H Jo3p Jo5p +Jo6p Jo711 +JoE ShMoee JoEiSaFiShEr +JoJi JoJo +JoJo Skriver JoJo79 +JoJoJoUrBoat JoKerRtheGOD JoMoe JoRouss @@ -11437,84 +24110,168 @@ JoWie JoXuh Joacco Joao +Joao EV +Joao Paulo Jobac Jobann Jobard93 Jobber +Jobbes Jobbits +JobbySkelper +Jobbydrinker Jobbyqq Jobless Jockward Jocqui Jodenzaad +JodioJoestar Jodon +Joe 7 +Joe Kronic +Joe Lol +Joe Mangina +Joe Mclaren +Joe Muggs +Joe Potato +Joe Schwa +Joe TheBeard Joe56543 Joe56780 +JoeBidens Bf +JoeEldenring JoeFoe JoeGas +JoeInglesGod +JoeJunk +JoeMothers +JoeStudd JoeTheGod JoeWoody +Joebie Joebobinator Joecuster +Joedaschmoe +Joee P +Joeholding +Joekle Joel +Joel 9444 +Joel In Pain +Joel Lobster JoelBtw +Joelemz Joell +Joenage +Joenly Joered40 +Joeri Joes Joeshmo Joestar Joey +Joey Diaz +Joey Mobile +Joey RS +Joey069 JoeyDabs +JoeyGatto +JoeyP +JoeySlays +Joey_1993 +Joeyboy +JoeyboySucks +Joeychh Joeydarebel Joeyer5 Joeyfernando Joeyjoe600 +Jofa Joferr Joffa +JoffreyLupul Joggaplanten Johan +Johan Cruyff Johanbtw +JohannesN JohannesRRL Joherk John +John Bilos +John C +John Cena +John China +John D4rk +John Ironman +John Mayer +John McCain +John Mugwump John Muir +John Paul +John Penn +John Sal JohnChaptr15 JohnDaBoss JohnGilespie JohnNoyes +JohnRambo43 JohnWLennon JohnWick39 +John_Wick007 +Johnathan Johnbovi JohndemenBTW Johnletics +Johnmcdodger Johnny +Johnny Chinn +Johnny Dinh +Johnny Lyu JohnnyBeanz JohnnyChimpo JohnnyHart +JohnnyLoco JohnnyMellow +JohnnyQuest JohnnySXC Johnnypants +Johnnys +Johno381982 JohnoMate Johns +Johns bad ma +Johnsons +Johnsters4 Johny +Johny Aus JohnyLocoo Johnyy Johuab Johzyn Joizz Jojis +Jojj Jojkan +Jojo Rabbit Jojora Jojy +Jok Jokar Joke +Joke xD +Jokelanopein Joker JokerzDice Jokinq +Jokkepappa JokuHeppu +JokuVaan Jokurul Jole JolliJolli +Jollyfarms +Jolonerz Jolteon Jolting Joltism @@ -11523,100 +24280,198 @@ Jombsy Jomer Jommann Jomoba +Jomppaa Jomppei +Jon +Jon Eusebius +Jon Meades +Jon Snow +Jon ny +Jon10 JonHDgamer +JonMarston JonOn JonVV +Jonadwyn +Jonahams808 Jonahcart Jonanism Jonas Jonas9115 +JonasLietuva +Jonas_Butte Jonasbroh +Jonassau +Jonatan Jo +JonathanRoid +Jonaz +Jonbaron Jonboy +Joncc Jondog JoneNikula +JoneZii +Jonesing Jonessy +JonesyBadger +Jonetsa Jonezey3 Jongo Joni +Jonibo +Jonie D JonisBaisus JonisSniegas Jonjo12knees Jonko +Jonko lover Jonn +Jonnay +Jonne r Jonnems Jonnisan Jonnisjoen +Jonno1789 Jonny +JonnyBiggles JonnyBoii +JonnyL2020 +JonnyLots +JonnyM Jonnybak Jonnybowler8 Jonnysniper Jonsamma +Jonsed +Jontzzz Jonxsy Jony Jonzza +Joo Potato +JooOvenPizza Jooe +JoojoThePk8r JoonSoo Joonas Joonayoyo Jooni Joontah +Jooogijuuu +Jooohnny +Joop Mgoon Joopaul Joose3 +Jooshica +Joosst +Joostvd17 +Jooxan Jophatmama Joptvajiumat +Jor dinh +Jor dy +JorVa Osj Jord +Jord 0_o +Jord Croft +Jord idk +Jord xD +Jord y +Jord z JordHarris +Jord_96 +Jordan 1 +Jordan 7218 +Jordan KY Jordan030592 +Jordan07 Jordan1063 Jordaneee +Jordanite +Jordans Jordany5b Jordavitch Jorden JordenFCB +Jordinee Jordnn +Jordo Am JordyM JordyMcSheep +Jordynn +Jordysteen Jordz_King +Jore Jorenator +Jorgeme +Jorgos +Joricki +JorkinMyWorm Jorkkelis Jorlund +Jornaleiro JoroEdde Jorsne Jorster Jorttis Jorzki +Jos Bezos +Jos de Mutn Josavi JoseLargeD +JosefStaIin +Joseluis1 +Joselyn Leo Josen Joseph +Joseph Sam2 Josh +Josh 2277 +Josh Jones Josh Tsutola +Josh x +Josh013 Josh2Godly JoshD +JoshDagainz JoshGymnast JoshMarksman +JoshYewAhh +Joshalog +Joshan Joshery Joshh +Joshhhh Joshii Joshimitzu Joshism +Joshjoshin Joshmaster31 +Joshpaul Joshua Joshuaaaah JoshyCii +Josiah Higha Josiahs Josoust +Joss +Josse +Jostavo +Josti O_o Jostle Josue Josukes Josylvio +Jota_420 Jote +Jothha Jotjemenotje +Jotq +Jottini Jotunheimar +Jotwe Joueur4376 Joulaha +Jovial Jovilius JovyGaming Jowah @@ -11624,43 +24479,86 @@ Jowalll JowatBTW Jowel Jowitt +JoyOfSatan Joycey1997 +Joynzz +Joystick +Joyun II Joz6 +Jozi Blue Jozu +Jpan1 +Jpellican +Jpq +Jqwss Jr Metro +Jr Muffin +Jr Stigel Jr2k13 Jrabbat Jrby +Jrdn Jreppks +Jrey Jroanirr Jrodjok Jrogo +JsJays JsN4 Jsag +Jsi7111 Jsnn Jsony +Jspot +Jsq Jstnn +Jstrife9 +Jthrust Jtownironman +Ju mala +JuGgLe BuG +JuJuzzz +Juan Dangle +JuanTalon +Juandissimo +Juaneria +Juanreliable Jubaah +Jubarte JubbaTheHut Jubilations Jubita Jublian +Jubster +Jubtus Jubu +Jubz Judah +Judas wept Judddy Jude +Judge +JudgeDredd +Judgewalker Judie Judies Judlmin JudoChop +Juduel +Judus Judybats +Juedons Juezz90 Juffo +Jug001 +JugMilk +Juga JR Jugalator +Juganog Jugernought Juggalo09R Juggerthot +Jugimaster JuhQ Juheniqus Juhhu @@ -11672,22 +24570,52 @@ Juhve94 JuiBoi Juib Juice +Juice W RL D +Juice WRLD +JuiceRock JuiceUSA +Juiceb0x44 +Juiceful +Juicewayne +Juicieee +Juicing Juicy +Juicy BIG +Juicy Jorma +Juicy Lil D +Juicy Pair +Juicy XPs +JuicyBigNut +JuicyJesusFE +JuicyJocelyn +JuicyJones +JuicyLap JuicyTear +JuicyTigr +JuicyWetNut +Juicy_Newfie JuiicyAF Juikki Juint +Juipp_Iron Juisy +Juk e +JukeLess Jukebot Juked +JukeduM Juko Juktes +Jul es Jules +Julesbak Julia JuliaFlorida JulieFromHR +Julieekins Julien +Julio Cesar +JuliusHotdog Julley Julma JulmaJoe @@ -11695,42 +24623,93 @@ Julmarsson Julpa Jumal Jumanji +Jumbalia420 Jumbo +Jumbo Joe +Jumpcut JumpingBean +Juncker June +June bug Junexo JungJulius Jungkook Jungle +Jungle Georg +Jungle Jepa +Jungle Jim +Jungle Wreck Jungle175 JungleKitty +JunglinTunes +Juniortank25 Junk168 Junmai +Junsimu Juntti463 +Juo Juoda +Juoppis JuostenKustu Jup1Ko1r4 +Juppi Juqqernaut Juranja Jurassix +Jurble Juri +Juri M +Jurikka +Jurisdiction Jurky Jurmalainen +Jurrie Jurtaani JuryRigging +JusAmain101 JusCauz +JusDoMe +JusPourVous Jusfat +JussJoshinYa Jussi Just Just Alright +Just Alt F4 +Just BeingMe +Just Bones +Just Bryce +Just Champ3 +Just Creepin +Just Dank +Just De-Iron +Just Jacob +Just Keith +Just Kurt +Just Logan +Just Malone +Just Milton +Just Mitch +Just Neptune +Just Reacher +Just Treason +Just a Dilf +Just a main +Just aFacade +Just for Fun Just1n Sane Just3lis444 JustAAPotato +JustADowny +JustAFroggy JustBob JustChillins JustDevon +JustDrew JustFollow JustGoInDry +JustIan +JustJS JustJake JustKidStuff JustLucky @@ -11739,14 +24718,25 @@ JustPeachy JustPertti JustRenne JustRoW +JustSarge JustSinful +JustTaxLand +JustTheFool JustTheTip +JustToast +JustTrynaMax +JustVibeWMe +JustVinny +Justa Wake JustaStar Justass +Justice v1 JusticeSven +Justicemoose Justiciaro Justified Justin +Justin NT JustinBieber JustinFromVA Justinkai @@ -11755,66 +24745,178 @@ Justins007 Justlfied Justnexuss Justo80 +Justorr +Justryin +Justyfi +Justyn Jusus Jutendouji +Jutku +Jutkunmetku +Jutter +Jutti +Jutty Ruckus JuuNinJi Juugmasta Juul +Juulxodia +Juun Solo Juuna +Juunaz2chips Juustis +Juuzo Juvi Juvian +Juzzy +Jvzy Jwad +Jwcsg +Jwd Jwett +Jwu JxJxV JxcelD +Jxck Jxcx Jxdidiah Jxdooo +Jxhnn Jxke +Jxmeson Jxnas Jxni +Jxstxn +Jxxst JxyStorm +Jy Jybais Jyeronese Jygers +Jyhlln Jyhy +Jype Jyppedi1992 Jysk Jyura +Jyy Jyypy JyzzBrah +Jz +Jzbeta +K 1 L L A +K 1 P +K AMI +K B D autism +K E K E B +K E L A +K E T CHUM +K E V 0_O +K Hades +K K Boef +K NW +K O L L I +K O M P I S +K OOOOOOOOOO +K P N +K P Sweet +K Smalls +K W +K W A L A +K Y Y +K a l e w i +K a z a +K aarel +K ayyla +K eller +K elvin +K en +K etaminer +K ev +K iNG IRON +K idd +K ilo +K im +K l 9 +K l N G S +K nauss +K nut +K o j o +K o o s a +K ohen +K orruptt +K ree +K rs +K t r n e +K una +K ushi +K uz +K voth e +K y u m a +K yogre K-Diddy K-epan +K-market +K0 +K0 4 K00LBR33ZE +K0F K0L0S K0NING +K0USE K0bus +K0edinator +K0ju Balius K0lbi K0ndemned K0rky +K0rnuit K0tleciokas K0veras K0zor +K19 +K1ERZ K1LLY K1ddl3 K1ller5169 K1ng +K1ngo +K1ngshredder +K1r1t0123 +K2 Jung +K32 +K38 K3KSE +K3U S2 K3azkoks K3fka +K3kt K3mi K3nn3d K44K K4IF20 K8iee +K99 2 +K9Father K9lenny +K9rk +KA97 KABBABEAST KAKAGUATE0 KAKERANDELIN KAL-JML KAMlX +KAT alyzt +KB1988 +KBARAKAT +KBX0 +KC Chiefz +KC M0 +KC8 +KCRB +KChiefn KDOG1419 +KDOT_OSRS +KDark22 KDrizzy KEEPOUNDING KEEPTHATSHIT @@ -11822,73 +24924,164 @@ KEEZY10 KEIF KEKDUBYA KEKLERO +KENTUCKYBLUE +KEllis KFBal +KFC CAMDEN +KFC EMPL0YEE +KFC OG KFCatz +KFChompy +KGBK KGCine +KGP KGee +KGoldy KHADER KIIIIIIIIIIH +KILLER COMBO KILO KIMB0 KING +KING GAYWAD +KING VILO KING332 +KINGNERON +KINGstayMAX KINGxGIZZARD KINNTO KIPPER +KIVI 420 +KIWI Stu +KIitor IS +KJ 2 +KJ6 KJLS +KKayK +KKela KKona +KKona USA KKrazyAl +KKronas KKurtiz KL93 +KLB +KLS +KM 30 +KMW +KN0G KNIKERSNIFFA +KO CANE +KOK enjoyer KOKAOKAA +KONMAI +KOS OVO KOlRA KQSS +KR Zangetsu +KR0VALI +KRN +KRON1C 420 +KRYMK +KRYPTONlAN +KRlT KRonHusker KS04rs1 +KSP +KSaucee +KT Ferrie +KT Tape KU51 +KUAY KUAYx KURD1STAN +KVM8 KVRPT +KXNG Razing +KXNGVEGETA K_sak +Ka0s50 +Ka92 +KaChiuSa KaIOKENRAGE KaMi KaMi_RnG KaTFeniX Kaan +Kaan Frog +Kaarel55555 +Kaaris95 +Kaarv +Kaasbaap +Kaasboom Kaasmantel +Kaaswater +Kaaz Channel +Kabatlor +Kachhow Kacinova Kacy Kacyy +KadHead Kadabara Kadan Kadarlu +Kadett Opel Kadeyr1 Kadocc +KaeBtw Kaelin Kaempen Kaepls +Kaer +Kaesar KafHaYaAinSa +Kafaei Kaffah +Kafficko Kage Boshi +Kahdoom +Kahis +Kahlx +Kahto Kahuna +Kahur111 Kahvikuppi +Kahvimaa +Kahvo Kahwoozy +Kai ri +KaiHos19 KaiXin Kaibaman +Kaif Kaihn +Kaiirl +Kaila Kails Kaimanll3kav Kaimorten Kainahuulio Kaine +Kaioken x420 KaiokenRyan Kaion Kaiser +KaiserBruno KaiserRS Kaister +Kaitaia KaitoSun Kaiven +Kaizen Reign +Kaizen Soji +KaizennxX +Kaizloh +Kaizooka +Kajbanan +Kajgils Far +Kakariiiiick +Kakarrot Kake Kaker Kakerandeli @@ -11897,84 +25090,144 @@ Kakoji Kakor Kaksitoista Kaku +Kaku bakudan Kakua +Kakuri +Kal9000 Kalakoi +Kalas Kalash556 Kalashnikova Kalavothe +Kalb Kale +Kale Henk +Kale vader +KaleKikker92 +KaleRS +Kaley Cuoco KaleyFan Kalezki Kalfite +Kali Maaaa +Kali Roses Kaliaa Kalico Cat Kalideos Kalihi Kalikow +Kalima Kalis Kaliumoxide Kallateral Kalle +Kalle Anka Kalleee Kalmaars Kaloex +KalopsiaSix +Kaloua Kaltsu Kalu1337 Kalub +Kalvaaja Kalveo Kalystas +Kam +Kam Lok Lam Kamal63 +Kamchi Kamelinpiaru Kamelovsky +Kamelze Kamen +Kami_no_majo Kamiel +Kamii Dad +Kamijou Kamikazi Kamino +Kamino Kage +Kammorie Kamp Kampest Kamphuijs Kanagawa Kanao Kanapius +Kanapizza +Kanbu Kandarin Kandeeh +Kandid GG Kandonesys +KandrakarsNX Kane +Kane 7687 +Kaneelkameel KanekiKun Kaneohe Kangru Kangst3r Kani +Kaninka Kanned KannonBalker Kannski +Kansas +Kansas Bill +Kansas State Kanseim Kansi +Kansloos Kant +Kantinejuf Kantoo Kantrimees Kanttis +Kanuk Kanye +Kanyeetzy +Kanzeigan Kaolo +Kaolo Spoon +KaozerMauser +Kapaa Kapakala KapeVing Kaphu +Kapiling +Kapitalisti Kapitein Kapiten Kapkeik +Kapkkha Kaporkchop +Kapot +Kapot Slecht +Kappa 73 +Kappa monkaS +Kappa xD +KappaZilla +Kappala +Kappalism Kapsaluun +Kapsones +KaptainPurp Kaptainkilla Kaptains KapteinK Kapten +Kaptn skev KarQ Karaboudjan Karaf Karagoz Karamjob Karans +KarateKon KarazySS4 +Karc KareemPie1 Kareir Karekano @@ -11982,73 +25235,118 @@ Karen KarenMaskin Karethaeis Kargas +Karhu48 +Karhuboiii Karhulohi81 Kari +KariJuice Karies +KariimsPik KarilSummer Karils Karim4lol Karkanii Karkotaseet +Karkov Karl +Karl The SUV +Karl1s KarlS282 Karlee +Karliah Karlit Karlology +KarlosBro Karlteine Karma KarmaRush Karmaa Karmadyl +Karmafox Karmah Karmas +KarnMother1 Karnivore Karnyx Karolik +Karolus6 +KarpyCarpe +Karrak7 KarsanHAM +Karsk kopp Karskeinmies Karso +Karsta Anne Kartelrand +Kartoesh Kartoma Karukas0 +Karumba Karumi Karuu +KarvaBanaani Karvajarru KarvaneMees Karvatatti +Karwos +Kasane +Kasdeya x Kasei +Kaseii 1 Kasejas +Kasen Kaser Kashak +Kasihan Gua +Kasoku Tesla Kasp +Kasperjus Kasprzak1 Kaspuhh Kasraa +Kass Glimmer Kassipotku Kassu +Kassu C Kasuel Kasugano Kasvikko Kat1nr +KatBeatitude Katagon Kataphatic Kate +Kate Bush KateTiffany Katenkos Katetuotto Katfishh Katiensam +Katikene Katikene0 +Katinas +Katiopeia +Katlink5 +KatnissGray +Katraenia +Katrielle Katski Katsuo666 +Katt 90 KattNiP Kattarui +Kattnakken5 Kattnis +Katze btw Katzes +Kauhee Hiki Kaukeneris +Kauldron Kaunas +Kaunas_Rulz Kaunopihlaja Kautschuk +Kavz KawaBonga Kawactus Kawaii @@ -12057,35 +25355,61 @@ Kawaiisaki Kawakuboku Kawkaw Kawked +Kawtik +Kay D KayJ KayWhyPee +Kayazy Kayback +Kaybizzle Kayden +Kayden Boy Kayen Kayla +Kayla Swift +Kaylidascope Kaylizz Kaylon Kayluh +Kayns Main KayranFootly +Kayso Kaytok +KayyPlz Kayzielol +Kayzo Kazatan1245 Kazave Kazaz +Kazcade95 Kazching Kaze8HerOut +Kazify +Kazuma Moon +Kazunni Kazuuhiro +Kc Collector Kcnny Kdash +Kdaw Kdens +Kdragons +Ke bajo +Ke era +Ke nt KeB4NG KeRah Keabler +KeanuCat Keasbey Kebab +Kebab Ari +Kebab Store KebabGuy93 KebabWrap +Kebabov iron Kebbabhallal +Kebbby Kebbe Kebintotero Kebs @@ -12094,35 +25418,62 @@ Kedakaki Kedirav Keebler Keef Supreme +Keef_Man Keegi100 +Keekar Keekers +Keel Keela Keelay Keenar +Keep Le Fe +KeepCup +KeepDistance KeepItWicKeD Keeper1OS KeepitStoney Keepo KeepoKeisari +KeepoNoIron Keepomaster Kees KeesCanadees +Keeslp09 +Keetgracht +Keevon Man Keff +Kegaz Kegern +Kegs +Kegse +Keh O Brien Kehaline1 +Kehno Keiala Keidy9 Keifay Keikoh Keinas18 Keiran +Keiran Perch +Keironn Keisari Keisarinna +Keister Egg Keit KeithMcChief Keithii +Keittokuppi Keizer +Kekaha +KekeLovesMe +Kekkonen +Kekkonen69 +Keksiviikko +Kel Darsam Kela +Kela maksaa +Kela-Olli Kelagang Kelb Kelbikers @@ -12133,11 +25484,14 @@ Kelgone Kelh Kellarivelho Keller +Kells o_o Kelly Kellycollin2 Kelohonka Keloo +Kelps Kelso523 +Kelso561 Keltik KeltonThaGod Keltuzazz @@ -12146,106 +25500,182 @@ Kelvin2GWW Kelvino Kelwus3 KempBush +KempDaShrimp +Kempisch Kempset +Kempy x +Ken +Ken Bolka +Ken Griffey +Ken Kill U +Ken RS +Ken Ten +Ken141 KenBone KenKaniffCT +KenPerm +Kendal x Kendal68 Kendlang1 +Kendrick3691 Kenery Kenesu +Kenfernal Kenleyy Kenleyy_TM Kenmaster Kenn +Kenn y +Kenna Kenndu Kennedy Kenny +Kenny Deez Kenny121 Kenny6397 +KennyKSD +KennyS KennyWhopper Kennyollie Kennypower5 Kennyyyyyyy Kenozh Kenpo +Kensan-7 +Kenshiro Kent KentWasTaken Kentacus +Kentarokins +Kentish Hops Kentucky Kenwood +KenyanChild Kenyann +Kenze +Keonii +Keox +Kep Kephan Keplunk Keppi +Keppi Einari Kepra Kepuck +KerZam Keraliix +Keratin Kerbeth KerfDaddy Keri +Keric Kerk Kerkerino Kermajorma Kermit +KermitTheRob Kernalpotato +Kernautist Keromasev +Kerrr Kertar Kerzara +Kes Sittus +Kesc Kesekui Kesohs +Ket +Ket Baggie +Ket Schep +Ket Uh Mean KetaKnallt +KetaYours Ketabar Ketanator Ketch Ketho Ketnet Ketonall +Ketsah Kettaz Kettu Kettyman Ketwards Keudel Keunic +Kev The Tonk +Kevain69 Kevali Kevb0t Kevbro9 Kevichan Kevin +Kevin Booker +Kevin Framed +Kevin Nguyen +Kevin5-0 +KevinDurant +KevinLawrune +KevinOSeven KevinTes +KevinTheGOAT +Kevinspostal Kevinw20 KevlarX KevolutionX +Kevsin2 Kevsin3 +Kevslays +Kevstrong Kevthebos Kevva +Kevve +Kevzy Kewl Kewlaidman Kewnsauce +Kewwl Kexkaka +Key Concept KeyNoir Keyashes Keydiss +Keyfob Keylock +Keylord Keyney Keyoh Keyori +Keyose Keywork Keyzz Kez0 Keza132 Kezmaya +Keztra +KezzerQ Kezzerina +Kgb Spy +Kgsnipe +Kha Zx Khaant Khabib Khader +Khajgold Khal +Khal Bow Khaled Khaleeeesi Khaleesi1113 +Khalesar Khalisee Khamoshi +Khan of Iron +KhanhDung +Khans Wrath Khanzed Khao +Kharium94 Kharjo Kharn Kharos @@ -12254,10 +25684,15 @@ KhatrickZain Khayri Demon Khazad Khazad Dum +Khazanedar Khazu +Khealim Khest +Khint +Khirean Khiru Khleb +KhooNBust Khoosh Khoppa Khornebull @@ -12265,16 +25700,31 @@ Khovansky Khride Khrollo Khryptik +Khrysus Khufu Khune +Khunt Flapz +Ki Adi Fundi +Ki Arts +Ki Stu GSK +KiD BeeR KiIIa4realz KiLn +KiSMET6 +Kia Jon Kiarama Kibb +Kibeleza Kibisai +Kibito Kai +Kibra Kick KickarseCale +Kickback Dw +Kickbums Kicker +Kickrolls +Kid Inferno Kid K O N G KidClutch17 KidLeaderKTY @@ -12282,237 +25732,482 @@ KidSativa Kidalien Kidchilly100 Kidd +Kidlizard KidneyBean Kids +Kids Bong Kidtrilogy Kidur +Kie Kiedis +Kieftron +Kiek um goan +Kieken +Kiekkoilija +Kiera Kiero Kierzo +Kiewit +Kifooo Kifsa KiiDSKOLiO +Kiinja +Kiinnostaa Kiirii +Kiisu Kiivi Kiiwityty Kiizoru Kijucatm +Kikikissa Kikiniki2 +Kikkel Kikkertje Kikyo101 +Kil U +KilIerDaddy Kilamanjaro +Kilbot0 Kiliann Kill +Kill Crazy10 +Kill Credit +Kill the GE KillConfirmd KillSwitch26 Killa +Killa Cam +Killa Kamali Killa213 KillaSilence Killab0rtion Killabrew Killadelphia +Killadeuce Killamemsta Killaowns Killatonicus Killed +Killed Elmo Killed145 +Killekalekoe Killemall Killer +Killer Jr +Killer Kurce Killer7502 +Killer81093 +Killer9823 KillerFlix KillerSlee +KillerVibes +Killerank202 Killercaster Killerdog HC Killerdustyn Killerkotti Killermatt +Killeroh Killers455 Killertribes Killgor138 Killi +KillianRS Killing KillinxLivin Killjoy4fun +Killjoyer2 Killmankind +Killme5551 +Killmelol Killnloot2 +Killoah +Killsw1tched Killswitch83 Killua +KilluaSam Killzone +Kilminater +Kilo Meter +Kilodoreo +Kilograms KiluaZoldyk +Kim +Kim Chungha +Kim Trails +KimKallstrom Kima +Kima Ronso Kimano Kimbr0 Kimbu +Kimex +Kimi Hendrix Kimoja +Kimosabii KimtonLe Kina Kinaesthetic +Kinboat Kind Kinda +Kinda Blue +Kinda Sinful KindaDerpy Kindaddy Kindom Kindoou Kindozsodln +Kineettinen +Kinetic King +King 0f Gout +King Ankle +King Aussie +King AvonIV +King Blob +King Boned +King Bud +King Bugs +King Chev +King Dong +King Dongo +King Edolus +King Elf +King Elon +King Emurxer +King Flipsta +King Frodon +King Green 2 +King H0d0r +King Ian +King Junkie +King Kabanos +King Kenneth +King Lexius +King Mariin +King Milky +King Nino 1 +King No Fear +King Noc +King Paf +King Rabbit +King Rayman +King Redeem +King Rico +King Runs +King Ruonis +King Seb +King Seneca +King Size V +King Slime +King Snowman +King Spudz +King Swine +King Tsar +King Westor +King XRPL +King Zaros +King davey +King of Imps +King of PvM +King0fHelll King0fSkane King1631 KingAcorn85 +KingAwowogay KingBOO KingBailey KingBoo +KingBuliwyf +KingClark KingCudii +KingCurtis11 +KingDarkVII KingDweebus KingEider KingFlugal KingGoblin09 KingGrekus KingGunshow +KingHawk O_o +KingInYellow KingJacula KingJelore +KingJoey +KingKahuna KingKlick373 +KingKlye KingKongKoen +KingKong_Qc KingLeonidas KingMikeyD KingMongo KingMonk KingMook +KingNate1 KingNathanx KingOfIron +KingOfQuests KingParcival +KingPatVII KingPlAnchor +KingPractice KingRobStark KingRustyVII KingSandCrab +KingScribles KingSizeD1CK KingSoge KingSpirel +KingStyle KingTheGreat +KingTsjubbie +KingValencio KingYoshi KingZac KingZerka +King_Kerran Kingaroo +Kingben +Kingbuddy40 +Kingdom Rush +KingdomBlade Kingeri Kingg +Kinggg +Kingism Kingjake18 Kingmonkey23 Kingofhearts Kingpfx2 Kingpin +Kingpin Xp Kingpk3r +Kingrobster7 +Kingruler456 +Kings67 KingsBluue +KingsGrace Kingspadex42 Kingsta +Kingsthor KingstoAces KingstonWall +Kingsty +Kingz Haki +KingzWorld Kinjello Kink +KinkerScaper +Kinkers Kinky +Kinky Kenny +Kinky Scr Kinkybuns Kinkytoast Kinkyy +Kinno +Kinobles Kinokird +KinokoZoku Kinp +Kinsaic Kintoki300 Kiopley2 Kiox +Kipee Anneli Kiplup Kipnuggets Kippenbro +Kipsel +Kiptandori Kiqz +Kiraci Kiraga Kiraly +Kirara +Kirbi Smart Kirbngo +Kirbsey +Kirby Kirby7670 +Kirchberg +Kire1n +Kiree +Kiriel Kirimah Kirito +Kirk4 +Kirk97 Kirkburton1 KirkyBeast +Kirne Kirrion Kirry Kirstin Kirthor +Kirumibe Kiruzonu +Kirx125 +Kirz Kisa +Kiseki Kisizel Kisle +Kiso Valley Kiss +Kiss Kiss +KissMeHomies +KissOfFire +KissOfFury +Kissahomie69 Kissanpentu Kissmyase111 Kist +Kit Fistoo +Kit10Kat Kita +Kitashan +Kite Solo Kiteman +Kitfox IV Kitsch KitsiKitty Kitsune +Kitsune Kami +Kitsune Ness Kitsunemimi Kitten +Kittenz Kitties +Kittle Bits +Kittoh Kitty +Kitty Perry +Kitty v2 KittyMeow83 +Kittymouse 1 +Kittys Newb Kiusatus Kivespulla +Kivick Kiwa Kiweh Kiwi +Kiwi Icons +Kiwi Stona +KiwiIskadda KiwiMacJ +KiwiSteve +KiwiTheBot Kiwiana Kiwidude Kiwiskurt Kiwwion +Kiyak Kiyoko +KizJ Kizminsky Kizone +Kizz mo Kizza +Kj Kai KjellEllen +Kjellberg94 +Kjomo Kjottfifaan Kkobe +Kkobugi +Kkokkom +Kkoppa Kl2AZY Kl3RAN +KlDDO KlLL +KlLL 4 BONES KlMI +KlMpossible KlND KlNG +KlNG MlKE KlNGY Klaar +Klaarkomer +Klaasie Klacky Klanezy Klanks +Klankss Klapzak +Klarence Klariany Klarna Klaskdeng +Klassic +Klassified Klatscher +KlausLittle +Klaussie Klavan +Klavelon KlazBooy Kleatus Klebold Kleened Kleiades +Kleine bolle Klementtii +KlemmDawg17 Klemonhaze Klengie +Kleo +Klepdiezle03 +Klepp Kleptic Kletz KlewKlew KliKlack +Kliewer Kliffa +Klik gebit +Klikke +Klingons Klippzz +Klo0 Kloefklapper Klogin Klonzyon +Kloofiool Kloorijoodik +Kloot-Zuk Kloover KloreCore +Klotho +KlovneKrabbe Klowdstr1fe +Klub Dubx Kluftritter +Klumpy Klumsie Klunchkey +KlungePlunge Klunkii +KlutzyKay +Kluuntje +Klvtz +Klyd Kmac KmartWorker +Kmd +Kmie +Kmk_Yawgmoth +Kmorken Kmtfwtm +KnD xP Knaap Knabbelbaars +Knabbernossi Knacker Knakenstein Knaksaucage @@ -12524,77 +26219,146 @@ Knaught Kndd Knead Kneeeled +Knewby8 KngBlkDrogon +Knickers +KnicksNati0n Knife +KnifeStory Kniffes Knight +Knight Crip +Knight Drake +Knight Jo +Knight Mors +Knight of 3 Knight50 +Knight522 Knight5247 +KnightKettle KnightMike KnightO +Knightcrawle Knightenator +Knightlock +Knightmare +KnightmareNL Knightrainy Knightromite Kniili Knikkerbal Knivezii +Knob End +Knobin Hood +Knod with Me +Knoo +Knospi KnowMadss KnowPurpose Knowing Knowledge Known +KnowsNoFear Knoxville333 Knuckle +Knuckles +Knulle Knummi Knurrbauch KnusCaboose Knusseprulle +Knut Knut +Knwn +Ko Addiction +Ko D Ur Dead +Ko0tje KoBe +KoH Zoro +KoPvM +Koa +Koak Koala +KoalaBear819 KoalaBwala +KoalaHeist +Koalarobe +Kob Bryant Kob3oshii +Kobakat +Kobayashi89 Kobe Kobenna +Kobi btw Kobold Kobushi Kochelas +KochiiBear Kocjancic +Kocyte Kodai Kodak Kodax Kodeth Kodfunk +Kodie Kodipar +Kodo +Kody IRL Kodywithac Koekebakker +Koekenpan Koekienator Koelkast1 +Koelkast3120 +Koelogg +Koemi +Koenfu +Koeppy +Koerdistan Koff +Kofferbak Koffie +Koffie Shop KoffieBoer Koffiekan Kofnx +Koga09 Kogarah +Koge +Kognito +Kogsin +Koh Me Lo Kohda +Kohrosian +Koii Diva Koka Koki KokiriSword +Kokki Kokkue Kokkugoburin Koko10tkd +Kokoftu Kokou Kolade123 Kolariah +Kolarino Kolbot +Kold Pizza69 Koldbetrayal +Koldz +Kolicee Kolmay Kolmiojuuri Kolodinsky +Kolomit Kolton Komai Komarov26 Komijn +KomisarzFlak Kommunist +Komog Kompact Kompania KomradeScape @@ -12602,61 +26366,125 @@ Komugi KonDaTV KonKai Kona +KonaTheCake KonaTheGent Konami +KonarMilkies Koncept Kong Kongen3609 +Kongherodes Kongklunk Kongmoakim +Kongon Musta Kongz +Konigs Tiger Konigsblau +Koningnoob +Konjakkia Konkelbearet Konkuuu Konnie +Konnor Ray +Konny KonosubaAqua Konroy11 +Konstiq +Kont Crumbs KonteNeuker Kontentti Kontoret +Kontrafakt +Konu Kony +Kony4ever +KonyRomo +Konya Slayer +Koo +Koob +Kooben Kooch50 +Koochie +Koogs +Kooiker +KookieDough +Kooky Kal +Kool Aid76 +Kool Hwhip Kool Iron KoolKriegs +Kooleey Koollpop +Kooloo Limpa +Koomar Koomorang +KoontzyJr +Kooopa Koopa +Koopa Kash Koopatrol Koopley +Koops +Koothi Jr Kop0nen +Kopet +Kopites +Kopn Alt +Kopoes +Koppa Olutta +Kopra_0nu +Kopzilla0 KoqPuuser Korado Korail +Koral64 Korangarr +Korasko +Korazi +Korbet KorbolJestem +Korby_K +Korea KoreaBread Korean +Korean Neet Korelivia Korihoko Korisas +Korkesh101 +Kormulus Korneel +Kornettos Korok Korpokkur Korravalvur Korsair +Korsan Kortti KosChiquiss +Kosaki +KosarevSpawn KosenRS Kosey +Kosha Engler +Kosken Kovin Kosmckid +Kosmo +Kosra Kosst Kossukissa Kostaja123 Kosteezer Kotaki95 +Kothfan2 Kothfan3 Kothu +Kotimaista Kotkatapult +Kotoe +Kotov +Kottis +Kotze Koucii Kouen Kouhais @@ -12665,111 +26493,227 @@ Koulupummi Kourend Kourk Kov0s +Kova Kova Kovacs +Kovacs Bela Kovaley +Kovalux KovidKai Kovit +Kow +Kowawa Koxu +Koy +Koy5 +Koyix +Kozileks +Kozmic +Kozojebec Kozyshack +Kpiy Kprs +KpyosX +Kq Kr0jm +Kr149 Kr1sten Krab +KrabbiePatty +KrackScape +Kradoth +Kraff +Kraft Slave Kraftra Krafty Kragjay +Kragwa +Krahhling KrakaJ Kraken +Kraken Beerz +KrakenSnacks +Krakenarse +Krakenmom +Krakkars Kralik Kralovna +Krammetje +Krana +Kranky Kraut Kranox +Kransie KrapNSchitz +Krapinschitz Krappa Kraq +Krasznahorka +Kratic Kratje Kratos Kratos-Arepa +Kraujukaz Kravcik +Krawall +Kray +Kraytoast +Krayz818 Kraz3d +Krazed Zen Krazezor Krazy +Krazy Kramer +KrazyKillah3 Kream +Kream PIE KreampieKing Kreams Kree +KreeM_Pies4U Krel +Kreme Krispy +Krepe +Kreshink +Kreupel hond +Kribo KriegFleisch Krigare Krigersej Krigsgaldr +Krikkos Krile Krillin +Krillin It Kriltar +KrimenReborn +Krios Kriptog +Kris 2 +Kris Kross +Kris Tis +Kris Toffer KrispCowMilk KrispyCow +KrispyJello +Krispz +Kriss42 +Krisse Krisstian +Krisstof Kristina Kristo1337 +Kristoh +Kristops KristySlays +Kristya Kriszx Krith +Kritters Krizalid Krizee Krllykins +Kro Kroeg +Kroekoek Kroer1 +Krogan +Krohmos +Kroketten +Krombop Mike Kromuh Kron0 KronScape +KroniKStyL Kronic KronicPlague +Kronic_gtt7 Kronjuvel Kronoryx +Kronstedt123 Krontio +Kropium Kross +Krownax +KrthisIrnhrt +Kruber KruimeIkoek Kruisboog Kruizar +Kruncha +Krusch Qc Krusk09 Krustorb KruttGutten Kruuxt +Krvavec +Krw Kryder Kryderman95 +Kryl +Kryllz Kryoge777 Krypsiss Kryptanite Kryptic +Krypto Pup Krypz Krystalbead Krystalized +Krystie Krytl0rd +Kryxon KryyptCeepR Kscott +Ksed Ksteg Ktran4 +Ku Kuaalo Kuanta +Kubanna Kubfu +Kubiak +Kuchera Kudos +Kudra Shade Kudsk Kudt +Kuemper Kufke +Kuger +Kugi Kuha +Kuhis Kuhki +Kuhnlicious Kuhvon +KuhwazyyPVM Kuhz +KuidaoreTaro Kuistikopone Kuittis +Kuji Otoya +Kukii +Kukko +Kuksukka Kulak Kuler Kuli +Kullilutku +Kullirausku +Kumara Fries +Kumduh Kumeku +Kumetis +KumikoOkada Kummars +Kummens Kumoga +Kumonyru +Kunakana Kunaphela +Kundalini888 Kung +Kung Aguero KungFuKennyy KungFuhr3r KungFury01 @@ -12778,18 +26722,25 @@ Kungler Kungzaki Kunie Kunkku289 +Kunkulu Kunsel +KunukGL Kuola +Kuollu Homer +Kupla +Kuppi KurSiens Kuran Kurasaki21 Kurask +Kuratus Kurayamii Kurdishtan Kurfue Kurgan Kurib0hh Kurim +Kurios Kurko Kuro Kuro6757 @@ -12798,141 +26749,368 @@ Kurohige-Jm Kuroma Kuroshin4 Kursdragon +Kurt Cocaine +Kurt1sdbr +KurtMaxed Kurtan +Kurtismo789 +Kurtiz +Kurtowogei Kuru Kurumin +Kurums Kurune Kurza Kurzgesagt Kurzi Kurzol +KusOnRNG +Kusai Kush +Kush 999 +Kush Grey +Kush Nerd KushWizdom +KushalaDaora Kushanada KushedKnight Kushies +Kushioned Kushkhalifa +Kushmooms Kushtyyy Kusiaks Kusimuna +Kusimuna JR Kusle KusmarPavola +Kuso Saiko +Kut Jack +KutInternet Kutasy +Kuthay +Kutirons +Kutkip +Kutori Kutunawa KuuDuu Kuudere +Kuulus +Kuuw Kuvakei Kuwolski +Kuxx +Kuykendoll +Kuzh +Kuzi +KuzzzTruckin +Kvacky Kvamsdal +Kvaoathe +Kvzy Kwadraat +Kwakske Kwambam Kwan +KwanDynasty3 +Kwani Kwarkark Kwastaken +Kweem Kwei +Kwep Kwieppie Kwintal Kwondeo +Kwong Kwongo KwuarmFarm KxKxW KxNoTTz KyIll +KyPolar +KyWi Kyaandere +Kyafa Kyberpaavi +Kye187 +Kyeb KyeeG +Kyelee Kyersago Kygehn Kygesm Kyhlen Kylanater Kyle +Kyle 8990 +Kyle Esq +Kyle G +Kyle Kmac +Kyle VA KyleFammm KyleGrounded +Kyledog829 Kyler +Kyler Moss +Kyles Cute +Kyles GIM +Kylesteven +Kylewwashere +Kylex Kylianvb +Kylliel Kyloman Kymeister +Kynodontas +KyotoSadness Kyouan Kyouko Kyouma +Kyouna Kyouran +Kyphrus +Kyps +Kyr0s +KyraXIV +Kyrakishuun Kyrdaar Kyrie Kyrist KyroThanatos +Kyroba Kyronius +Kys Ironmen Kyski +Kytkinpommi KyuubiKurama +Kywt Kyykin +Kzyl +L 0 S T Y +L 3 G 4 C Y +L 67 +L A R A M S +L Ben +L CBO +L D A +L E G E N D +L E G O +L E L O +L E P I +L F C +L FC +L Hus +L I N U X +L I V M +L OAFS +L S Q +L U I G +L U U K E +L X R D S +L achie +L aika +L aka +L ama +L ang +L apras +L atias +L aw Rune +L aze +L e an +L eafErikson +L egs +L ek +L emaster +L ev +L i m a a +L iamm +L iar +L ilo +L inox +L ions +L o w g +L ockdown +L ofty +L osi +L paradoxum +L u m i +L u mi +L u x +L ucas +L unatic +L00000 +L00M L00OL0OO00OL +L00T SNIPER +L00tacr1s L00termember L0G0 +L0GI +L0L L0L0LL0L00LL +L0RA L0RD L0RDGAINS +L0ST S0UL +L0Z L0kur L0rd +L0rd Arthur L0rdMullett L0st +L0vecraft L0ves2Splooj L109 L115Squirtle +L1L GN0ME +L1ghtweaver +L1l bits L1ncoln +L1ndman +L2 L2Crash L2D3 L2Loki L2love L2mmutaja +L2sit L2tankbandos L2tob +L337 GodHand +L3RKON +L3V3L L3apOfFa1th L3gg0 L3mur +L3prec0n L3sius L3tMeBreath +L4D2 Enjoyer L4rry L4st +L522 +L64 +L86A2 +L8CP +L8ers L8rT8r +LADFS LAMAFAO LAMARJACKS0N LASBE +LAUFY +LAZY88 +LB9 +LBS M +LBaccer +LC33 +LCpl +LE0 MESSI +LE54SON LEARNINGTHIS +LEGOSl LEN0 LENZ +LET ME COOK +LEWlS +LF Content +LFG 69 LFGrills +LG 8anter LGBTQLMNOP +LIL BLESSED +LIL PRINCE +LILKHALAMARI +LIMEWORLD LIQUICITY LITEIT LITHITS +LJ 8 +LJAP +LJPalmer LKIT +LL Trigger +LLAMA_ears93 +LLIRSHSLSIEi +LLY Duramax LLeffe +LLich LLol +LMAO LOL KEK +LMAOImDying +LMFAO IRL LMFAOIRL LMNOP3 +LMParrot +LN41 +LOADED_AR +LOGAN109 +LOGlC LOH3 +LOL BMW +LOL MAD LOOP1456 LOOSECOOCHlE LOSTinGAMES +LOUlSlANA +LOWIQXD LP Smokie +LRG LRGD LRichyy +LS1 +LS3D +LSD-25 LSDDS LSDe +LSDeezNutttz LSDonny +LSDreamy LSxD LTUD3stroy3r +LTapperz +LUBRICAT0R +LUKA DONClC +LUR3ME +LURED BY ROT +LUTlN +LVN iZN0 +LWE +LXFY +LYAM femboy +La Benezra +La Bollita +La Brebis +La Croix +La Fiesta031 +La Frontera +La Moo +La Porta +La Sopa +La7itude LaCroisssant LaFroob LaLegende LaMachCaron +LaMarii LaPichula +LaRS 07 LaYdlN Laaban +Laadvermogen Laady +Laagvliet +Laaki +Labas Utak LabbatBlue LabbattSplat Labbis +Labor +Labstev +Labundo +LacDeaths +LacedKoolAid Lacedonian Laceinyoface Lachosocko @@ -12940,82 +27118,160 @@ LachysMain LacinorI Lack Lacking +Lacking IQ Lacoline Lacraio Lacrymosa Lactosite +LacusClyne +Lad J Ladbrook Laderstall Ladme +Ladrian Lads Lady +Lady Calais1 +Lady Chompa +Lady Devil +Lady Porky +Lady Storms +Lady2022 +LadyBuck +LadyGagaTbh LadyJan +LadyJan BTW LadyJessicaL LadyMidn1ght LadyOfCyprus LadyOfMagick LadyPidge +LadySaurus94 LadyStarlite LadyStorm83 +LadyVamperic Ladydoll Laedzter Laeretes +Laethia2 +Laetor +Laf +Laffam Laffy +Laffy Taffy +Lafondaa Laftonn +Lag out LagArtist +LageLanden Lagerhaus +Lageri Lagg Laggbeer +Laggro +Laggy Brain +Laggy Clicks Laglet +Lago +Lagodzacy +Lagomancer Lagoon Lagrange Lagscape +Lagu +Lagwagon +Lah Di Dah Laharl +Lahn +Laid +Laid bare +Laika Wolf LaiskaJake Laiskiainen4 Laitoin Laitti +Laitue +Lajer +Lajfi Lake +Lake Show +Lake Valor LakeMonYew Laker Lakeshire +Lakka +Lakonic Laksa Laku +Lakuni +Lakupiippu Lala +Lalochazia Lalundi +Lam lul +Lam_12 Lama Lamanent Lamb1237 Lambretta62 Lambs +Lambzilla Lame +LamePuttE10 Lamented +Lamfear +Lamh Lamie Lamiia Lammen Lammy +Lamns Lamp +Lamp Burner +Lamp master Lampepit Lampyy +Lampzki +Lamshnarf +LanJiaoDuaKi Lana +LanaLuna +LanceDaPantz +Lanco Lancy Land Lander Landeskoging Landlord Landofzoa +Landucey19 Landyll Laneeta +Lanell Latta +Lanesstee +Lang Chang +LangeNieWies +Langeboy Langecries Langner Langosman Langscape Langtu102 +Langutan +Langzzy +Lanier +LankFrampard LankaKekw Lanky +Lanky Josh +Lankyfeed Lann +Lanny Pan +Lanoue +Lanpzki Lanrico LantadymeRey +Lantern Snow Lanx Lanzlol Laogai @@ -13025,69 +27281,142 @@ Lap0tai Lape Laphloredos Lapsa +Lapsapp Lapsivesi Lapua +Lapuz +Lapy +LaquishaBaby +Lar0i +Laraelias Larcadum Larcenex +Lard Jaysus Lare Lare240 +Larecia Larecio +Larenz Tate Large +Large Chompy +Large D +Large Npc +Large Tasty +Large Toads LargeExpLamp +LargeGrandma +LargeZock +Largelad2 +Largeprune Larie Larissa +LarksTongues Larkypoo Larotux +Larrey Larry +Larry 0G +LarryB LarryIsHere Larrys +Larrys btw Larryz +Lars Ohly +Larser +Larsinosrs Larsjns Larso +Lartsi +Laruka +LasBoi Lascooby +LaserLad LaserSchlong +Laserati +Lashi Lasjstts Laska +Laska Siara +Laski +Laskii +Lasne LasoliLeiffi +LassT Last +Last Bison +Last King +Last N1te +Last Stages +Last Texan LastAttempt +LastBoss LastHours +LastMark LastRecalI LastTexan +LastWookiee Lastinis +Lastkaiii Latanoprost Late +LateKnight LateOwl Lateksiuljas +Latelaturi Latero123 Latias Latins Latissimus Latitude Latompachy +Laturaivo +Lau396 LauQT +Laudine +Laufeyson965 +LaughTale XD Laughed Laukage Laukie +Laukki1 Laundry +Laundry Room LaupieLaupie Laur +Laur ex core Laura +Laura J +Laura uwu +Laurat J Lauren +Laurentina Lautanen Lauw LauweEgberts +Lav x Lava +Lava Buster +Lava rune +LavaFountain LavaKitty Lavadude42 Lavafrost +Lavagirl420 Lavak +Lavak Bob +Lavanis Lavasat LavendrGoons +Lavigne +Lavina26 +Lavios Laviuthen Lavvv LawOfBirds +Lawesy Lawfox +Lawhrer +LawlAsYouDie Lawlie Lawliet Lawlimon @@ -13096,96 +27425,221 @@ Lawn LawnChair48 Lawncat Lawnmower73 +Lawre nce +Lawsilk Lawson +Lawyer JD +LawyerGirl24 +Lax_315 Laxar Laxx +Lay +LayDead Layden +Laydwnandr0t Laydyn Layes +Layes X +Layezy Laylaa +Lays Layzi +Laz GIM +Laz Lo Mein Laz2510 +Laza Ferro Lazer +LazerVizion LazerWork +Lazgo Laziest Lazikiel LazloDaLlama Lazy +Lazy Fare +Lazy Jazz +Lazy Lump +Lazy Matt +Lazy Mauler +Lazy Moo +Lazy Shell +Lazy Soul +Lazy Stona +Lazy XP LazyB0y +LazyBoneZone LazyDevon LazyFarmer LazyOwner +LazyThom LazyTurtleRS +Lazydrink Lazyie_KiD +Lazysmokes LazyyySloth Lblacc Lbuzz +Lck Lda237 Lder +Lds +Le Bibu +Le Biff +Le Big Sad +Le Catptain +Le Doda +Le Foole +Le Gio +Le H0NK +Le Jeffeh +Le Peanut +Le Petit BH +Le Pogo +Le Reject +Le Stu +Le Sus +Le Tom +Le von +Le4f +LeAUD +LeB0ng James LeBlownGames +LeBoobie LeBrianJames +LeDamos LeDerpski +LeIronJims LeKinguin LeLuuk +LeMontBlanc LeMoonMan LeMoopey +LeNnEeX +LePeach +LeVarrock Lead Leader9922 Leaderless Leadfeathers Leadley +Leads Dead Leaf +Leaf 7 +Leaf Parker +Leaf998 LeafStoneDab +Leafffy +Leafpool Leafyshade +Leaga +League Brain +Leak +LeakedDMs Leaks Lean +LeanFavaBean Leanlce44 LearnCatMeow +Learningosrs Learti Lease0fLife +Leather Top LeatherJan +LeatherRat Leatherr +Leaux Key Leavepigrun +Leb Crotch +Leb Man +Lebanesee +Lebennn +Lebor +Lebowski2033 Lebrons +Lebusoft Lebzima LeccaJr Leckie12 +Leclerc 2024 Lectaminol +Lectosh +Lectrix +Led2000 +LedXia Ledgendairy Ledning +Ledu +Lee +Lee Ratt +LeeFelix LeeGavGav LeeHen +LeeV_V Leecherboy Leechy2399 +LeedsUnited Leegotalo +Leeleebug210 +Leemer +Leemi +Leemo Leer0y Leerjet Leeroyy +Leers OSRS +Leeshore LeesusChrist Leet +Leet Blues +Leet Bug Leetroopa Leeuwarden Leevar Leezy Lefonzeee +Left gf 4 Xp +Left inPeace +LeftFistt +LeftHerFor07 +LeftHerForRs +LeftTwix Leftist +Leftwich22 Lefty +Lefty-x +LeftyWarrior Leftytexan +Leg Day 99 Legacy-Blade LegacyOfErik +LegalCounsel Legalism Legally +Legally Dumb +LegallyAfk +Lege Legend +Legend 0007 LegendHarold +LegendKingz LegendOfShao LegendSuz LegendaryDTM LegendaryFoe +LegendaryLVP +LegendaryMe LegendaryRS LegendarySte +LegendaryZ0 +Legenddiary Legenddreams Legendelek +Legendish +Legends Epic +Legendsam7 Legened248 +Legggggooooo +Leggo Leggy Leggz Legikt @@ -13194,17 +27648,29 @@ Legion2410 Legionals Legislatore Legit +Legit Ape +LegitGarbage LegitSamuel +Legitidrown +Lego Brick Lego Fisher +Lego Mania X LegoMyBob +Legolas +Legolas I Legolic Legoliker999 Legosas11 +Legosaur +Leguminati +Leha +Lehawek Lehmo Lehnert Lehoir Leid Leider +Leidmavo Leif LeifBestLord Leiff @@ -13212,16 +27678,27 @@ Leigh Leilin Leimstiift Leion +Leist1nas +Leistus Leito +Leitwolf +Leivermorale Leivonnaiset Leiza +Lejj BTW Lejoon +Leka xo +Lekira97 +LekkerMoeder Lekkeri +Lekray Leky LelSickMeme Lelalt Lelbow Leldorin +Leldra +Lell Lelott LelouchV Lelysia @@ -13229,113 +27706,230 @@ Lemako Lemillion141 Lemiy Lemke +Lemmelleni Lemmy LemmyThePerv Lemon Lemon5000123 +Lemon9000000 +LemonTart +Lemonade max +Lemonguin Lemonmooffin +Lemonowo Lemonrider +Lemony Earl Lemonz +Lemosgomes Lemphys Lempsu Lemurcow Lemuria88 Lemursnore +Lendtable +Lenegis +Lenel Devel Lengzz +Leni Epiza Lenience3 +Lenify Lenlami +Lenn375 Lennie Lenning +Lenny Euler LennyPro +Lenovel Lenreys +Lenses Lentiano1 Lentil LenvisCZE +Lenya +Leo Gagner +Leo Messi +Leo The Fish +Leo12_1993 Leo2 Leo96 Leodero Leoma Leonatwo +Leonbozz LeonidasIV +LeonidasThor LeonidasXCIV Leonl Leontje Leorio Lepek38 Lepkilla +Lepra Leprechau Leprincias Lerch +Lernaean +LeroyDanknz Leroyvdk +Lerzbot LesGetIt +Lesbean Lesen Leshrac +LesleySnipez Less LessIsMore Lessar +Lesser Gods +Lessking +Lestamsakul Lestersaurus +Lesva +Let Us Dream LetBrettBang +LetJimCook Lethal +Lethal Blade +LethalClick LethalMortal Lethally +Letharil +Lethwei +Letits now LetrahL Lets +Lets Blaze +Lets Boss +Lets Glide +Lets Plop OK +Lets Ride +Lets See +Lets Toke +Lets Ziggy +Lets pep LetsGetSmity +LetsGetem LetsRouQ +LetsgoDaddy Letsjjj +Letspoint Lettersloth LettuceLegs +LettuceLime +LettuceNut Lettuce_8 Lettulainen +Leturpentinr Letz +Leukaremmi +LeukemiaLord +Levante Frog Level +Level Denel +Levelations +Leveldegree Levi +Levi Squad +Levi lmao Leviate +Levibeelevi +Leviud +Levven +Levyiah +Lew Sanus +Lew sid +Lewd Queen LewdTouchMe Lewdberrypie Lewey Lewf Lewfu +Lewhh Lewir Lewis LewisMcLaren +Lewis_y Lewism22 Lewison +Lewiss Lewithetui +Lewu +Lewwiis LexaSteel +Lexatrax Lexay Lexdegekte Lexer +Lexington73 Lexkai Lexxi Lexy +Leyon +Leyr +Leysim Leyton Leyzen +Lezio7 Lezley +Lfts +Lhk +Li am +LiI Tii Lii +LiT Clutch +LiT on Dabs LiTxEXODlAx +Liam McPoyl +Liam1994 Liam6780 +LiamLate +LiamLollypop +Liamas Liberate Liberaxa Liberty +Liberty Cap Libolik +Libracorn Librain +LichKiing +LichOneeChan +Licharus Licht +LichterLo +Lichtert +Licitness Lick +Lick My Wyrm +Lick Time LickAhrim +LickMcFicks Lickeris Lickilicky Lickumss +LidawgMcChad +Lidless +Lidlman +Lie Lie4it +Liebzer +Lies of S +Liet Katsu Lietuviskass Lietuvisz4 +Lieve +Lieven Lif3 Lifal Life +Life Road +LifeInsAgent LifeIsBaked LifeIsRockie Lifeform Lifehunt +Lifeisnow13 Lifeliners +Lifelulz Lifes Lifes12Rules Lifesteal @@ -13343,247 +27937,528 @@ Lifestyle Lifewaste Lifezajoke Lifticus +Lifting Fe +Liggen Lighning Light +Light Ace +Light Shell +Light age II +Light1324 LightAura LightB0ne LightRigger +Lightarrg255 Lightaxo Lighten LightenUp Lighter Lighterfalz +Lightfister Lightg0d Lighthead45 +Lightlord440 +Lightning MF +Lightningess Lightqt Lightstoria +Lightww +Ligma Balzaq +LigmaMufin +Ligt Lihatanko Lihtnenolife Lihtsurelik Lihu +Liiga-Ari +LiikeAGlove +Liite Liitokissa +Lijk +Lik me knie LikMijnRaid +Lika C Likalatopus Likark Like +Like Saint LikeABrother LikeAGloveee LikeCinnamon LikeToetally Liketocombat +Liko Likrot +Lil Callisto +Lil Dickyy +Lil Donut +Lil Dor +Lil Doss +Lil Eso +Lil Fika +Lil Garbo +Lil Hogg +Lil Knight +Lil Koda +Lil Lilyxo +Lil Lotus +Lil MCM4A1 +Lil Moe +Lil NllLO22 +Lil Rat Mann +Lil Roli +Lil Shay +Lil Stoma +Lil Tragic +Lil Weeezy +Lil Woowoo +Lil Yeeter +Lil Yungen +Lil Zeusy +Lil Ziik +Lil Zimp +Lil parasite LilBirb +LilBlueMew LilBobbi +LilFaulk LilGBigThing +LilGay btw LilHorny LilMissSlays +LilNubbins +LilPeepBoi +LilSeany LilSquidgy +LilSteamBoat LilStonks +LilSuzieVert LilUziBlyat LilWitness +LilYungChitn Lila +Lilac Devil Lilangrydude Lilbobsters Lilchris Lildirt +Lildischarge Liles Lilhotshotv2 Lilinss Lilith +Lillia n Lillie Lillyz +Lilmoose99 Lilnenedemon Lilqtforeva +Lilsauce72 +Lilsutts Lily +Lily Mayy Lilyalatea +LilyaxD +Lilypily0 +Lilysaurs +Limb +Lime Light +Lime Season Limed +Limeguy21 +Limewire +Limit Form +Limited Room +Limiwinkz +Limiy Limmert +Limmy Limo Limp +Limp Lime +Limpsioo Limpwurt +Limyt Linalool +LincolnButt +Lind say Linda +Linda Lou Lindegaard +Lindewyn Lindsey Linearr LinedFury +Linelis99 Linen +Linen Cry Linerz +Linewa Liney Lingwood Linh +Linhson Link +Link Adam +Link Click +Link Noises +Link Tribute LinkKing +LinkTheIron LinkedList Linkedln +Linkin Boy33 +Linkinaz Linkmoon Linkseratten +Linkv21 Linnara Linsey Linsunt +Lintell-lad5 LinusEkedahl +Linxis Lion +Lion Gin Lion-021 Lion0fZion Lionbatdog Lioncheart +Lionclaw Lionelliee +Lionheart +Lionheart Xl Lionhrt +Lionyxia +Lioui +LipShits +Lipalow Lipperr +Lippy Jimmy +Liqu +Liquar Liquicity46 Liquid +Liquid Apple +Liquid CSGO +Liquid GZA +Liquid Mire +Liquid Nexus +Liquid Reign Liquid8 LiquidRmt LiquidTheory LiquidTrails Liquidat0r +Liquidated +LiquidatorRS +Liquidwood0 Liquified Liquir LiquorGrain +Liqwid +Liridon Lirrix Lishenna Lisica +Lisle Liso +Lissino Lissoms Listeffect Listen2me ListenMorty +Listerine_TC Listics +Listifyy Lisuna +Lit Dawg +Lit Guy +Litas +LiteForge +Litefooted Litelii +Litem Liten +LiteralCow +Literic +Lites Evil +Litey Liteyr +Lithassa Lithuano Littens +LittieTover LittjeterRS Little +Little Allie +Little Flirt +Little Jaxon +Little Knob +Little Sloth Little Snor +Little Ticks +Little Twig +Little meow LittleGhosty +LittleIron +LittleNudger +LittleTrev8 +LittleWillis +LittleZorro Littlebluefe Littleblueju Littlechirru Littlefarms1 +Littlefire01 Littleguyz +Littletickle +Litto +LittyNoCap Litvintroll +Lium Liuo Liutkemenas +Livahpewl +Livand Live +Live Jaked +Live Moose Live2Win Live4thefigh LiveItRight LiveLoveAsap LiveYourLife +Livedasniper Livepan +Liverpewle +Livey +LividPharm Living +Living Life +Living Lust +Livingenemy +Liviu230 Livvii LivyLo Liwyn +Liyum +Lizard Siege +Lizily Lizinginis +Ljb Ljudmila Ljuu Lkarch +Lkky +Lkn Lkoi +Lkue LlHAPIIRAKKA +LlLY ALLEN LlLYUFFIE88 +LlMEWlRE +LlNT LlON +LlSA ANN FAN LlTEWORK LlTT +Ll_lK3 Lla234 Llama +Llama BTW +Llama Pharm LlamaDawg LlamaMcfenis +Lleucu Ann Llirik Lloydyy +Lluuk1 +Llychlynwr Lmao Lmaz +Lmfao Lmlxlk +Lmmortai 07 Lmsjfjksdnhb +Lmurs Lncln +Lng +Lo Kii +Lo My God +Lo cation Lo07er Lo0pyy LoGiiKBah LoPintos LoadMySkeng +Loaded Loadizzle Loadstar LoafOCelery +Loathed Kmd +Loathing +Lobb Dad Lobby +Lobby Two +Lobo Blanco +Lobo Sonora LoboStark1 +Lobot96 +Lobotomizer +Lobstars +Lobster12 Lobstero Local +Local FEmale +Local Idiot LocalHero7 LocalJoint +Locale Lochi LockDownLife +Lockdown v2 Locko Lockpicks Lockski +Locksnap Lockssley +LocoDoritos LocoHamsterz Locococonut +Locothegenie +Locrian +Locton +Loda Lodarion Loders Lodestar Lodestones +Lodgehunter +Lodiedoo +Loebas Loeffen +Loez +LofaBred Lofi Log62 LogHog8 +LogHunterKaz Logan Logan2x Loganator34 +LogansPrayer Logavano LogiTekton +Logia LogicTerror +Logical God Login +Logitech +Logitekton Logless Logos13 LogsKnog Lohan Lohkey Lohruken +Lohwi Loikoi +Loikoi Lee LoisGriffin1 +LokieDokie +Lokolow Lokos +Lokrand Lokur +Lol Ur Dead Lol466 Loladactylll +Loldg Lolek +Loli Cox +Loli Neko +Loli Pantsuu Loli-Remain LoliChan LoliElie LoliStrangla Lolicons +Loligagging Lolipoparty Lolitsleeroy +Lolmanever Lolmc Lolopipop Lolwierdo Lolwuts +LomLy Lombachs Lombardi Lomborghini +Lome +Lomobuu Lompardo Lon3y Lonan +Lonan Arikos Lone +Lone Gym Rat +Lone Lee Axi +Lone Pop +Lone Requiem +Lone runkero LoneCorp LoneMage LoneStarWit Loneful +Lonehenge922 Lonely +Lonely Eevee +Lonely Neo +Lonely Norms +Lonely Ride +Lonely Salty +Lonely Slave +Lonely Table +Lonely Tugs +LonelyLight LonelyOnT0p LonelyRS +LonelyTugs Lonelyy +LonerSushi +LonesomeSoep +Lonewolf117 Long +Long 4skin +Long Demon +Long Ol Dong +LongBoneee +LongRodGod +LongSnapper +Longbow +Longest Head +Longie Longjohnz +Longmeatlog +Longnech +Longo Doggo +Longstaf +Longsword950 +Longview Longwave +LongySlongy Lonjick Lonksu Lonz +Loo p LoofiePoofie +Loofoo +Loogs Loogy Look +Look out bro Looked Lookin Lookingman @@ -13591,62 +28466,166 @@ Lookn4Puzzy Lookout Lookup Loon +Loon Master +Loonetick jr +Looney278 +Loongstickyy Loonlette Loony +Loony RS +LoonyLunar Loonykilla +Loonyluke5 +Looolo LoopGoon +LoopSwoop Loophole336 LoopieFish Loopy586 Loose +LooseAnos LooseLesley +LoosebuLdge +Loosh +Loot Chemist +Loot Party Lootcifer Looted Lootedyou2 +Lootorz Lootrich Lootsharing +Lootsi +Lootski +Loox +Lopmkinjubhy +Loppy Killer +Loquwsea321 Lord +Lord Amonite +Lord Bees Lord Buud +Lord Bv +Lord Caldlow +Lord Conte +Lord Cryer +Lord Cypher +Lord Devil +Lord Doofy +Lord Elfen3 +Lord Extropy +Lord Grefven +Lord Grim +Lord Grofyth +Lord Guam +Lord Hents +Lord Jebbe +Lord Joona2 +Lord Jostyh +Lord Keithus +Lord Kratos +Lord Loss +Lord M0RG0TH +Lord Mantra +Lord Masonic Lord Mjosh +Lord Of Cows +Lord Pengu1n +Lord Pillow +Lord Richie +Lord Runes +Lord Shayne Lord Tarkus +Lord Valzin Lord Vioarr +Lord Vishnu +Lord Xeth +Lord Yaksha +Lord Zq +Lord iFlex +Lord kuro +Lord polak LordArtonius LordAusticus +LordBaphomet LordCoffee2k +LordCorreia +LordDanko +LordDaxel +LordEpic69 +LordFarquxd LordFoxy LordGuthanPK +LordJRazE +LordJuba LordLambo91 LordMullett LordNorden LordOfHarems LordOfOtakus LordPh1L +LordPolgoth LordQuinker +LordScoobert LordShrubber +LordSloppy LordThyas +LordUSA LordYawgmoth LordZahard Lordalbert0 +Lorddraconal Lorde Lordjoeman +Lordkaes Lordstails Lordtwinky +Lordy Flame +Lordy608 Lordza Loredon +Lorehold Loreland Lorencia Lorenz +Lorenzoh sr +Lorenzokazoo +Lorithean Lorkaa Lorki +LorqueldIM +Lorre46 +Lorry +LortJob Lorttomies99 +Lorvikatari Lorwic LosAngeles Lose Losel +LoserKid Loshambo +LosinAllHope Losing +Losing Fat +LosingXP +Loss1525 Lost +Lost Angel +Lost Baby +Lost Baggage +Lost Logan +Lost My Baby +Lost My Sock +Lost Oliver +Lost On You +Lost Roomba +Lost Snail Lost Tadpole +Lost Weed +LostBank +LostBankKey +LostChad LostCloss LostDude28 LostHalls @@ -13655,258 +28634,608 @@ LostMoon LostOcean LostOnThePCT LostSauce +LostStatus LostVorki +LostandFound +Lostdog03 LostlSoul +Lostpetrock Lostplzhelp Lostrelic93 +Losty99 +Lot of Beans Lothariou +Lotilyx Lotion +Lots of Eggs +Lotsa Regret +LotsaOSRS LottaPotAgo Lotto Lotu15 +Lotus bless LotusKid +Lotwik +Lou Le Dur +Lou Red Wood +Lou Sputho1e +Lou Surr +LouBug LouSass +Louezzi Loug Lougle LouiVui +Louie Bags LouieMurphy Louiec3 +Louiseyy Lounckie +Loupak +Lousy Drunk +LouvicDank +Louzy +Lov ed Love +Love Caley +Love M Poker +Love Roman +Love Taylor +Love Yourz +Love me +LoveMyAnzaa LoveThat +Loveable Lovelili Lovely +Lovely Clawz +Lovely Cola Lovepoot +Loverboy Loveskillin Lovexdragon Lovey +Loveyan823 +Low Alched +Low Chief +LowBaller LowKeyPickle +LowLifes +LowPines LowPower +LowRunEnergy +Lowanse Lowballz Lowercase Lowery +Lowfield19 LowkeyBallin Lowlander +Lowlife121 Lowlux Lowner +Lowrey73 +Lowstar1 Lowtempterps Lowy +LoxoJ +Loxtos +Loyal2pvm Loyalcaptain +Loyd Nichols Loze +Lpfan Lrauq +Lrian +Lric Eotter Lron Lronic +Ls4 LsummerC +Lsv +Lt Burgers +Lt Golpar II +Lt Mantas +Lt Purekarys +Lt-Iron-Lt6 LtCastiel LtJan +LtRemigijus Lt_Torch +Ltfreggin +Ltk Iron Ltman42 Ltmf +Ltufighterlt +Lu Diabla +Lu be +Lu0nto +LuauKing +Lub Lub3edUp +Lubbz Lubed LubinLen +Lubos +Lubosek Luc4rio LucSynthesis Luca +Lucaemar +LucarioLVL X Lucas +Lucas Solo +Lucas1192 Lucasmelo11 Luccaa Lucho Luchtloper +Luciah Lucid +Lucid Cynic +Lucid Dream +Lucid Josh +Lucid Meme +Lucid Truths +LucidFeels +LucidPie Lucidcr Lucidfever LucidityX Lucie SkyDia +Lucifenrir +Lucifer v2 Lucifer06 +Lucifer4Real Lucifer_link Luciifer Lucil +Lucina +Lucipur Lucivert Luck +Luck Lost +Luck Voltla LuckRunsAlt +Luckario Luckd0ut Luckeh Lucker LuckieStein Luckless Luckpvm +Luckscaper Lucky +Lucky Arian +Lucky B Boss +Lucky Bambam +Lucky Baws +Lucky Cash +Lucky Chance +Lucky Clover +Lucky Clown +Lucky Duck +Lucky Greg +Lucky Kev +Lucky Link +Lucky Lombax Lucky Lukey +Lucky Mofo +Lucky Rabbit +Lucky Sofa +Lucky Yoru +Lucky skrue +Lucky when LuckyAce LuckyDog +LuckyDog x LuckyEmerald LuckyKroketa LuckyLackey LuckyMatch +LuckyNrSeven +LuckyVic Luckybamboo1 Luckynuts Luckyxx +LucoUK Lucyfer22 +Luczzs +Lud a +Luda-Dan Luderan Ludo +Ludo Sand3rs Ludomo +Lueis +Lueke LuffyAce LuffyDMonkey Lufidius Lufue +Lug RS +Lugal Ki En +LugiaWaifu Luglys Lugs Luider Luigihbk Luis +Luis Anico +Luis Antonio +Luis Dk LuisFarm +Luis_Vzla Luka LukaBrasi Lukas +LukasFlux Lukaz Luke +Luke S Luke3 LukeOS Lukeee LukefonFabre +Lukeh Lukeicth +Lukesfish LuketheDM Lukey294 +LukeyUK Lukezz LukiOne Lukiekuipie +Lukio W Lukiss Lukoo911 Lukse Lukytisz +Lulani 13 +Lulla Lullie +LuluTheCat +Luluca Lulucifer +Lumber Yak LumberStevo +Lumbidge Lumbo Lumby +LumbyCalled LumbyCastle +Lumbys Waits Lumiaris Lumifrost Lumimies +Luminatti +Lumm1475 Lummer Lumo +LumpiaFan69 +Lumpqua +LumpsMcgooey Luna +Luna Koneko +Luna Lucero +Luna Mexi Lunacy +Lunaec +Lunamarie Lunar +Lunar Haze +Lunar Lotus +Lunar Tear +Lunar Tones +Lunar Ursa LunarDemon99 LunarEquinox LunarSC2 +LunarTheCat LunarTigerr +Lunarann +Lunarcrow614 Lunardini Lunarism +Lunarmoat638 Lunate Lunati Lunaticmo1 Lunatric +Lunaverse Lunch +LunchboxLLC Lunchtime007 Lund LundXCV Lundh Luneasa LuneyTunez +LungTied +Luni +Luniaxis Lunie +Lunier Lunis Lunizzzz +Lunytic +Luonteri Luonto Lupah Luper +Lupi +Lupo +Lupuloid Lure2G +Lurjus LurkinTurd +Luru +Lush Vibes Lusitropy Luskidoo +Lussen1 +Lustwaffle Lusu LusyTheGoat Lutha Luthien +Luthien T2 Luthors Luthstorm Lutinrouge Luucy Luud Luukie +Luuloterve Luuseri +Luuuseri Luuuuna Luuwana +Luv2spuj +Luver Focker Luvholic Luviii +Luwucy +Lux Please Lux211 Lux7thSaga Luxatio +Luxeo +Luxilie Luxire +Luxoul +Luxumine Luxury +Luya Luzu +Lv ranger +Lv 5 Psyduck +Lv Camo Lv100 +Lv100 Raichu +Lv5 Treecko LvI3stak3 +Lv_1_Mew +Lvcretivs +Lvl 1 +Lvl 3 Nub20 +Lvl 99 Goon Lvl100cheese Lvl30Ditto Lvl99 Lvl99Docking LvlUpUrself +Lvls Up Lvqquvs +Lwy Lx1I +Lxbe +Lxfleur +Lxnes +Lycix +Lycoe Lycstoned Lyct LydeZGrod +Lyderis Lydia +Lydia Kenney Lydmix +Lyfe Tyme Lyin +Lyin Eyes +Lyke625 +Lyks +Lymaks +Lymez +LynX ZrLeX Lyna Lynamet +Lynching Leo Lyngo +Lyni Lynics Lynx +Lynx Jitan +Lynx Tiger +Lynx Titan LynxTitan Lynxes +Lynxy LyraLyraLyra +Lyrad002 Lyrich Lyricidal +Lyrilusc Lyron Lysandra +Lysdexic4986 Lyse +Lysmann +Lyyli PL +Lyzu Lzin +Lzs +M A G 3 +M 1 KE +M 3 3 P +M 4 T R I X +M 8 A 1 +M A D O X +M A D Storm +M A T E J +M A X O U T +M A X PAYNE +M B Z +M E H I S +M E L D O +M E T R O +M E X I +M I K B A R M I T H O X +M I U M I Z Z O U +M INDGAME +M Itty +M K J +M O B I L 3 +M O C 0 +M O C H +M O ID O K +M R NaCl +M Super Buu +M T C +M U D K l P +M X G P +M a V 3 Rick +M a d Shrumn +M a k a i +M age +M aikel +M ak0 +M ammoth +M ana +M ankDemes +M anu +M aples +M arcel +M arquim +M artin +M ask +M athis +M axou +M azzz +M c +M elz +M enzy +M ga +M gh +M i t c h y +M i y a +M ikasa +M ike +M imik +M int +M itchel +M ittens +M l Q Q +M merz poL9 +M o C e +M o r t e n +M oist +M onkfish +M orytania +M the Maxed +M ugger +M ulas +M urphy 2 +M usashi +M-theory +M00CHIE +M00SE M00SE +M01 M0IST +M0IST B0X M0LE M0NALISA +M0NEYM1TCH3 +M0NST3R1PP3R M0ON M0ONCAKES +M0R TEN M0RG0TH M0RGE +M0SS3Y +M0ST D0PE +M0hannad M0ist +M0ist Midget +M0ney Swag +M0nk3y DLufy +M0nke y +M0nkey15 M0nsterTuk +M0obs +M0resheth M0rningstr +M0use M11CK +M11ka M1911A1 +M1GU M1NG3_GOO +M1TTLE +M1ch M1gos M1ke50 +M1ksu +M1nd Master +M1ntberry C +M1ss Di0r +M1stak3nly +M26 +M3 L M30W M30z +M3GAD0UCH3 M3L10DA5 M3MEL0RXD +M3MoRY M3X1CO M3XICO +M3ch4nics M3ll3 M3lllll M3lviin +M3ntal M3rking +M3ry +M3t4l1n1S M40A M4D399 +M4g3 +M4g4z M4gnus666 M4k3d0 M4tte M4xt0R +M5 +M52 M523 +M6 Mill +M6N +M7J +M7TT M855A1 M8NoFreebies M8TT +MA N E MAAAAK +MAAGES MACKOGNEUR MADLADz MADRNGJACK +MAESTR0FRESH MAFKINCHAMP MAGA MAGA1292011 @@ -13919,140 +29248,275 @@ MANT4S MARCOPOLO MARLB0RO MARMlTAO +MAS0N MASKED +MASSGAINER32 +MASTER DREAM +MASTER J0KER MATUTVlTTUUN MAURERA79 MAUROPICOTTO MAX3D MAXABILITY +MAXED PINOY +MAXXEDDADDY +MAX_HER0X +MAXlME MAlNEVENT MAlNTENANCE MC Cheep +MC catheter MCBURNOUT MCHammered MCKenny91 +MCSIZZLE +MCmattt +MD7 +MD96 +MDE Presents MDPS +MDaher +MDucks +MEAT G0D +MEAT HEAD36 MEGATRON MEK4KK4KK4KK MELAN00MA MELT METM0NKEY +METR0lD +METS0 +MEV4NS MF DC +MF MORTEN +MF SofaKing +MF TEE +MFE +MFKU +MFLI MFSTEVE +MG5 MGFS +MGKRevs +MGM WAY +MGreengrass +MH Therapist +MHA C +MHBC +MHS MIDAs MILFmauler MILSHAKE MINH +MISOGl MISSYGAMlNG MIST MITCHY MIX0R MJ23 +MJKaboose2 +MJT MK-HARDSTYLE +MK6R MKAM +MLB +MLTEEZY +MLaidman +MMMahogany +MMORPGenius MMTera MMitchh +MMtheMachine +MOABDADDY MOMHUNTER666 MON5TER +MOODSWlNGS MOOSEM3AT MOTM MP17 +MP9 +MPB +MR JOHN WlCK +MR LETHAL2u +MR REET +MR TMR MR UDZ +MR556A1 MRButter +MRC Tugboat MRGAMEZ MRHD +MRLARGE +MRM MRPlZZAPRIZE MRWHlTE MR_MAITO +MSPaint64 +MSceneFF MSpacePotato MStarkz MTBMB +MTPETE +MTV CRlBS +MTXP MUISSS911 MULHERndaEXP MUMM0 MURMELl MUSK MUSK0KA +MUSUMUMM MUZAMMIL +MV Flow +MV Welshy MVIII +MVKirby +MVP HERO +MVP Mahomes MVRDA MVTIASD MWwarzone +MY L U N A +MYRSKYVIITTA MYTHICROYXLE M_Sariol +Ma Band +Ma Dood +Ma Titi +Ma t t h e w +Ma5onx Ma7e +MaCoMb MaHeelsHurt MaJeShTic MaQtPie MaX662 +MaXam00se +MaXeDSani +MaXx0wnage Maacc +Maake88 Maanman Maasegyr +Maax2 +Maaxiking Maazako +Mabbbs Mabbs Mabel MableLake Maboe +Mac Diver +Mac Donald +Mac Garfield +MacDuff MacFredrik +MacFredrique MacMillers MacMoblins +MacRae MacSandwich MacTheRipper Maca +MacaFazoL Macabre +Macaron +Macaroni 73 Macaronni5 MaccaM +Maccaroni Macduffe +Mace Windu Macedo +Mach Sigma +MachV2 Machado Machfredy +Machine Girl +MachoTimo Machtig +Machtige Machtigeman Machtigemeid Machto Mack +Mack x +MackD +Mackadactyl Mackadee Mackdizzle99 Mackeo +Mackerel Sky +Mackerels MackhNL +MacksEntropy MacksIsland +Maclairin123 Maclas Macoinho Macre demia MacreedyLove Macromage1 +Mad Dog Eris +Mad Flavour +Mad Krampus +Mad Max 20 +Mad Papper +Mad Suss +Mad Vlad +Mad Watson +Mad X +Mad arrows12 +Mad as heck MadBoy20 +MadBruh +MadCanadian +MadChemist8 MadD0g11 +MadD0gL4d69 MadDogged +MadJeffs MadKingMikey MadMaxMan +MadPubes MadSnowman23 MadaRook Madaddam Madam305 +Madarah +Madd177 MaddAntelope +MaddMann5 Maddape Madddiieee Madden +Maddie Baddy Maddogjr Maddux Maddy +Made of Sand Made4Slaying MadeInAfrica +MadeYouClick MadeinTYO Madeiraa +Madeleine Madeweine Madhu Madlaina Madmaxie +Madness Max +Madodee Madona +Madra Madrock01 MadsG Madsenn Madsermad +Madshatter71 Madskillz756 Madslasher30 +Madslax2 Madsosaur Madula Madvantage @@ -14062,48 +29526,83 @@ Madysen Madza Madzilla Maeda +Maegera Maela MaerlinTaz Maertynas Maester +Maester Trea Maestro +Maestro Heil +Maestro1 +Mafia-BP MafiaMan MafiosiDad Mafooma Mag1c Mag1cJohnny Mag1c_W33d +Maga Kahn Magalator +Magani C Magawie Magc Mage +Mage Eh +Mage Kume +Mage N Skil Mage7master7 MageFish MageHax +MagePriece +Mager Magerold Magers Mages350 +Magestus +Magethirst Magezi +Magggorical +Magginator Maggot MagiTurtle Magic +Magic Bonus +Magic Clicks +Magic Mackee +Magic Moose +Magic Rino +Magic Tree +Magic Wand +Magic fTail MagicAppel +MagicMemorys MagicPanda91 MagicSchoBus MagicSilver Magic_Elmo1 Magical MagicalRuby +Magican Magicarp Magicbox Magicdefence Magicken +Magicx +Magija +Magik Magik773 Magikilo Magiok +Magisteerial +Maglet Magma +Magnaboy +Magnati Magnautism Magnesium +Magnesium J +MagnesiumIV Magneticism Magnetite Magni99 @@ -14111,99 +29610,217 @@ Magnifice Magnilo Magnis Magnu +Magnus Gram Magnusungam +Mago +Magsd1 Maguneru +Maguro Magus +MagusChum Magyk +Magzem +Mah Jae +Mah Jong MahSeed Mahalusa Mahanimal +Mahe Mahkelroy +Mahler +Mahmoud Mahogany +Mahomes +Mahonoken Mahtitykki Mahzius +Mahzka +Mai kel +Maiba +Maide +Maidenheir +Maignansdead +Maikel J Maikhol +MailTime Mailor Main +Main 3s +Main Cactus +Main Ginger +Main J0urney +Main Mynt +Main Natey +Main Pando +Main Path +Main Product +Main Twiddle +Main Wario MainCharlie +MainCoach +MainCringe +MainDong MainForever +MainHamendex MainHolm +MainJ +MainMan_Mads MainNudley MainPurp MainSt MainStand +MainStreamx MainWabbit Maind Maindeer +MaineDeno +Mainline Mainly +Mainly Pure +Mainly Ricky Mains +Mainslet +Mainuru Mainz +Mainz Gainz3 Mair +Mair017 Maisa +Maisa Torppa Maisteri +MaitoRimpula +Maix +Maizon Maizpilao01 +MajMischief MajQ Majakanvahti Majcew +Majcew 2 Majehjk +Majer4 +Majin Buuwu +Majinbooo Majinjon +Majki Majokko Majooty Major +Major Damien +Major Gains +MajorEar MajorMammoth +MajorObesity MajorOwnz MajorSnizz +Majora MajoraMasked +Majoras WRLD Majzako7 +Maka +Maka2201 +Makagago Makaule Makaveli +Makaveli I +Makaveli II +Makaveli l Make +Make A Pile Make Carrion MakeItStack +MakeMeKing MakeNotes Makeboy +Makeeesful Maken +Maken Gainz MakenMakkara +Makenna +Makhachev +Maki Makilake +MakinExcuses Makiverem Makk Makke Makkeii +Makker Benja +Makker Trane Makkiavelli +Mako Nox +Makoea +Maks Cape +Maksimit +Maksoinvelat Maksuamet +Maksui Maksukka +Makzd MalaLechita +Malachai Maladec Maladiec +Malagah Malbec Malboulgea +Malcz Malding Male Maleurous Malfoy +Malhavic +Mali RS MalibuMan96 Malibuux +Malignant00 Malik Malinerix +Malitiae +Malkav Mall +Mall Gang +MallbuRo Malleus Malli +Mallieero69 Malloc +Mallomar Malmi Malmot +Malomalo +Maloo Malqy Malse Malt +Maltapkiller Malteadita +Malter +Malterz Malucoftw +Malurian283 Malvian +Malvidus Malvoliuus Malware Mamachii +Mamas Meat Mamba +Mambaaaaaa MambasWRLD +Mambo No5 +Mamboita Mammad +Mamoul Mamupatja +Man Asian +Man Bag +Man Killa77 +Man Kip +Man Raccoon +Man Throater +Man gos +Man-Yak ManBearPiggy ManGoBzzzt ManOfGold @@ -14213,20 +29830,30 @@ ManWT ManWoox Manaburna Manafont +Manakiel ManakuraJP Manantti123 Manantti321 Manardog Manawatu +Manby +Mancandy +Manchest Mancino Mancunion92 Mand1ng0 Mandelbrot +ManderSala +MandoCheese Mandor1 Mandred Mandulorian Mane Manegaming +Maneirinho +Manelzera +Maneter56 +Manevolent Manfa MangJoe MangeMeister @@ -14234,95 +29861,179 @@ Mangle Mangled Manglican Mango +Mango Monkey +Mango Rat +Mango Season Mango10 Mango1997 +Mangobnana +Mangostangos Manhoos Manhunt +ManiacBison +ManicNode ManicRS Maniek Manila Maniwani +Manju Manke Mankitten +Manlanter Manletti Manly Mannekeuh +Manni Penny Mannie +Mannix270 Mannjpip +Mannnekala Mannowrath +Manny21 +Manokin Manor +Manorvic MansaMusa Manser2300 Mansup5 +Manswarm Manswers Manta +Manta Wray2 +Mantarayo MantasA +Mantaslocoo Mantelio8 +ManteliseXe +Manthe MantorokDIA +Mantoshka Manttt Manuelh3 Manumatti +Manx_Scaper Many +Many Walrus Manyi Manyvids ManzGotViewz Manzo +Maose +Maozn +Mapanza1 Maple +Maple Jay +MaplePoutine +MapleRoyals +MapledOaf Maplejuana Mapletech Mapne Mappl1n +Mappzz Mar0e Mar782 Mara +Maracruz Maradonaa Marassa Marathonius Maraud Marblez Marc +Marc NL +Marc Paul +Marc Spac MarcVinicius Marchmello Marchuk +Marcia Ress Marcikarp +Marcilicious +Marcius 7 +Marco225 +Marco7k Marcoli64 +Marcoo Marcooow +Marcos Vibe +Marcski +Marcussius Mardiie Marducas +Mardy O G Mardzz Mare +Marenki +Maret Marg3 Margana Marganer +Margiella Margins +Margodx +Margon +Margonite Xu +Marguana Marheim Mari Marianas +Mariano 1 +Mariasonic +Marib +Marijuano +Marikadere Marines Marinez +Mario Bros +Mario Goatse +MarioKartDD MarioTennis Marioh MarioisKewl +Marioman Marioneta MariosPeach +Maritime +Maritozzo +Marjapuuro +Marjatta +Mark Pledger +Mark Swenson +Mark-777 +Mark-Zuk +Mark0vDeath Mark12387 Mark1ta +Mark5Barki MarkBuns +MarkJongejan Markald87 Marke Markerr +MarkhamON Markie994 Markipedia +Markku Marklyft +MarkoOSRS Markop100 Markovia64 +Marks Main +Marks Phone +Marks lron Markus +Markus Stier +Marky428 Marlbrozo Marleth Marleyy Marlin1993 +Marlon0817 MarlonisGod +Marlooo Marlopped +Marluxia Pwn Marmita99 Marmp Marms @@ -14332,40 +30043,66 @@ Marni Maro202 MaroO Maroj +Marokkaan Marokkaantje +Maroko111 Maroon5 Marpollo MarquiseDmnd MarrCuzz +Marrcy +Marreldil +Marrer Married Marrio +Marrius Marro75 Marsal Marsalkka +Marsel Marsg Marsgl +Marsh Marrow Marsha Marshal Marshall1 +Marshmont Marshyy MarskiLark Marsmash +Marsovec +Marstead +Marswatt Mart0103 Marten +Marten x MarthProMonk Martial +MartianLynch +Martiba +Martiiian +Martijn Martika Martin +Martin 2007 MartinGameTV +Martindeq Martinjsh Martinkyle20 Martins Martinside +Martip MartnShkreli +Marty +Marty150 MartyG MartynMage +Martyr Main +Maruna Marv Marvelli +Marvick +Marvins Dad Marwan Marwin MarxRoux @@ -14373,16 +30110,22 @@ MarxTheMyth Mary j4n3 Maryj Maryland +Marylandd Marzcorw +Marzeo Marzhy +Masaca Masacre599 +Masade Masago Masakado Masandalf Maschok Masconomet +MaseLitt Maserati Mash +MashedOP Mashimarq Mashiwo Masin @@ -14390,31 +30133,57 @@ Masiron Maskedpump Maskin Masochisttwo +Mason OSRS MasonJarr Masonatorr Masonitte +Masons Dong +Masoo MasquedMan +Masryy +Massa +Massacre Fc +MassageMan97 Massif +Massimo130 Massinissa7 Massive +Massive Noob +MassiveJonas Masss Massterduel +Mast3rOogway MastaHeff Master +Master Bakes +Master Bogs +Master Byro +Master Garni +Master Jos +Master M V +Master Riven +Master Skizz +Master Vates MasterB1994 +MasterBarter MasterBlazee MasterDragxn MasterGrogu MasterKiefff +MasterMake +MasterMasa2 MasterNeigh MasterOzzy +MasterPanda MasterPookie MasterRooshi +MasterSlayrr MasterThresh MasterX Masteragota Masterbihno Mastercat +Masterdemon4 Masterflick Masteri MasteriMori @@ -14422,43 +30191,79 @@ Masterkindem Masterrgod Mastervile Mastirida +Masturbeerke +Masurda Masuro Masylvain +Mat 1 +Mat Jacko +Mat Share +Mat thew11 +Matchbox 20 Mate Matematikk +Materium Mateusz1210 Math +Math Is Fun +Math ematic MathVibes Mathcore +Mathematics Matheor Mathers Mathers1996 Mathew Mathias +Mathias Nemo Mathisse Mathmic Matholemeu +Mathrotus Matieus Matix +Matkijanarhi Matmo +Mato Seihei MatoPotato Matoaca Matrak +Matreex Matrix Matrixpachi Matruusi2 Mats +Matsu Matsuri Matsyir Matt +Matt 162 +Matt Bman +Matt CFK +Matt Cat +Matt GIM +Matt K +Matt Lad +Matt Mo +Matt Slay +Matt Smash +Matt V +Matt Wy +Matt1494 MattLeedz MattMattBro +MattNDew MattRanger MattRoux MattSeal7 +MattStyle +MattWallet Mattaclysmic +Mattakuda Mattam66 +Mattaroo Mattec +Matteos1 MatterOfTime Matternot Mattex @@ -14468,29 +30273,52 @@ MatthewDK MatthewRS Matthewwww Matthidan +Matthis +Mattias Mattice +Mattie osrs Mattie43 +Mattj Mattniss Matto +Mattor Mattorel Mattrate Matts +Matts RNG Mattsbro Matttbob Matttt +Mattty +Mattus50 Mattx1 Matty +Matty A Matty Gibbs +Matty Ic3 +Matty467 +MattyChasee +MattyLight91 +MattyNW +Mattych Mattyflight Mattys +Mattyz6 +Matu btw Matuba Mature Matwo +Matygoyo Matz +Maub1 +Maucca Mauddibb Maui MauiBeach +MauiMallard Mauidude +Maukas +Maukka MaukuMaija Maul 0n Top Mauler4500 @@ -14500,80 +30328,234 @@ Mauna Mauno Mauricio555 Maury +Mauvayy +Mauvier +Mavdagin Mavel Maven Maver Maveric Maverrick +MavicAir +Maviie Mawch Maween +Mawie +Mawlocke +Mawn +Mawsen +Max 4 Mikey +Max Ape +Max Attacken +Max BD +Max Blacks +Max Botter +Max Cape +Max Deiron +Max Eff +Max Entropy +Max Gadget +Max Gav +Max Here4Pet +Max House +Max Karma +Max Klett +Max Methi +Max NoLyfer +Max O7 +Max Obi +Max Pkr +Max Puffs +Max Re3oo +Max Relax +Max Scape +Max Snek +Max Temper +Max The Hero +Max Tilting +Max Tonks +Max Vandal +Max Weezy +Max Wotif +Max XP +Max Zack +Max Zeus +Max btw +Max cape 420 +Max hits +Max killz6 +Max plus +Max uwu +MaxAchoo +MaxAnarchy MaxBTW +MaxBadAss +MaxBear MaxHare MaxHaus +MaxHomieJose MaxIgnorance +MaxIrl +MaxKhalifa +MaxMainJake +MaxMuffin MaxNeander MaxSAVAGERY MaxTix MaxTurbo +Maxchar +Maxd Maxe2968 Maxeado Maxed +Maxed Beans +Maxed Code +Maxed Egirl +Maxed Emm +Maxed Eric +Maxed Groot +Maxed Hippo +Maxed II3en +Maxed Jeff +Maxed Kiraly +Maxed Loser +Maxed M0bile +Maxed MVP +Maxed Masak +Maxed Newfie +Maxed POH +Maxed Phells +Maxed Rat +Maxed Rob +Maxed Scaper +Maxed Spyike +Maxed Total +Maxed Twice +Maxed Velho +Maxed Whip +Maxed Zeb +Maxed Zuk +Maxed osrs +Maxed when +MaxedActuary +MaxedBruh +MaxedBurnout +MaxedButPoor +MaxedFrog MaxedIn2074 +MaxedInDa6ix MaxedMain MaxedMax751 MaxedMike +MaxedMobile +MaxedNbored MaxedPleb +MaxedRepel MaxedYP Maxedlegacy +Maxedtoasty +Maxedwell Maxell Maxerder Maxiboy4a9 +Maxidy Maxime5100 Maximonster Maximum +Maximum Tier Maximumist +MaximusAM +Maxinator87 +Maxing zzz +MaxingMyMain +MaxingSucked +Maxingthis Maxiorek1200 +Maxisbaws +Maxisen +Maxitaxi777 Maxiu Maxjuhhhh19 +Maxkenzi Maxmemix Maxnominus Maxo +MaxoBlasto +Maxoou +Maxpappy Maxpro Maxst Maxstalker67 +Maxstatz +MaxtanosXD Maxwall Maxx +Maxx y +Maxxed Alt +Maxxed Dusty +Maxxed Trash MaxxedNoob +Maxzet MayanFuror +Mayate +Maybe CIA +Maybe Idiot +Maybe Jeff +Maybe Shady MaybeMason MaybeMitch Maybemnam Maybez +Maybizzle Maybon Maydole +Mayerdynn +Mayhaps Mayhem +Mayhem Maker MayhemMakers Mayl Maylive +Mayo +MayoForFunds Mayonaz Mayor +Mayor Jiwana Maytona +Mayuri +Mayushii Mayvex Mayweather Maz0n1k Maza Mazala +Mazande Mazariner +Mazauu +Mazda168 +Mazdan +Mazdaspeeed3 +Mazdraith +Maze +Maze of Iron +Mazel613 Mazersyy Mazhar Mazlol +Mazmarazor Mazoni Mazpls Mazta Mazuma +Mazz y Mazzacre +Mbox Mbyoo +Mc Dragans +Mc Florry +Mc Red McAlakazam +McAsssBlast McBurn McCheddabomb McChimkenGOD @@ -14581,204 +30563,402 @@ McChubbin McCllin McConaughey McCreJ +McCringle McCune McDanky42O McDizzle15 McDongles +McDoodle_21 McDouble McFantasy McFizzleDady +McFly93 +McFozzar McGooser +McGorm McGregor60gs McGruff +McHammock McIllu +McIronLeech +McKennon +McKerma +McLOVlN +McLaeNz McLeaNz +McLemore +McLovin707 +McLowry McMeekin McMillan McNeal +McNoob10 McNoodle +McNorm McNugget McP0P0 McQuaker McQueensy McRibs +McRibs Back +McRip +McSchloogan +McShrubbery McSomf +McSplitter McStarley McSuperNoob McTaskupillu McThomzie +McVittties +McWeaksauce +Mcards Mcbelsito Mcberra Mcdally Mcgingerpony +Mcgregorini Mckelvie Mckinconn Mclaren88 +Mcneill Mcpatrice12 Mcpielover Mcturdson Mcwaffle1 +Mcy +Mderg +Mdub Suhh Mdzvwz +Me Acoustic +Me Ca +Me Dead +Me No Brains +Me Woody +Me and Jr +Me lvin +Me phisto Me3lem +MeBigPoppa +MeBlast MeMillionthD MeThudZ +MeTwo MeadowFall Meadows MeagerSkills +Meals Mean +Mean Crusher +Mean Street Meano +MeanrangerFE Meap Mearm +Mears Measles Meat +Meat Rat +Meat Shank +Meats Meatspot MeatyLoaf +Meauner +Mebo Mech +MechantBozzo +Mechaodin Mechelen +Mechvengance +Mecidon Mecone Mectofion +Meddler +Meddlr +Medi Mobile +Medi i +Medi ocre +Medical Herb Medicate Medicides Medicinal +Medicore +Medievh MediocreMatt MediocreRye MediocreTime Medispensary Meditations +Medium Cloo +Medler Medoletics Medon Medorable Medusa228 MedwayDragon MeechIsCute +Meechy Dark Meeeseek Meelays +MeenBeans +MeepBeepMeep +Meeran Meerca +Meerkz Mees126 MeesKees MeetMyMeat +Meetti Meew +Meewerp +Mefaustofele +Mefco Meftah Mefy +Meg 3 Mega +Mega Butt +Mega Farce +Mega Kyle +Mega Mort +Mega konn MegaAmpharos +MegaDoris MegaDrive MegaMustarn MegaNaziHatr Megabyte6 Megadwarf47 Megalo +Megalodont +Megamanyo Megamind +Megamind Jr Megans Megaronii +Megastoffe +Megatortle Megatrax +Megis Megnificent +Megpan Megumin Megustio +Meh Noob +Mehrunes Mehts Mehuelin +Mehuo MeideC94_BB +Meido Mein lron +Meinkul +Meiousei +Meister Sho +Meiyo +Mek +Mekaanik Meklo Meksa +Mel Meow +Mel Yakutia +Mel btw +Melanderr Melanoma +Melayna +Melc0n Melchuzz Melcoor Meldianx +Meldynoir Melee Melee_Range +Meleny Meleven Melhoop +Meliodas420 +Meliodin Melisma Melk +Melkin Melktietje +Melkzuurtje Mellakka Melleruds Melling +Mello Gello +Mello Yello +Mellodynamic +Mellow Jingy +Mellow Tones Mellow6 MellowSoul MellowTokes Melly +Melly YNW Melo +Melodicolt Meloenschijf +Melongrab +Melotoninn Melpan +MeltedCash Meltman Meltok +Meltryllis +Melvin dew +MelvinTheOK MemberBerry Memberlist Meme +Meme Loord +MemeDoge111 +MemeVendor +Memedalorian +Memem3 Memeologist Memeshake +Memmor Memory MemoryCard MemoryWorm +Memphis lol +MemryLoss Mena Menap Menaza Mend +Mendicant Mendieton +Mendokusai +Mendota Meneer +Meneer Nijn +Menesus Menetoeihin +Menial Luck +Mennie Menrey +Mensphysique +Mental Coach Mental4Metal MentalAbacus Mentally Moo Mentalmissy +Mentoes +Menyu Menza +Menzola +Meoooow +Meow Ghost +Meow Im Hawk +Meow Softly MeowKiki Meowed +Meowgi +Meowler Meowmagic +Meowrijuana +Meowskeys Meowtheduck +Meowzer7 +Mepiff +Mepn Mepthadr0ne Mer Train +Merami fan Meramon +Meraxus +Merbz +Merc-Raa +Merc_Lobo +Mercedes F1 +Mercenary V Merces +Merch MerchantUrch +MerciTwingo Merciulago +Mercphobia Mercules +Mercury Owl Mercury15 Mercy +Mercy Osrs +MercyfulFate Mercys +Merderr +Mergician Meric Meridians +Meris Merisalu Merisorax Merkdalat +Merke +Merked Ko Merksick Merlin +Merlin Otter MerlinMonroe MerlinPT Merloc21 Merlucius +Merlvin Merricat Merry MerryTuesday +Mersunperse Merten Mertguy2p0 Mertiin +Mertjaars Mervyn Meryam Meryath Meryl +MesH3aL Mesa +Meshi510 +Meshkot +Mesin +Mesmeriize +Meso cyclone Meson +Messaa Messersmitti +Messi Messias +Messorium Mestari +Mestaristick +Mester B MesterAbekat MestreGlados +Met Promise MetDoobie Meta +Meta Mammoth +Meta l +MetaCTF +MetabolicPro Metadragon Metafisico3 Metagel Metal +Metal Booty +Metal Little +Metal Shad0w MetalGear +MetalMaiden3 +Metalest Metaling +Metallic Neb Metallifog MetallikDeth Metallproz Metalproz +Metamorphic Metamorphs Metamushroom Metaphwoar @@ -14787,45 +30967,89 @@ Metaxia Metbol Meteora Meteoriitti +Meth Teeth +Methal Methodical +Methusal Methylanara Metix Metoprolol Metropolia +Metsavaras Metselaar Metsiq Metters +Metukka +Metzifer Metzz +Meulendijks4 +Meune Meuosh Meur +Meuyou +Mevvz MewIlicious +MewPulse Mewby +Mewli Mewllicious Mewrad Mewtwo MewtwoKing Mewww +Mex Arkantos +Mex_N_Flex Mexicanchild MexiePie +Mexlet123 +Mextex +Meykaa Meymer Mez-qt Mezane Mezecs +Mezenburn Mezeroth Meziriti +Mezmereye +Mezomel Mezy Mezzalarry Mezzito +Mf Fe +Mfey +Mfin Taylor +MfknNewports +MgZz +Mglegolas +Mgn +Mhh +Mi Hoy Minoy +Mi1os +Mi3pelst3in +MiAdidas MiIIenia MiIIers MiQuu MiTDro +Mia Kalphite +Miacon +Miami 305 +Miami Cane +Miami Rebels Miasm +Miawnation +Mibs +Micaso +Miccolo3 MiceMan +Micecream Micella Mich +Mich Bz Mich49 Michael +Michael4655 Michael67676 MichaelB MichaelScarn @@ -14838,103 +31062,203 @@ Michanderma Michano1992 Michaud Michel647 +Michelau +Michelle jnr Michiel +Michiel_96 +Michinaki +Michism Michlenn +Michxa +Michy Man +MickZagger Mickael +MickeyJoe Mickeyr4nge Mickul Mickyy Micosa Micro +Micro Cosmic +Micro Nerd +MicroButt420 MicroShrooms Microdot +Microgolf +Microman0000 Micromelo1 +Microo +Micropyle +Microsoft22 +Mictie +Micxyz +Mid Fade +Mid Pack +MidValley +Midareru Midas224 Midday +Middelkerke Midget +Midget Bones +Midget Rave MidniteGreen Midori +Midori Enju Midside +Midway16 +Midweeks +Midwife Dan Miega +Miegalius Miekka Mier Mierdapier Mies +Mies Lapsi +Mig Wizard Migalos Miggles Mighty +Mighty King +Mighty MP1 +Mighty Milk +Mighty Oak +MightyDolt MightyNemo MightyOrange MightyPieBoy MightySlappe +Mightyfrosty Migjiris Migou +Migrainelife Migraines +MiguelDyson Miguu Migy Migzee +Mihu o_o +Miiammi +Miig +Miiiild +Miika +MiikeyG Miillls Miiori MiissMandii Miitt +Mij +Mijae +Mijniebelle Mijuzo +Mik +MikTheKing +Mika Kuwait +Mika x +MikaDMM Mikael Mikasana MikazuAugus Mike +Mike DIY +Mike Davis +Mike Hochuli +Mike Hunt +Mike Mike +Mike Unit +Mike Xp +Mike-NL Mike1 Mike745638 MikeChang +MikeConleyJR MikeDangr MikeDitka +MikeHasMoobs MikeM MikeMontana MikePunts +Mike_Oxmaul Mikebaker417 Mikeey Mikeje13 MikelCz Mikemyers31 Mikerockshhh +Mikeroscape Mikeroscope +Mikes1995 Mikethafarm Mikey +Mikey B +Mikey Bai +Mikey Hey +Mikey Milk +Mikey x Mikey1plate Mikey47745 +MikeyBigDick MikeyPat Mikeygirl94 Mikeyscape MikeyyG +Mikezalwinnu Mikezilla Mikezzup +Miki4 Mikilly Mikki Mikkon +Mikouich Mikrobangine MiksuBTW Miksuuu MikuNakanoxx +Miky852 Mikzel +Mil Z +Mil ky Mila +Milagre Milaz MildRussia +Mile Stoner +Mileage MilesQPR +Miley Cyrush +Milfcocktail Milfguardian Milhous Mili +Milico +Milieu +Milieudienst +Milimoowolf +Miljoona Milk +Milk Energy +Milk Expert Milk Sausage +Milk my milk MilkDaughter MilkMan227C MilkOhh MilkToast +Milked Cox Milkki Milkless +Milkmate +Milkn Tiddys Milkopia +Milkraze Milky MilkyGalaxy +Mill Reef Mill385 +Millbrook92 Milleks +Miller 40 MillerLatte Millerlite40 Millerlite95 @@ -14943,37 +31267,82 @@ MilliMillzy Millie Millionsppl Millkk +Milllf MillsMCR Millsbay +MillzyRS +Milo +Milo Iced +Milo Monster Milol Milpe Milsurp Miltank Milton Mim3r +Mimahh +Mime Tan +Mimi20 MimiKe +Mimic +Mimori +Min Botter +Min XD Minalinsky Minar +Minazuki Mincene Mind +Mind C Crew +Mind F-ed +Mind of me +MindBender84 MindYoStep Minde Minde0777 Mindf4ck7 +Mindforce MindfulGnome +Mindgrnd Mindhead Mindlet +Mindreaver +Minds Hunter Mindys +Mine is frai +Miner00 +MinerMvp Mineraal +Minerii Minerock +Minerock Man Minesweeperx +Mineta +Miney Minfri +Minga Minga Mingdee +MingeKing Mingerd +MinhteaFresh Mini +Mini Aurelia +Mini Biceps +Mini Chocobo +Mini Elba +Mini Hazy +Mini Jaack +Mini K +Mini M +Mini Misty +Mini Van +Mini Xander +Mini o MiniBuilt +MiniBundy04 MiniCoat MiniDrew +MiniDuckling MiniNinjo MiniSoMini MiniStew @@ -14981,96 +31350,201 @@ MiniToast Minibini Minidefiant Miniglass +Miniguez Minijazz Minimaps +Minimizing Minimum Mining +Mining Runes +Minioz1 MinipeTh Minirio Miniscus +Minish Gal +Minisnacks +Miniuzy +Minix Mink +MinkMiller Minkyeung +Minnesoooota Minnick Minnie Minski Minslee +Minstrel RS Mint +Mint1s MintEastwood +MintSoldier MintWestwood +Mintaras Minton Mintvolcano +Minty Elder +Minty Rogue Minty28 MintyBeaver MintyBreath +MintyFreshFe +Minty_Duos +Mintyyyy +Minu Kamp MinusMinitia Minyons Minzy130 +Mio Magic Mioceen Mipu Miqdad Miqote Miquuw Miracle +Miracle Grip +Miracle Sun MiracleToy Miraculous MiramiS +Miran a +Mirana Mirari +Mire Mirek +Mirepoix +Miriage Mirin_Gloots Mirith +Mirize Mirk Mirkat +Mirkoi +Mirkys +MiroSemberac +Miroh Miroki Mirthless Miruki +Mirxcle MisClickPro +MisLilToe +Misaka 10032 Misakipillow Misano +Misantrofia +Miscellaneum +Mischief Miscrint +Miscy Misdeal +MisfitGrinds Mish +Mishie x +Mishigamaa Mishkkal Misimo Miskil +Misks MiskySam Mislabeled +Miso Horney Miss +Miss Amanda +Miss Amped +Miss Beth +Miss Clover +Miss Inform +Miss Judging +Miss Kipatzu +Miss Kitty +Miss Nothing +Miss Piggy +Miss Tinaa +MissArcane MissMockingJ MissMystique MissRosie +MissTowlie +MissTwistedx +Missandrist MissclickGG +Missel0 Missen MissinTicks Missing MissingRNG +Mission +Missu +Missus Missvmk Missy +Missy Cee Mista Mista 1337 +Mista Wright +MistaPhelps +MistaWubz +Mistagainz Mister +Mister Chill +Mister Ex +Mister Gone +Mister Jar +Mister KJ +Mister Texas +Mister Tiger +Mister Xanny +MisterBass MisterBensy +MisterBidoof MisterCobb +MisterGurn MisterJager +MisterPatego +MisterStats MisterTrump +MisterWhale +MisteruDongu Misterwieb1 Mistheos Misticwok Mistify +Mistik Soda +Mistio +Misto-Flies +Mistr Morale +MistrGiggity Mistral +Mistre Apple +Mistres Pres Misty Misty12 Misty7632 Misuryu Mitabi Mitch +Mitch Gate +Mitch Izle +Mitch Peters +Mitch W MitchHardo MitchRap Mitchggee +Mitchman987 +Mitchs 2nd +Mitchys Iron Mith +Mith Man214 +Mith Scimmy +MitherHobo Mithoon Mithrality +Mithralking8 +Mithrane +Mithter T Mito Mitologas +Mitqh Mittag MittensRS Mittum @@ -15079,18 +31553,26 @@ Mituse Mitver Mitzchy Miuted +Miuw Mivo50 +Miwi +MixBro MixKit MixTapeFiya +Mixes Mixieg Mixtape +Mixun Mixxush +Miyags Miyui Mizis Mizo Mizro Mizty +Mizuno Akane Mizusawa +Mizz Horror MizzFrizz Mizzzura Mjay @@ -15101,57 +31583,130 @@ Mk60 MkLeo Mkiller120 MknlC +MlCOOL +MlDGARD MlKE +MlKEL MlLFnCOOKIE +MlLLlSECOND MlLO999 +MlXOR MlZORE Mlao +Mlddel1 +Mlopes Mmgmike24 Mmichel +Mmkbro +Mmm Food +Mmm Mushroom +Mmm Xp +MmmBathSalts +MmmButter +Mmmmm Bacon Mmorpg +Mmu Mmurder825 +Mmv Mnemic +Mnir MnkyDLufy +Mnmnnmnm +Mnts +Mo Fo Sho +Mo Hit +Mo slays +MoFo Boss MoIon Iabe +MoMoYaP1972 MoPhobia +Moathog63 MoaxD +Mob Partyhat +Mob Punch +Mob Up +MobILe_Own3R +Moba All Day MobbDeep +MobbyWang Moberger Mobiel Mobile +Mobile Data +Mobile Maxin +Mobile Rng +Mobile Skiff +MobilePlayin +MobileSkeng +MobileXPOnly +Mobilekraan Mobilist Mobiusyellow Mobo Mobs MobyWoby Mobz +Moca Pet Moccamuna +Moccies Moccona Mochasins +Mochi Donuts +Mochyy +Moe Amien +Moe Is Back +Moe You Up +MoeCipher +MoeTx Moeberg MoedZhafa +Moedameyer +Moefugganutz Moepog Moer Moes +Moestieee +MoetIkLopen Mofaer45 MoffelRS Mofleminator +Mofo Lt +Mofo Shadow +MofoMo92 Mofoe +Mog Time xD Mogcow Moggok Mogtime +Moh Mohahm Mohamedss Mohanad +Mohannah +Moheed +Mohh Mohib +Mohlo Mohnday +Mohphy +Moiqol Moist +Moist Dreamz +Moist Holy +Moist Maori +Moist3allsac +MoistButh0le MoistMaker MoistPainal +MoistWreck +Moistium Mojimot0 Mojito +Mojo Fiki Mojojojo171 Moju +Moju GG +Mojurico Mojzis Mok101 Moka @@ -15160,78 +31715,149 @@ Mokkasiini Mokke-senpai Mokkis Moksa +Moksu Moku Mokum +Mokum Syl +Mola +Molag x Bal +Molars +Moldy Nuts MoldyChips Mole +Mole Slides Mole1 +MoleMan-II Molemountain +Moles Rule Molinas +Molkkipo Molle Mollem +Mollium MolllyPop +Molloyo Mollt MollyLlama Molokotorby +Molotoffer +Moltea Molten +Molten B +Moltenclawz +Moltres X +Mom Hunter +Mom Madness MomICantPaus Moments MomentsApart MommaCuz Mommy +MommyMish +Mommys Hand +Momoh flip Moms +MomsLasagna Moms_Spagett +Mon key +Mon3yy Mona +Monarchis +Monarchy Monday +Monde MonehBabeh Money +Money BTW +Money Bagz +Money Grabs +Money Mann10 +Money tyven MoneyMalone Moneyman +Moneyman 199 Mongke +Mongrel Hick +Mongstaman Moniez +Monika Liu Moniosaaja +Monitor Monk +Monk Fists MonkFishking Monka +Monka Blunts +MonkaFront +MonkaGrizz +MonkaSFish MonkaZter Monkadile Monke Monkees80 Monkey +Monkey D C +Monkey News +Monkey Pox +MonkeyDGazoo MonkeyHeadAF +Monkeyannie +Monkeyboy991 +Monkeydodo45 +Monkeyhug +Monkeys Ass +Monkeysick Monkie +Monkphish Monksmen Monkster MonnerMads +Monnivalas Monnual Monny Mono +Mono Y Mono Monopoly +Monopoly Mvp +Monotone 07 MonrealkaAfk +Monroejo Monsemand92 Monsilly Monsta Monstaarr +Monster Hog +Monster Tits Monster333 +MonsterKush +MonsterTrain Monsterofpk Monstrius Monstrocity Monsutaa Montagne +Montak +Montanaro Monterey +MonthOldMilk Monty +Monty Jr Monumental Monuu Monxanvrooo +MooGoo Mooch Moocow910 Moodeer +Moodoo Mooffa MoofinnMan +Moogly Moohcake Mooi Mooie Mooing +Mooing Cow Moojin Mookinater Mooksy @@ -15239,58 +31865,98 @@ Moon Moon688 Moon7I8 MoonCard +MoonDunes +MoonStaIlion +MoonWolf MoonYagami Mooncrafting Mooner Moongazing Moonish +Moonish Ale Moonjock Moonlightcb +MoonlitNika +Moonly Moonman392 +Moonr0cks +Moonshadow18 +MooonCakeee +Mooony Moopy +Mooqie Moordaap3 +MooreNoyce Moorleey Moortgat Moose +Moose Land +Moose713 +MooseEatBear Moosecup +Moosefangs Mooseheads Mooserini +Moosewizza +Mooseyt Moosy Moot Moowi Mooyee +Mopdussy Mopeds Mopedstian Moppeharry +Moppy +Moq puW +Mor Ul Neck Moral Morales Morally Moray Morbid +MorbinThyme Morch MordLacaroni +Mordacai Mordenumero2 +Morder-Biest MordinSolus Mordy More +More AFK +More Chillli +More Coala +MoreThermite +Moredots92 Morelos +Morfeusz +Morgan Donor +Morgan69 MorganAtkins MorganaTits Morghuan +Morghulish Morgo +Morgoth Man Morgue Morguhh12 +Mori Memento Morijo Moriquendi Moritz Morkius Morkret +Morkula37 +Morland Morlun Morlyx MormonFTP21 Morniingstar Moronavirus Morot +Morph1ng +Morpheus Aus Morphing Morphogene Morpice @@ -15300,71 +31966,311 @@ MorrisTheCat Morsey Morski Mort +Mort Eater +Mort Rigo Mortal +Mortal Coil +Mortalize MortarMan MortemPlaga +Mortituros +Mortle2 +MortonRamsey +Mortonnizer +MortresxD s1 +MorttMoryt Morue +Morvas Morytania +Mosade Mosaq Mosbol Moscosung Moseley Mosess +MoshPitJosh2 Mosio Mosiph Moska +Mosmo +MossadKiller Mosse +Mossels +Mossgiant +Mossy +Mossy Taint Most MostDreaded +Mostly Godly Mostoes +Mosychuk Moteha +MothQueen +Moth_29 +Mothafuqueur +MotherFigure Mothless Motikeli +Motion1010 +MotivaSean Motivated Motmans +Motochorro +Motor +Motse Mottis Mottly Mottookaa Motx Motyas Motzimoo +Moubu Mougi +Moukie Moul Mouldied +Mouldy Lamp +Mouley Mount Mountain +Mountan Drew Mourn Mourners +Mournhold Mous +Mousecream Mousekeys Mouselifter Mouseman298 Mousenn Mousie23 Mouteo +Mouthful Pip Move +Move Over +Move Ziggy Move2791 +Movember +Moviestar Moving Moving20 +Mow on mate Mowgli13 Mowk Mowt +Mox +Moxy Senpai +Moyaha5 Moyd +Moyis Moysey MozDef Mptrj +Mq4 +Mr 0wnage +Mr 223 +Mr 7o7o +Mr 9ine +Mr A +Mr Airborne +Mr Alba +Mr Alex +Mr Ashh +Mr Ayye +Mr Bagel +Mr Baggy +Mr Barakas +Mr Bazzi +Mr Beefman +Mr Beekman +Mr Believe +Mr Biceps +Mr Bijpakken +Mr Bond +Mr Boogley +Mr Brunoo +Mr Burton x +Mr C0KE +Mr CHM +Mr Chonky +Mr Chopz +Mr Comrade +Mr Costy +Mr Count Up +Mr Cryin +Mr Dan Solo +Mr Darzelis +Mr Deivis LT +Mr DirtyDan +Mr Dong322 +Mr Dreamcast +Mr Dry +Mr Dudeicus +Mr Dumbiller +Mr Durian +Mr Dylesxic +Mr Easyscape +Mr Egret +Mr Elmar +Mr Elysian +Mr EsKei +Mr Fathead +Mr Father +Mr Foe +Mr Freezie3 +Mr Fridge +Mr Funguses +Mr Geese +Mr General +Mr Gentil +Mr Ghillie +Mr Ghizar +Mr GnW +Mr GodLuck +Mr Hanki6 +Mr Hassan Fe +Mr Hollowx +Mr Hrodbert +Mr Hulbert +Mr Infinity +Mr Iron Bar +Mr Iron Gray +Mr Iron Owl +Mr Iron Poo +Mr IronAss +Mr Jacko +Mr Jam10 +Mr Jam1O +Mr Jasperr +Mr Johbi +Mr Jonh L +Mr Jordy +Mr Joshing +Mr Jot +Mr Kaasmof +Mr Kato +Mr Keyss +Mr KingCobra +Mr Kirbo +Mr Kiwi Bird +Mr Kman +Mr Kodai +Mr Kokkok +Mr Krabbsss +Mr L0af +Mr Laser +Mr Laz +Mr Leeee +Mr Looch +Mr Loser +Mr Lysol +Mr Mackie +Mr Manual +Mr Martel +Mr McCune +Mr Mentos +Mr Mikers +Mr Missiles +Mr Miyagy +Mr Moncler +Mr Mordacai +Mr MrX +Mr Nagoh +Mr Nasty Kev +Mr Nate +Mr Nebs Main +Mr Neckless +Mr No Rift +Mr No Sleep +Mr NoMates +Mr Nonya +Mr Ohio +Mr Oizo +Mr OldSchool +Mr Osc ar +Mr Ozzy +Mr Palm +Mr Pandaz +Mr Pastorius +Mr Peggers +Mr Phelipe +Mr Pita +Mr Platypus +Mr Pondman +Mr Poup +Mr Pretzels +Mr Questerr +Mr RaWaR +Mr Rebirth +Mr Rich T +Mr Robert +Mr Romm +Mr Ryker B +Mr S N S +Mr SZX +Mr Sasquatch +Mr Shaman +Mr Siege +Mr Sighco +Mr Slabs +Mr Slaw20 +Mr Spark +Mr Splitter +Mr Squicky +Mr Stan Man +Mr Syvan +Mr T C +Mr Takoya +Mr Tbh +Mr Teej +Mr Thornbery +Mr Troll +Mr Trump +Mr Untainted +Mr Vaidys +Mr Vanhanen +Mr Veegs +Mr Wieler +Mr Wild x +Mr Woods +Mr World 420 +Mr Woz +Mr Wumbo +Mr Xray +Mr XuRu +Mr Yozef +Mr Yum +Mr Yzi +Mr Zevosh +Mr Zio +Mr ensayne Mr noli Fe +Mr rubler +Mr spikey +Mr stony +Mr2ndPlace +Mr44 MrAlcotester MrAmazing MrAmbaal MrAngelxz2 +MrAngerfist MrAnkan MrAwesomeNL +MrB1u3 +MrBananaJoe +MrBeadyEyes +MrBeastly MrBeerNTits +MrBic MrBigLoads MrBigPecs +MrBigWheels +MrBingly MrBlueScreen MrBooBlocca +MrBorreby +MrBouncyButt MrBraa MrBry MrBryne @@ -15377,36 +32283,62 @@ MrCivilian MrCoolSkills MrCoook MrCoopahh +MrCowey MrDTails MrDairyHeir +MrDaive MrDarkBlue +MrDarkSide76 MrDarling MrDashwood +MrDeadInside MrDevice MrDevour +MrDoake MrDoofes +MrDraconite +MrDumbaldore MrEasty +MrEdgaras +MrEmerica +MrEnd +MrEwan MrExterm +MrFANG MrFancyboots MrFarrell MrFlizz MrFluffy97 +MrFreakyFrog MrFrizzesh MrFro +MrFrogRS +MrFuack MrGaalis MrGainz MrGanksta +MrGatorGnash +MrGeeeeeee MrGibbletts MrGixxer MrGodBrand +MrGoodbye +MrGraveLord MrGrind +MrGurbz MrGurn +MrGustuv +MrHatN Clogs +MrHeftyBag MrHobokian MrHummus +MrHypeK0 MrIWontMax MrIronChef MrJTheIron MrJad +MrJargon +MrJermu MrJoestar MrJohnnyx MrJonMan @@ -15414,17 +32346,32 @@ MrKadir007 MrKerrie MrKevinR MrKoalas +MrKyle +MrLaffy +MrMag MrManny +MrMatchett MrMaxLvl99 +MrMayhem +MrMeeseek420 +MrMeeseexs MrMell0w MrMime +MrMonkeyJock +MrMonopoly MrMonsterrr MrMooCows MrMose911 MrNL +MrNaf1 MrNatee +MrNeverWrong +MrNice98 +MrNieksas MrNikeKush MrNoBank +MrNoFgiven +MrNoFilter MrNoLove MrNook MrNorwayOS @@ -15433,75 +32380,169 @@ MrOceanic MrOctapus MrOngh MrOriginal25 +MrPK74 +MrPaip +MrPapaJoe MrPezcu MrPige0nz +MrPiggles +MrPlasters MrPoopiehead MrPork +MrPotionz MrPowers MrPutterLite MrQuaker MrQuick1 MrRaidUrGirl +MrRakoon +MrRangingElf +MrRawDog +MrRiceBucket MrRidder MrRight4U MrRobinHood6 MrRoboto MrRocco +MrRodgersHD +MrRojo31 +MrRumarak +MrRuneDrag +MrRyo +MrSanta94 MrScape2Much MrSensimilla +MrShneeeebly +MrShoarma MrSimQn MrSirOne +MrSkydive MrSlongerton MrSmiiLey +MrSmikkel MrSocorelis MrSolo MrSteelYoRNG MrStickyBudz +MrSucellus +MrSuibhne +MrSupo MrSusans +MrSwift00 +MrTanglez MrTibberfitz +MrTickMaster MrToad +MrTobyG +MrTooSerious +MrTough rs +MrTrashclikz +MrTryHard69 +MrTurds MrVillanelle MrVitable +MrWallnutt +MrWeageZ0311 +MrWest +MrWhetFartz +MrWobble420 MrWorldwidee MrYachie +MrZandra +Mr_B1ff +Mr_Hairless Mr_Kadir007 +Mr_Kapoo Mr_Manchello +Mr_Ostroum Mr_Schmeckle +Mr_Scoff Mrawrs +Mrbadwrench +Mrbaird +Mrbd Mrburnsss +Mrcoconut22 Mrdeemoney +Mrevil1 +Mrfuntime517 Mrfuzzy Mrglex +Mrhood +Mrjellyfish Mrjli Mrloonetick Mrm0rm0r +Mrmagoo0 Mrmanguy Mrn1ceguy89 +Mrpokoz +Mrpoopyface1 +Mrs Budie +Mrs Pure Cut +MrsFabler MrsJonesUFT +MrsMushrooms MrsPurpTurt +MrsSocorelis Mrslipkn0t Mrwaffleses +Ms Goblin +Ms K +Ms Lizziard +Ms Trap +Ms Zik +MsAnderzen +MsArachnea +MsBoothanqq MsFreakyFrog +MsGroves MsSev +MsethOWarq p +Mssp +Mstr Postman +Mt Eben +Mt Olympus +Mthrfckrmike Mthw +Mtn Dew Dew +MtnDewford MtnGoat +Mtp69 +Mtra +Mtv Cribs 07 Muad_Dib +Muahahaha45 Muahhahaa Muahuahuahua +Muas MuasBtw +Muay Mat Muaythai +Muc Gib +MuchBetta MuchGpWaste Muchly MuchosAssias +Muchy Muckball +Muco +Mud Cricket +Mud Temple Mud9 MudCatBigDog +Mudda Focha +Muddas Main +Muddy patch Mudguard +Mudkins Mudkip +Mudmur Mueezy MuerteBella Mues Mufasa +Mufasa IXI MufffinKing Mufficer MuffinActual @@ -15513,7 +32554,9 @@ Mugarooni Mugen Mugge Muggerman3 +Muggled Muggles +Muggtjuven Mugrub Mugy Mugzy @@ -15521,116 +32564,232 @@ Muhaji Muhamed Muhfn Muhkea +Mui Gokuu Muilpeer Muki Mukkaram7861 +Mukkey Muktheduck +MulasRevenge +Mulberry Mtn Muleleaveox +Mulky Mulle-mek +Mullet Mafia +Mullishus Mullvaden Mully MullyMammoth Multi +Multiloquent MultipleRats Multiplying Multitalent Multiway +Multizeta Multrix Mulugga +Mum3nRider +MumBanker Mumble Mumbles +MumblinSloth +Mummzy Mumriken Mums Mumspaghetti Munansurvain +Munchise +Munder Mundt Mungles Mungoe Mungu +Munia15 Munich Munire Munk Munkea +Munkefar Munkinut +Munky Munk MunkyBizness MunkyKnuckle Munn +Munnchicles Munqqi4862 +Munqqii +Munshae Muparadzi +Muphat Muppz +Murasa Murbez +Murda Turk Murder +Murdered +Murderings Murdimius Murdock Murdur +Murgambit +Muri Murilokooo +Murimekko +MurkWahlberg +MurlokMurlok Murogrim MurphRS Murphys +Murphys Lag +Murpman Murray +Murray 1991 Murre Murrloc Murrrum +Murt15 +Murtti +Murzum +MuscleNation Musftw Mushmom Mushroom +Mushroom Mtn Mushrooms1 +Mushtime MushuPorkPls +Musi c Music Musica MusicalMurdR MusicalStory +MusiclRevivl +Musicpunk Muskets +Muskintine Muskogee +Musky Whale +Muslimi Musschoot Mussy Must +Must Slay MustBeGanja +MustKillBill Musta Mustachio +Mustamae +MustangYak1 +Mustangs Mustard +MustardXD17 Mustasurma Mustekala MusterShelby +Musto Task +Musty Ropes +Musty Sailor MustyToofer Musuwu +Mut3dHasselt MutaNep Mutants Mutapets Mutated +Mute Pker Muteself Mutilated Mutsurini +Mutt a dile Muttadale Muttadiddle +Muttadude +Muttallica +Muugz +Muumipappa +Muunchyy +Muurxi +Muushuu Muutz +Muws +Muy Booty Muzbo Muzi +Muziek Smurf Muzket Muzz Muzzle +Mv P +MvP ov RnG +Mvk +Mvko +Mvp Scrub Mvvs +Mw2 +MxMay +MxSloot +Mxb36 Mxffin +Mxr Mxteorites +Mxtta +My Damie +My Dark Hell +My Dark Soul +My Death Bed +My Demons +My Dont We +My Dumb Iron +My Faith +My Fantasy +My GF isMILF My Gentiles +My God +My Iron Man +My Ironmain +My Ki +My Kill +My Kingz +My Limp GIMP +My Main Game +My Maine +My Mate Elm +My Name Vyga +My Pet Mocha +My Rng Ass +My Sana +My Secrets +My Ticks Now +My Ult +My pp stink MyAssLucky MyCatKillsMe +MyCtyNeedsMe +MyDuck MyElyNow MyFitPal +MyHandyMan MyIiu MyLastGo MyLoveFaith +MyMercy MyNAm3BubBA MyNameIs MyNameIsCole MyNameIsKent +MyNameIsTina MyNameIsTrev MyOSAccount +MyPetRicky MyProject MyRifleMyGun +MyRight Nut MySeed +MySkillsKill MyStinkHurts MyTakao +MyWanderlust MyWyvernAlt Myams Myat @@ -15639,88 +32798,240 @@ Mycreation1 Mydlong Mydragon8u2 Myers +Mygary Mygraine +Mykeh Mylar Myles +Myles_008 Mylifeisless +MylilBrony +Mylle Mylo +Mylo 7 Mylos Mylosas Myndemo Myoboku +Myosarcoma +Myoshi Myotoxin Myriadic +Myrm Myron MyronAynes Myrupz Mystearica Myster +Mystery Btw +Mystery X MysteryGifts MystiCool Mystic +Mystic Mak +Mystic Pizza +Mystic Voke MysticChompy MysticDrift MysticErebos MysticRiver MysticStrega +Mysticpuffer Mysticrobe +Mystics Main Mysticvaa Mystiic Myth +MythCerix MythCraft Mythic +Mythic Hiero Mythicat +Mythrin III Myto +Myuf Myuk Mywa +Myz Myzi +Mzaa +Mziy +Mzr +Mztar +N 10 +N 55 +N A l N E R +N E L L +N E N E +N Gallagher +N I GH T96 +N I N O X +N I S H +N ICK Y +N O B S Y +N U B U +N W M +N a t t z +N ang +N anko +N arb +N dejay p +N e a k i le +N e i l +N e0 +N iall +N ibbler +N ightgleam +N l C K O +N l E V E +N o m a d +N occo +N oggin +N u d +N uggies +N-J-R N0 H34RT +N0 Invictus +N0 pid +N00biistyl +N00bslayer27 N04me N0B4Marri4g3 +N0Ballz N0ID +N0LlMlT N0OneCares +N0T HC N0XPWaste N0blelegend N0llie +N0obalhao N0rse_k1ng +N0sie +N0t Maxed +N0t special N0tliketh1s N0ul +N1 CK +N17 Jake +N1C3 N1NJASK1LLZZ +N1ckai +N1cwho +N1nja N1njaCat +N3XX +N3p N3se +N3x +N4L +N4ruto +N4styNat3 +N7N +N8vy +N9NE420 +N9T7 +N9U +NABEEL RJ +NAGAKAMAL +NANORA NARPslayer +NASDBOY +NASSERN NASTY NAVl +NB8K 2K13 +NBA +NBA NewMain +NBA Youngb0i +NC90 +NCG +NCG 2 +NCPS +NEBR0SKY NECR0DANCER NEEDAMETHYST NEENEE NEET +NEET forever +NELSONORS +NENOS NEONiC NEWBEYE NEWFISHMATE +NEX IS WET +NEXFARMER NEYOVIC NFed +NHL Blues NHrn +NIIXIIK +NINJABLEV1NS +NINJATMNT NITR00 +NJC20 NJWW +NKJ +NL Chronos +NL Gilbert NLDeluXe NLFreakky +NMM Jaoel NMOS_giant NMZLetics +NO 1s SAFE +NO CHlLL +NO FEEL +NO MlDS +NO N R G +NO PlD NOAH +NOMETHESPORT NOOOOOOOOOO NORTHSEA NOSTALGlA +NOTTDY +NOTaPancake +NOmki +NPC Healer +NPC Icedrake +NPYJ +NRA NSFL +NSHN +NST Praise +NT FiSHvv +NT Y NTBeerBandit +NTMR RADIO NUEL NULLI +NULLlN KUPPl NUTSHOT +NVQ NWHL +NWI 219 RAT +NY +NY C +NY G +NY x LEGiiT +NZ Dave +NZL +N_MB +N_other_day +Na Mn Or I NaCl +NaCl Sprite +NaCl is salt +NaQ Naaath +Naafiri +Naais Naakkeri94 Naakt +Naaon +Naautilus +NabD Rank 5 Nabroleon Nabshadow Nabss @@ -15728,191 +33039,375 @@ Nabua NabyLad Nach NachB +Nachitto Nacho +Nacho Alt Nacho2030 +NachoByte NachoDragon +NachoPapi +Nacht Nachtkastje NachuiTuda +Nadaa +Nadeo +Nader +Nadsage Nadund +Naethera Naftininkas Naga +Naga Morich Nagisa +Nags NagyonJo Nagyung +Nah0824 +Nahida +Nahiida Nahkamestari Nahuel +Nahyol +Nahyun NaiiSha Nailbox Nailed Hard +Naimsen +Nainenoon +Nairda Niam +Nairda Nori Nairino +Naisu Najda +Nakal +Nakama NakedTwister +NakednFeared Nakke176 +Nakkee +Nakkesleijer Nakkimauno +Naksitr6ll +Naku Nakuz Nakuz0r +Nalle Puh FT +Nallieheai Nalsara +Nam +Namcel Name +NameECJ NameRjected NameWasBannd +Named NamedGenius Namelessdude Namelus NamesAreMeh NamesHisoka +Namine Silke +Namir Nammer Namuko Nana +Nana Steel Nanado Nanciscor Nancyy Nander +Nandos +Nandos Man +NangMan Nangdalorian +Nanimavi +Naniva Nannertee Nanno +Nannu Baba +NannyCam69 +Nanoh +Nanoman360 Nanonymouse +Nanook IV +Nanoray +Nanotech Nans NansBeaver +NansCumTowel NantaoL +Nanyts Naoe +Naoe Y +Naoe Yamato NaofumiLTU Naoka Naow +Nap Tackle +Napaaaaaaaaa Napalm Napanderii Napettaja +Naphtic NapkinFork +Napnapnap8 NapoleanBra +Napoleon +Nappy Head Napsutaja Naqu +Nara ven Naradas +Narbose Narby +Narcan Saves +NardDog +Nareg +Narel1a +Narendradath Narg +Nargarothian Narked Narkon NarnodesNono Narrative Narry Nartens +Narth Calior Narthalion Naru808 Naruto Narval Narvalow Narwallus +Narwhal1731 Narx4 +Nas is like Nasa Nasaman +Nascar Naseeph +Nashh Nashluffy +Nashonic Nashy +Naskarsdad +Nasko 07 Nasper Nasrullah Nasseee Nassim Nast +Nastacov Nastie +Nastik Nasty +Nasty107red7 NastyAss +NastyCasual NastyDonger +NastyGarbage +NastyGeUsers NastyV6 Nasuuu +Nat Scheetje Natalie +Natby Nate +Nate Dogg g +Nate Joggers NateDoge +NateStayLove +Natebroh +Natedog 1104 Naternater +NatesOSRSAcc +Nath Meister +Nath btw NathJeaL Nathan +Nathan A +Nathan Lyon +Nathan Novak +NathanTurn +Nathandrthal Nathanyuelle +Nathn Nationwide Native +Nato is Jake +Nato888 +Natoh +Natoroid Natrox999 Nats Natsu +NattNub Natte +Natte Dop +Natte Dream +Nattetid +Nattkungen +Nattmara Nattraps Natu +NaturalBeaut Naturally +Naturally Me Nature +Nature B0Y NatureNymph +Naturealis Naturejacks Nauce +Naudra +Naught Good Naughtpure +NaughtyPanda +Naukahtaa +Naukkiss Nautis +Nauuyn Navas +Navbrah NaviRio Naviaux +Navidson1 +Navn Navraj Navtik Navy NavyDD214RET +NavyLight +NavyPunk +Navyseals199 +Nawberry +NawtyMonkey Nawus +Nax Naxacid Naxiius Naxito Naxos Naxtzi +Nay RS +Nay0101 Nayna Nayrus +Nayrus Love +NazTehRpR Nazgul Nazty Nbba Nbcw +Nbsniper69 Ncpure Ncrr +Ne x is Ne3po Ne86 +Neak +Nealonl4 Nealos Neals +Nealvy Neanderthal Nearly Nearomancer Neatkii Neav Neb0lith +Nebb Nebbo +NebbyGo2Bag +Nebezaidu Nebijok Nebrosky +Neccto Nechromancer Nechryass Nechs NechtKnecht +NeckBat Neckbeardis Necksnipped NecroEric +NecrodedGSF Necrokingns +Necromatus +Necromooser +Necronomist Necrophorum Necrosauruss Ned1991 +Neddam NederweertV2 Neduks Nedus +Nedved Nedward +Neeby Need +Need 2m +Need A Pint +Need Femboy +Need GP Now +Need Protein +Need Rogaine +Need Spoon NeedInternet +NeedMoore +NeedPurp4Bed Needs +Needs Coffee NeedsADad Needtomboy +Neeech Neefey +Neeisnet +Neekkoco NeekoNeekoNl Neekomata Neekss +Neelen +Neems +NeetScape +Neetman +Nefarious fe NeferSeti +Nefereous Neffiz Neg14 +NegAttiveI Negan Neganeogami Neghed +Nego Baby +Negrong Nehxy Neil +Neilthedead +Neintein +Neitiznut +Neitiznut Jr +Nej tak Nejvalt Nejvash +Nekalbink +Nekkopanda +Neko Inori NekoSayNyaa +Nekomata Nia Nekomimi +Nekromant Cz +Nekrukeisari +Nelaimingas Neleron Nelhium Nelkirr +Nelli Matula Nelliell +Nellysan Nelox Nels0N Nelsi @@ -15926,154 +33421,295 @@ Nemaksciai Nemba Nemerrr Nemesis +Nemesis2020 Nemf +Nemijin +Nemipro Nemisys +Nemj Nemmo Nemo +Nemo_o Nemonia +Nemoven Nenah Nendou +Neng_Thao02 Nengah +NeniHead Nenio Nentsukka +Neo +Neojoramony Neon +Neon Christ +Neon Juan +Neon Slinky +Neon Volts +Neon xxv NeonChilli +NeonGenxsis NeonM1d +NeonO7 NeonPaladin NeonRhythm11 Neonik Neonke Neopia +Neoplasia Nephedes Nephyrion Neppe +Neptune169 +Ner +Nera Obuoliu NerbBlaster Nerbles +Nerbs Nerd +Nerd Body +Nerd Owns +Nerd Stone Nerda +Nerdbob Nerdcore +Nerdier +Nerdpuff +Nerf Bowfa +Nerf Coffee +Nerf Th1s NerfMePlz NerfTG Nergegante Nergg +Nerio x +Nerithma +Nermzz7 Neroxcen +Nerraw +Nershi Nerve +Nerve Cell Nesk +Nesquiik KlD Nesretep Ness Nestedloops +Nesties Nestl3 +Nestorianos Nesuvarzytas NetTrap +Netamu Netanelba +Neteroem +Netgear Nethada +NetherToxin Netho Netjes Netmn15 Neto +Nettipoliisi NetturDab Neturtingas Neural +Neuro Lepsis +Neuro-Tomb +Neurologist Neurophys Neurovelho +Neut +Neutral Game +Neutralised Neutrally Neutronas +Nevar89 +Nevena Never +Never Die113 +Never Spoon +Never die +Never2Clever NeverAssume +NeverBudge NeverEnding NeverFreeze NeverGetRift NeverGunaMax +NeverImprove NeverLateWiz +NeverMoves +NeverMyFault NeverQuest NeverRespawn +NeverSailing NeverSober NeverTrading Neverender27 +Nevermaker Neverover Nevi Nevik94 Nevinnn +Nevit +New Monkey +New Tooka +New journey +NewAgsWhoDis NewBoy4321 NewDad NewFavorite +NewHobby +NewMobWhoDis NewPlayerx13 +NewToBossing NewWrldHodor +NewZealands Newb +Newb Ranger Newbillnye +Newby NewcastleFC NewfieTinMan Newfiebanger Newguy2003 Newleesh +Newlut NewrockkuOS Newst0nekid +Newt Jacuzzi Newtman907 +Newton 1 +Neww Zealand +Nex Afg +Nex FFA King Nex Is My X +Nex Minion +Nex Myself +Nex leecher Nex1s Nex2169 +Nexarion Nexcellent Nexeiy +Nexfinity Nexgen Nexi Nexil Next +Next Day NextPet +Nexus Sire Nexx +Neya Neyburr Neye +Neyes Neyugn NezFix Nezqi Neztea +Nezuk o NghtPnda Ngis +Ngyessiree +Nh3r NhaleXhale Nhan +Nhest Cutter Nhimzo Nhouse20 Nhyrenn +Ni +Ni ke Niahl +Niall x Niawag +NibblyTitter +Nibbyus Nibexx NiblaNoss +Nic +Nic Machine +Nic Nasty +Nic Nerc +Nic co NicMachine Nicannand +Nicao Beck Nicashi Nicathan Nice +Nice Adept +Nice Caulk +Nice Iron +Nice Nice +Nice One +Nice Peaks +Nice Pets +Nice try guy +NiceGuy Edy NiceGuyEddyy NiceMarkMark +NicePotatoes +Nicely High +Nichohls NicholasRage +Nicholaswei Nichy NiciValbuena Nick +Nick Grows +Nick Ints +Nick Lopes +Nick Sellers +Nick X10 Nick0hwolf +Nick1234101 +NickChubb24 +NickReady +NickScape NickSpoof NickTSMITW NickVo NickaClassic Nickernack55 Nicki +Nicki Menage NickisBackyo Nickk Nickmitz23 +NickmyKnack Nicknao +Nickolai Lol Nickool4 Nickos +Nickoss +Nickoudbier1 Nickroo1234 Nicks +Nicks OSRS NicksNipples NickyPunky Nickynice23 Nickyy +Nickyy G Nico +Nico BE +Nico Le Chef +NicoFreakOh NicoIas NicolaSturge Nicolai +Nicolaj Nicolas +Nicoo +Nicophilia +Nicsyth NidaNewName Nidalee +Nidgen Nidh Nidhogs Nidk @@ -16081,26 +33717,45 @@ Nidmann Nidoking110 Nidraugas NieI +Nief Niefable Nielaahh Niels1608 +Nielscorn +Nielsen9312 +Nielssjeee Niely +Nieman NietzscheJR Nieve +Nieve Hamtaa +Nieve Rivers +Nieve Task NieveIrwin NieveIsBad NieveIsThic NieveMeAlone +NieveTitties Nieves +Nieves Bean +Nieves Boob +Nieves Butt +NievesDead NievesThighs Nifelhiem +NifkeCove +Nifty Gifty Nigel Nighlist Night +Night Elf45 +Night Shade NightNurse +Night_Furor Nightbass Nighter Nightmare +Nightmare CX Nightmare028 NightmareSHW Nightolas @@ -16108,174 +33763,354 @@ Nights9 Nightsharp Nighttman NightxxShade +Nightz Watch Nihilismi NihilistScum +Nihplod Niihilism +Niiick +Nijah123 +Nijn +Nik-fil-A +Nikab Nikco Nike NikeOnMyFeet Nikez Nikit Nikkerpoo +NikkiJaxx NikkiQT +NikkisDD +Nikkisaur Nikko Niknea +Niko Solo NikolasOG Nikoo Nikronic +Nikskill Nikumei +Nikun +Nikz Niley +Nilitsu Nilpferd +Nils +Nilwh NilzZ +NimaNaruto Nimajineb +Nimble Snail Nimbubu Nimex Nimismies2 Nimlasher234 Nimloth_666 +Nimma Crew Nimmongel Nimrod Nina +Nina Dobrev +Ninanunana +Nine E L NineTs +Ninef +Ninesax +Ninetails Ninetales4 Ninevolz2 Ninfia Ningaa +Nini N Kiki Ninja +Ninja Bamsen Ninja Cow Jr +Ninja Rasta +Ninja1978 Ninja66 +NinjaNoodles NinjaPunch72 NinjaSpeed NinjaTurt Ninjaloff NinjasDark3 +Ninjee xo +NinjerNick Ninjunzo Ninjymate Ninook Ninorc Nintendogz +Nipaahv Nipes Nipitipi Nipp +Nipp-on +NippleSundae Nippppppppee Nipps89 NipseyHpvm Niseraru +Nishax Niskha Nismo +Nismo Ranqe +Nisramont Nissan NisseIadden +Nissmo Nistipata78 Nitefall3n +Nitepearlz +Nitetrip +Nith Nithe Niton +Nitro Crate +Nitro Dax +Nitro Rng +Nitro306 NitroCrate Nitroalkenes +Nitrognhorse Nitros +NitrosOxide +Nitrous Bro Nitsch +Nitsuj42 Nitt +Nittany +NitwitSchool +Niukkis Niva Nivex Nivory Nixby Nixi_NL +Nixiro +NixonsJowls +Nixvet +Nixxay Iron Nixy NixzTez Nizqa Nj0y Nkpi NlCK +NlCKT +NlLREM NlMBY NlSO NllCK NllL022 NlppleX +Nmf Euphoric Nmofm +Nnavs Nnoitra +No 1 There +No 99s btw +No Arcane No +No Autoclick +No Basic +No Death Tax +No DexL +No Diff +No Emphasis +No Fear X +No Fkeys +No Honor Yah +No Joggers +No Kwuarms +No Legs Lazy +No Logic +No Lucko +No Means Ya +No Meds +No More Bugs +No Much Bulk +No Normies +No Old +No Pets +No Rationale +No Rugrats +No Saint +No Senpai +No Sleepin +No Souldier +No Splits +No Submit +No Tax Due +No Tbow Andy +No To War +No Xp Waste +No Zily Luck +No ah +No toleranss +No ur roll No0dlehead No53 +No7 NoAntiVenom NoBankIRL +NoBanksNoThx NoBans NoBp +NoCreamy NoDayMercy NoDealEU NoDropForMe NoDurex4you +NoEdge707 NoFame +NoFang Wizza +NoFapp +NoFlipZone NoGoodSkills NoHelp +NoHesitation +NoInferno +NoIronManBTW +NoLife4Him2 NoLifeCue +NoLifeLevi NoLifeMain NoLifeMcgee +NoLifeScape NoLifeSincRS +NoLiferSoul +NoLimit NoLootBag NoLootNoWoot NoLove +NoLuck Mario +NoLuckBearku +NoMarinero +NoMercyUIM NoMo NoMore NoMoreTrades NoNumbers4me +NoOlmletSig +NoPainNoMain NoPolnT +NoPrims2k_kc NoPurpleAku NoRNGsmalle +NoScyOrStaf NoShit +NoSprayNoLay NoStore NoStrategy NoStress2Day +NoTangleroot NoTank4U +NoTexture +NoTradeBrad NoTradeForMe +NoVa ITI +NoVow +NoWaR +NoXpWast3 NoXpWasted NoZulrahIM +No_Dumping +No_Remedii Noah +Noah Dinnae +Noah G +Noah Luvs U +NoahB NoahGriffith +Noahfireball Noahs +Noam Chompy Noamonts Nobber Nobbys Nobelanerr +NobilityTorn Noble +Noble Gage +Noble Oats +Noble Sticre NobleCorey NobleVespo NoblesForRec +Noblood +Nobody Good Nobodyz Nobrain +Nobu +Nobudy Nobularlol Nocando Nocarred Nochill NocnyKoszmar Noco +Noctivagous Nocturnal +Nocturnal RS Nocturnal024 +NocwocDaLord +Nodens +Nodonge5 Nodorcro NoeLT Noeka Noem +NoemMeJePapi Noexi +Nofolkn whey +Nogal +Nogi Nogoodnms NoiScape Noig +NoirSandy +Noiserv Noisy +Noisy Luigi +Noita-akka +Noith NoizRock Noizex +Nokil Nokiny NolanAlpha +Nolch +Nole Jr +Noley Nolifepvm Nolifer +Nolifer 28 Nolly +NoloadRIP Nolungs Nolzeyy Nolzzz +Nom C +Nom Ruby NomCensurer +NomNomSoulz +NomadForseti +NomadRek NomadsLife Nommmy +Nomoenoobs Nomonater Nomskichooo +Nomtiq Non5ens31 +Noname Nate Nonc None +None Feared +NoneOther Nonke +Nonni Nonplayer Nonreal Nonsense @@ -16283,29 +34118,50 @@ Nonstop Nonvalid Nonwestlee96 Nonwitzki +Noo Promises Noob +Noob Man +Noob N Smoke +NoobHey NoobPkedMe NoobWrecker Noobacleese Noobalhao +Noobe15 Noobest Noobicidal +Noobike00525 +Noobirini NoobishAct2 Noobs +Noobsscape +Noobtyle Noobtype +Nooby Noodle +Noodle Dude +Noodle Me Noodle Soups Noodles +Noodlike Noodz Nooki Noolbort Noon Noons +Noonshake Noopi757 Noorbee +Noorden +Noosii +Nooster Noot NopePope +Noportals NorCalGreens +Nora Flora +Norbet +Norbsi Norchis Nordas Nordfeir @@ -16316,270 +34172,660 @@ Nordstrand Norfok Norge Norhig +Nori Nitsuj Norilsk Norimasa NormHadAFarm +Normabel NormanBates +Normans Normie +Normie Main +Normie helm +NormieDalzii +NormieFYI Normies +Normy Narked +Norn Norqe +NorrSken +Norska +Nortenosk North +North No 2 +North Rmmbr +North1ane Northerly Northfork Northic +Northnewfy +Northrod +Northtoeast +Northxy +Norti Norton Norton_Gman +Nortoon +Nortron +Noscythe bad Nose +Nose Beerz +Nose Puncher NoseBeersies Nosetkl Nosevesey NosferatuBoi Nosni +Nosnorb Nosorow Nost4lgia95 +NostalgiaNp +Nostalgic +Nostalgic00 Nostalgimon Nostos +Nostrily +Not 0A +Not A Lover +Not A Robot +Not Bad +Not Brizz +Not Carlyle +Not Cynical +Not Dzop +Not Eternal +Not Flicking +Not Frac +Not Gaming +Not Ice +Not Internal +Not Ketho +Not Level +Not Lime +Not Lorppe +Not Med +Not Mesijus +Not Mikers +Not Muppet +Not Muppz +Not Panik +Not Perry +Not Rudy +Not Ryu +Not Salinger +Not Schuproo +Not Sharp +Not Soft Yet +Not Sotetseg +Not Tanzu +Not Tarczon +Not Tarny +Not Twistie +Not Vaxx +Not Yakosu +Not Your Nan +Not ZB +Not Zema +Not a Fan +Not a UIM +Not all +Not an elf +Not enough +Not even Dan +Not main btw +Not rn Babe +Not trivial +Not wow man +Not-afraidem NotAFKenough +NotAJ +NotALurer532 NotASkrub NotAStreamer NotAlright NotBiabanana +NotBot893294 +NotEp3 +NotEvenRare +NotGilthresa +NotHCJames NotKD +NotKailey +NotKnowMadss NotLefty +NotMatched +NotMaxinSoon NotMinty +NotN07NeMo NotNecro NotPker +NotPlateWolf NotReady NotShaneska +NotSoCasual NotSoHCZoro NotThaFather +NotUIM NotUrAvgTim NotUrBisnis NotValidName NotYerGuyPal NotaCola +Notanedgepkr Notanoob12 +Notfatprism Nothard +Nothin Lasts Nothing +Nothing Sold +Nothing2die4 NothingMate +NothinqThere Notjoeybloom Notlayla Notmyrsname Notori Notorious +Notorious N1 +NotoriousALB Nottarg +Nottingham +Notutoring +Notwind Notz +NouGIM Nour +Nouvelle Vag +Nov Nova +Nova Lova +Nova NK Nova Rez +Nova X1 NovaDragonX +NovaNovNov NovaNova_v1 +NovaaDay +Novacult Novahearts Novahria Novalisky +Novamus Novaqueen +Novaspell +Novelled Novem +November Air Novesey NovicePlayer +Novist Novizy +Now Boarding Nowa +Nowa Lyfe Nowlan2 Nowoxifer Nowt Nowuh +Nox Irea Nox1de +Noxai +Noxeek Noxelder Noxia Noxied +Noxif +Noxifer Nino +Noxifer Noob Noxifers Noxiti Noxitrall +Noy rs +Noys NozFox +Nozel +Nozzie +Nozzles +Npc Contact Nppb +Npzu +Nrsa Nrse +NsG Flames Nshit +Nsns khalifa Nsoak +Nsor Nssc +Nstfu Nt0y NtQuiteRamb0 Ntsf +Nu ff +Nub Cakes +Nub Cape +Nub Die Plx +Nub II Elite +Nub at PvM Nubby +Nubby Nubnub NubbyOtter +Nubciclez Nube Nube101 Nubje +Nubslie +Nubthhh Nubutraum +Nuc1ear Nuck +Nuck Formies Nuckie34 +NuckinPhutty +NuckkinFuts +NuclearDron3 NuclearShift +Nucleons Nucleotide Nucu +Nue +Nuffedyr +Nuffers Nuffyz Nuffz +Nuge Hews Nugget +Nugget Farm +Nugget8453 +Nuggo Nugs Nuhapiippu Nuigaia Nuirokay +Nuk3rO +Nuke Nuke Rofl NukeDuke98 Nukkumassa +Nukooa +Nukster +Null God +Null Quiet +Null Scaper NullObject +NullTalisman +Nulliko Nullish Nullly Nuloh +Nulsen +Nuluki +Num1 StepSis NumTaker Numazu +Numb God +Numb Too +NumbButWhole +NumbaWanGIM Number +Number Forty +Number is 47 Number1 +Number1 Bass Numbermatch Numel Numenor21 Numerater0 +Numerikaali Numidium +Numinious Numismatist Numpad +NunWithAGun Nuna Nunac Nunc Nuno NunsRtight Nunsbox +Nuoli Z +Nuori Karhu Nuparu22 Nupayne Nupiso Nuqubba +Nuqx NuranJeezes +Nurco Nurdal NurgleBurgle +Nurrminatorr Nurse +Nurse Turbo Nurselie +Nursering Nusky Nussi Nust +Nut Nut +Nut on Nieve NutStains +NutZak +Nutgood +Nutipaa +Nutjes Nutrino +Nutta Nutu Nutviper +Nutwic Nuubby1 Nuubi85 Nuuh Nuuhi Nuux Nuwanda +NvMe NvMy +NvMy Madness NvUs +Nvh Nvidas +Nvious7 +Nvr Ironman Nvsh Nwkz Nxcv1 +Ny e +NyThinIsFine Nyaa Nyalesh Nyam2 Nyannoid +NyarkThunaki +Nybocs +Nydarb +Nydde Nydloh Nyesqui +Nyholmeen +Nyk X1 Nykat Nyler +Nymlonn Nymph Nyppe96 Nyquistt +Nyranger99 Nyraxion Nyrkki +Nystuen +Nythan Nythos +Nythsama Nytrate +Nytrogen Nyula +Nyx Avatar Nyx296 +Nyx_TrueShot NyxxiePixxie +Nz Str +Nz Boy 96 +Nz Str Nzfisher +NzhiaT Nzpkers +Nzz +O C M W +O E M +O G Herbs +O G RasTa +O K E Y +O L D Z E +O Lewis +O N W +O O 9 +O O O O O O +O Rodrigo +O TUGA LINDO +O X Y G 3 N +O ctopus +O dhran +O hio O l m e w +O m a r +O o g a +O s s e +O stake +O-Scape +O-Six Newb +O-SobaMask O0BY +O5O5 +O64 +O7 offroad +O93 OBD2 +OBGYN doc +OBKush69 +OBLV Empson +OBLV KKRKAT +OBLVPIPEBOMB +OButterstick OCBP OConnell ODarnUFail +OEM +OFFS NFS +OFS I +OG AlanEspo +OG BlowsCOX +OG Boney +OG Ezena +OG Germ +OG Greenery OG H4zed +OG Horizon +OG IronAaron +OG K1ng +OG Kassu +OG Kenobi +OG Mr Crispy +OG PvMer +OG SUOMINEN +OG Sage +OG Soul +OG StrongBoy +OG Totti +OG not OJ +OG-Bebardo +OG2 OGBloodFam +OGJezus +OGKingRavenZ OGLman416 OGRockstar OGTeacher OGThicPickle OGWhitePanda OG_Westside +OH NO PLZ +OHC +OHP +OH_mes OHv3rdose +OINK OINK XD +OId Nite OJ AVENGER OK Thug +OLD MAKAVELI OLUTMIES +OLY Krzanich +OLlVER +OMEGAPEG +OMG U DID IT +OMG a GIM +OMGstepbwana OMNIV0RE +OMX OMYLANTAAAA ONCES ONDERBOKSEM +ONE EYE Q ONEBIGJOKE ONEM0REBEER +OON HUMALASA OOOGAABUNGA +OP Yoyoei +OPEN NA N00R OPIronman OPName +OPP2 +OREG0N ORLZU ORlCHALCOS +OS Anthony +OS BAKA +OS Badger +OS Flexin +OS Gdtn +OS Glory +OS Hadley +OS Iron Life +OS Jordan +OS Lou +OS Maroko111 +OS Masochist +OS Nat +OS Reecy +OS Versace +OS Weesh +OS dah +OSBudknight OSBug OSCannabis OSCastleWars OSColbyStock OSGingerkiin +OSGraham OSGrindscape +OSHH OSRASS -09Reaper -09Rhys -09Rvape +OSRS +OSRS Brody +OSRS Cyze +OSRS DANI +OSRS Denmark +OSRS Dresse +OSRS Hostage +OSRS Jim +OSRS Joshua +OSRS Keegs +OSRS Moey +OSRS Rapaaja +OSRS STIMPY +OSRS TOBI +OSRS Tired +OSRS Zezima +OSReaper OSSD OSSoulwars +OS_AndyB +OS_Jazzy OSzerox +OTF SPRINKLE +OUTSlDERS +OWE N OZANN +O_o +OachKatzal +Oak Cliff +Oak Tree Ted +Oaonui +OasisRS Oathbringer Oathh +Oatmels +Oatre OavTXXrC2Bc +Ob1tuary ObZenpai Obama Obama2014 Obanana Obby +Obby Apples Obby Cam +Obby Cape +Obby z +Obby200 Obedar +Obelisks +Oberschicht Obese +Obese Scrub +ObeseMaurice ObeyBdubb +ObeydaWalrus +Obfuscatiion +ObiHiGround +Obib Object62 +Objection +Objektas Objektijuht Oblitergator +Obliticks +Oblivion Oblodzisz +Obloid Oblv +Oblv Jass +Oblv mobi +Obnoxious Oboi +Obos +ObscureFruit ObscureHeart ObscureLogic Obscuremelon Obsel Obsidian Obsidian222 +Obtain Shade Obvious Obviouseboyz OcaJomba Ocachobee Ocara +Ocara Debrew +Ocarious 2 Occ0x Occcy +OccrumsRazor Occulent92 Occupation Occupational Ocean +Ocean Fog OceanMachine Oceanside Oceanux +Oced Ocellari +Ocelvon +Ocg +Och Ochen Ochit Ochrie +Ockult +Oclusvision Ocra Ocst +Octagawn +Octane07 Octane09 Octanes OctarineJake @@ -16587,155 +34833,375 @@ Octave Octavia Octet October +October 12th +Octoberain Octopossy Octoppus +Ocuflox +Ocular Rift +Oculist +Ocyd +Odang +Odawg121 +Odd Focus OddPhallus +OddSaus OddSnipa +Oddjob46 +Oddloop Oddni Odeee +OdenKozuki OdensWinterG Odeon Oder Odezt Odin +Odin Slayin +Odissious +Odiums Champ Odlaw Odonodb +Odophru +Odors Odssy Odsza +Odyssey Fe Odyssey310 Odysseyyy Oenhausen Oenonymaus +Oepeloetje +Oepsie +OetOet Oetje +Of The Rune +OfThePirates +Off Pace +Off Rate +Off a Bar OffMyChest +OffPeesh Offer Offering Offers +OfficerTFist Offka +Offlime +Offret Offset OffsetPaul +Og Voldemort OgAcco OgChrisCudi OgDankRiddim OgHood +OgSephiroth Ogazumu Ogg25 +Ogisek +Ogkek +Oglong King Ogmj Ogopogo5000 Ogre Oguussie +Oh Bee One +Oh Billy +Oh Canadian +Oh Daddy Yes +Oh Edgeville +Oh Gzuss +Oh Hi Marc +Oh Im Ben +Oh Its Toast +Oh No Oreo +Oh So Alone +Oh Tylor +Oh Vacancy +Oh sh Oh4Sure OhDannyBoii OhEmGe OhHaiMark OhHeyGrant +OhIScott +OhItsMatt OhJezuz +OhLookABot OhManOhJeez OhMyJosh OhMyShoulder OhNo OhNoMyHymen OhTurtle +Ohbi +Oheck Im Fe OhhCaleb +OhhMikey OhhTiS Ohio +OhioTexas +Ohlander +Ohm Calvin +Ohm Free Ohpiate Ohseeya Ohtoodles +Oi +Oi Matey +Oi You +Oie Oifey +Oij Oikeisto Oikis +OilHawk +Oiler1k Oilertay +Oilux OilyMeat Oinky Oishii +OisnesA Oispa +Oispa Kaljaa OjibweJohn +Ojigkwanong +Ojman +Ok Bud +Ok G +Ok Jose +Ok a y +Ok-sail zip +OkYh +Okadolf +Okageo Okaiko Okay +Okay Mommy +Okay Papi +OkayCCal OkayTwilly +Okeechobee Okeydoke Okino +Okke +Oklahoma Rat +Oksa Okupant +OkzobRS +Ol Mucker +Ol Salty Dog +Ola Nordmann Olajuwon +Olav Jr Olav2002 Olaveraaa +Olaviitsio Olbyy +Old 9m9a9 +Old Abe 101 +Old Anao +Old Beer +Old Bill +Old Birdy +Old Boy +Old Champ +Old Dabs +Old Delf +Old Dry KBAC +Old El Paso +Old G ordao +Old Greggg +Old Jedi +Old Lancer +Old Man Bob +Old Man Cris +Old Man Rabb +Old Maxie +Old Mog +Old Monkey3 +Old NlCO +Old Nutbag +Old Olorin +Old Pixels +Old Player22 +Old Rangoon +Old Sbi +Old Schooled +Old Toaster +Old Yammu +Old man Kent OldBae OldBlueish +OldBruce +OldDirtyMan +OldFishLife +OldGamma OldHitta +OldHulver +OldQwaltz +OldRzzlTrog +OldSkewlRS OldSkoolKush OldSteinlein +Oldbaldman5 Oldburnzy Olde +Olde Nite Oldemark +Oldinsh Oldizjr Oldman +OldmanP +Oldmanhandz Oldschool Oldschools OldskuleRS +Oldsusik +Oldtimate +Oldwhiteman +Ole +Ole IrIsh +Ole Martin OleFrumpacus +OleMusky +OleStinkBait +OleTejas Oleg Olei Olemand8 Olen +Olen Iron +Olenpromees Olertomb Oles OlesDpaul Olette Olfre31 +Oli +Oli xo +OliTheFarmer Oliivi +Oliivi Rouva Olimpus Olios Olivas Olive +Olive You +Oliveinho +Oliver GIM +Oliver The G Olivia Olkikalsar +Ollie 01 +Ollivanders Ollonjonny Olly +Olm Alone +Olm Likes me +Olm Nut +OlmMyGod +Olmar Olmek +Olmie Wolmie Olminous Olmlet Olmlit Olms +Olms Daddy OlmsNutz Olmsbish +Olmspetwhale +Olobor Olrox +Olspa Rahkaa +Oltsu Olvi +Olympic 33 Olysian Olze +Oma r +Omaci Omar +Omar Kai +Omar Khaldun +Omar Uchiha Omarinski +Omatunto Omaxiu +Ome Sjors Omega OmegaBeast OmegaRs3LuL +Omegathletic +Omegatron +Omen Forrest +Omena3 +Omerta Omfg +Omhellz yea +OminousMan Ommetje Ommy Omne Omni +OmniRick Omnicide97 +Omnient Omnivaw +Omolon +Ompikuusi +Omroep Max +On Blocks +On Rate +On Steven Dr +On Tv +On a Bar +On the alt +OnAMeme OnDeaTHrow +OnPoint OnRedPanda OnTheEdge +On_log_n +Onana Onbekend Onbekende Once +Oncey Onchune Oncle +Oncle Jazz +Onderwerp +One Arm Chin +One Eyed Owl +One Lazy Cat +One Leaf +One Off +One Piece X +One Record +One United +One Wolf +One au One life lad OneBadNWord +OneBoxBox +OneCallBTW OneClickMan +OneDayIs2Day OneFalseStep OneFive +OneForAll8th OneFunkies OneInchDong OneInchPeen OneJohn +OneLeg1 OneLifeGiven OneLostMain +OneManBand OneManBucket OneManNoob OneManTeam @@ -16748,201 +35214,383 @@ OneSillyBoi OneSnappyBoi OneTera OneTickAway +OneTickBrick +OneTickyBoi +OneWhoKnox +OneWish Onebuc +Onedeadthing Onehidefrog +Onelaughbob Onesecafk +Onesome Onetick Onexia +Onfight +Ong Gia Onidhre Onika OnionGoggles Onism +Onitir +Onkdah +Onke +Onkel Dunkel Onkelleif +Onkologen +Online Coach Only +Only 1 Iron +Only Bussy +Only Crazy +Only Fight8 +Only Scotch +Only Victims +OnlyBans OnlyBrand +OnlyChompies OnlyCraig +OnlyDanss +OnlyDrags OnlyFFAns OnlyFans OnlyFansss +OnlyFlies +OnlyGain +OnlyJars +OnlyJoel +OnlyJordann OnlyKingKoob +OnlyKisses +OnlyKnuup OnlyPepsiMax OnlyRussell +OnlySolos OnlyTheCold +OnlyWithTime Onlyfans Onlyfarm OnlyyMike +Onn Onno Onoezeleer Onoin Onox OnthatGrindd +Onu-sama +Onubis +Onus Onuzq +Onxaba Onya Onyksi Onyx +Onyx Farming +Onyxe Onze +Oo Step Back Oodenssiii Ooelluoo +Oof Dankus Ooft Oofus +Ooga Booga C +Ooh Skill Em Oohf Oohfunkyme +Ooiboi OokOokStrats Ookfried Ooktism +Oomp Oompy +Oooh Baby +OopsiePoopsy +Oopsralla Ooskabible +Oouu Weee Ooyf Ooze Oozymooz +Op Closed +Op Wout +OpGetGood +Opa Bravo +Opa Snipes OpaJei +Opacki +Opal Mafia +Opalfruen Opatsuno +Opel Vivaro Open +Open GL +Open osrs +OpenAI GPT4 OpenTheTill +Openpuppygo Opera Operacional Operetta Opex Opgezwolle Ophelia +Ophelia Prim Opiez +Opihr Opinionated +Opitz OpiumWard +Opkikkeren Oponn OppaSky +Oppai Heart +Oppai OwO Oppanox Oppheng +Opposite OppositePoop Oprego +Opreus +Ops +Opt Optic +OpticAGS +Optical itch Opticplex Opticplex09 +OptimistLuke Optimus +Optimus Pork +Optiver Opts +Optus Optyfen Optyfengauww +Opus Deo +Opus149 Opus22 +Opyomi +Oqagin-san Oqlak OracleOf +OracleStud Oraclez Orange1213 Orangeboy333 +Oranje Panda Oranqe +OrbWeaver Orca Orcanater +Orch Orchazm Orchid Orchidzx OreSpasm Oreano +Oreeezy +Oregon Weed Oreinstein +Oreo Empire +Oreo UwU +Oreo Wafer Oreos OreosInMilk Oretizm Oreton Orezzer Organic +Organic Hemp OrganicOnion Organics Orgasmique +Orgo +Ori lion Oriaks Orienterare +Origens +Origin Puff +Original BA +Original Blu OriginalGoat Originaljim Originexo Orilion +Oringl Wafle +OriobanaOuhi +Oriole Orioles OrionDragon OrionRenegd Orjan +Ork Merchant Ormi +OrngFish OrngeManBad Orodyn +Oronius +Orphaaan +Orphaan Orphan +Orphan Annie +Orphan Soul +Orphan Twin +Orphan8r +Orpheus +Orpoerpo Orrey +Ors striker Orthago Orthiss OrthodoxJoo OrthopodMD +Orvud +Oryx Aksis +OryxZebu +Os Him +Os Hitman +Os Rolex Os SMDJ OsBlackBolt OsBrody OsBudknight +OsDave +OsIronCrash +OsRs Vibes Osav +Osbenji +Oscar Jacob Oscarnight90 Oscietra Osdorp +Osetek Osgu Osgub Oshawnasi +Osidric Osimhen Osiris Osjuicey Oskar +Oskar XVII Oskari Oskinathor Osmo +Osrs Bane +Osrs Dimitri +Osrs Goku +Osrs Mistren +Osrs Woolley +Osrs2007 +OsrsBawlz +OsrsDavid +OsrsVibes +OsrsWiki +Osrshabibi Osscar69 Osseb Ossi666 OstBakarn Ostengar +Ostentatio OsteoSoon +Osteonics Ostidecriss4 +Ostmumten Ostracized Ostrich Osumi +Osvo1d Oswaldorun +Oswin Oswald +Osxu47 +Osykoo Osyrs +Otago Nz +Otakar Otaku +Otan Olutta +OtarsBeast +Othantos Othelllo OtherJackets +OtherWize Otho +Otomycosis Ottarl Ottchy Otter OtterMG OtterMan Otto +OttokarIII +Ottoman1907 Ottwanbre Ottzor Otyugh +OuchIFarted1 Oucho +Oud Nieuws Oudenophobic Ought OuiDaddy Ouija +Oukashi Oulusta +Oumaji Oumarou Oumu Ounaaja Ouncie +Our ClapTrap +Our Kid +OurLordAllah OurPage +OurTbow +Out Of Herbs +Out of Town OutOfBreath OutOnBail OutR Outbid +Outblasted Outblasting Outbox +Outbreak46 +OuterBodyXP +OuterShock +Outgrinded Outie OutlawBTW OutofQontrol +Outofcontrol Outohere Outperform +Outplayy Outra +Outs Outsider058 OutsidrR OuttaThePan Ouze Ouzi +OvO Ovaryacted Ovaryacting Ovela +Oven Dish +OvenGold +Ovenschotel Over +OverRoid +Overburner67 Overcame Overclockers +Overdose1911 Overhand OverkillWill +Overklokkd Overlegen Overload Overload_inc @@ -16953,155 +35601,334 @@ OverpowTV Overprepared Overrated Oversight +Overspan +Overspec +OvertPyro Overtaxed Overthinker Overtus Ovid +Ovl +OvrLrd Zaros +Owed OwenFever +Owip +Owl Full +Owl MD OwlMyLove +Owlea +Owlpeth +Owlson +Owly +Own Risk +Own Skillz70 Own617 Ownage Ownd Owned OwnedByMK +Owner Previn +Owning Owning4babes +Ownsz Ownt Ownyouall6 +Owusu Owwi +Ox Prez +Ox0 Ko0ol O0 Ox310 +OxStache Oxct +Oxcy +Oxeon OxideIon +Oxidising +Oxidizing Oxiduck Oximas Oxit Oxium +Oxjenks +Oxoi +OxyCottN OxyDream Oxycotton Oxyoxyoxyoxy Oyrn Oyster +Oyster37 Oyugock Oyvin Ozaiii +Ozak Ozcred Ozeana +Ozenc Oziarch +Ozin OzirisRS Ozium Ozmone +Oznerbon +OzokuLight Ozuhan OzyMex +OzzMate +Ozzb0 Ozzerro Ozzie Ozziemate Ozzio Ozzy +Ozzy Hobbit +Ozzykye Ozzys Ozzzyy +P 0 W N E D +P 0 E F +P 0 R G I E +P A M K A +P A P Z +P A R N Y +P DIRTY SODA +P EDRAO +P Eng +P I T +P K +P O L I S H +P O T A T O +P O V I +P Purts +P R O X +P R S +P V M Lew +P W A Y +P Y R O +P a n x o +P eachy +P erfect Ten +P h Z o r o +P i +P ix +P ixe l +P o z e +P oH +P ockets +P r o g r am +P udding +P ure +P uss Wizard +P00ksalukes P0CKETPUSSI +P0ES P0PE +P0RKB0I +P0ST HUMAN +P0TIONS +P0TTER P0TUS P0ddy +P0nti4c P1CC0L0 P1CK3R1NG P1Hat +P1SSBANDIT +P1ZZA EATER +P1ZZY +P1ckleR11ck +P1ssDr1nk3r +P1stols +P1tts P1zzaTheHutt +P1zzaa P2Chill P2D2 +P2P Race Car +P2w Scape +P3C P3RKELE P3RLICH P3RMMUT3D +P3T3 IS G0D P3TAR P3aceful +P3loce P3rcy +P46 +P4CK P4DLA P4RKER04 P4cH P4sk P5ythix +P6D +P7DRO +P9 +PA N I C +PACK WATCH +PACKETLOSS +PACTV PALAK1KO +PALL3N +PALSAM PALSANMAKI +PANTY DROPER PAPA +PASTORIKONE PATPATMAX PATRlOOT PAUL +PAULWALKER +PB Barbie +PB Dauntless +PB J +PBT Yumi PBTM +PBnJ +PC PrincipIe +PC0TE PCCZ +PCDO +PCE PDGA PDizzleworth +PE strategy +PE3ST +PEAMINlSTER PEARSON92 +PEC Zwolle PEEKYNUMBER1 +PEEinAcup PERMA +PERSE PET3R +PET3R PAN PETEAIR +PF Killaz +PFOF PFalciparum +PG MAIN +PG-13 +PGA_Pope PGMid PGmeupe93 PH1SH3DB4N +PHGomes PHLP +PHURY PIAN0 PICC +PIITAA PING +PINKYxBRAIN PITFIGHT PJ Salt +PJRovers +PK NOOB BR 2 +PK Shark PKTHEOTHER PKing PL4T1N4 +PLANET SHlT +PLAYER827324 +PLAZID PLSDONTPLANK POGPOGPOG POGvM POMP3Y +PONYRIDER73 POTTER +POTUS DJT +PPale PPorappippam +PQMF PQWNEM12XXSS PRADA PRAISE +PRAISE FOOT +PRAISEHELIX PRETTY +PREW0RKOUT PRIM0B0LAN +PRIZ0NM1KE +PRODaintOFFu +PRlNCEE +PSMark +PSO Pokie PSRB PSTjager +PSY OPERATOR PSacz PTKNT PTMN PUBG PULL +PULL A GLOCK PUNANYCEZZ PUNANYMASSIF +PUPPY SIT +PURP xx +PURPLE MAN X PUSHUPS PV60 +PVM PLUS PVP +PVM Zem +PVM lifee PVMGrim PVMramranch PVPJACKUS PWNJoLee PWNl +P_rple +PaIe Nimbus PaIm PaJau PaPaSaucee +PaPePiPoPuPy +PaR0 PaShango PaTeraNauu +Paaaants Paaatriick +Paarse Kat Paarty +Paatse PabIoEscobar Pablana +Pablo Q +PacDan PacYakJack Paca Pace +PaceYourself Pacellino Paciar +Pacifico0ler +Pacifist Pack +Pack Yarack PackAnother1 +PackYakistan Packapunchd Packers +Packers Ammy +Packfan35 PackingCope Packmanjr PacksOfBagel +Paco 41 Pactii +Pad of Note +Paddy Simcox +Pademelon Padge Padraig Padrew Paduann Paehkisfe Paem +Pafffy Paffio Pagan PaganFox @@ -17110,60 +35937,115 @@ Page Pagman73 Pahapukki Pahizz +Pahys +Paid 4 Paike Pain deliver +PainInTheAx +PainRain Painb0ws Painovoima PaintBoxx Painta Painted +Painz Wrath +PairODocks Paixo +Paiyrd Paizuri Pajaaay +Pajama0sam Pajaripipari Pajita Pakaika Pakanajumala +PakasteOlut Pakford Pakmaniac +Pakr04 Palabutoh Palad1um +Paladijn Mb Palapak +Palataan Palatro Pale +Pale Marble +Pale Player PaleCocoon +Paledeano +Paleek +Paleek sucks Palenaatio +PaleoRanger PalestineHC +PaliRebel Paliperidone +Paljad Pallas +Pallas Cat +Palle Panik +PalliJarn Pallihintti Palllister +Pallof Palmboom +Palmboom95 Palt +Palworld CEO Paly PamPams Pamdora +Pamela Isley Pampas +Pamz +Pan Biceps +Pan Jawel +Pana Sicknez Panacea +Panal +Panarin +PancakeOSRS +Pancaker Pancakey Pancukeshi Panda Panda Godz +Panda Pride +Panda Rua +Panda Seany PandaBier PandaBrommer +PandaKIKI PandaMan PandaMcfanda PandaPowa +Pandasadge Pandaux Pandaz Pandeh +Pandemicbowl +Panderal Pandiman +Pandini_O +PandorazBox +Panelka Panera +Panesii +Panette Panferno7 Pangolins +Pangs Panic +Panic King +Panic Papi +Panic Switch +PanicThenRun +Panicupdate +Panini Panixate Pankekee +Pankki on Panky Pannu Pano @@ -17171,32 +36053,82 @@ Panoople Panorramix Panqueques Pans_Gaming +Pansendoras PansophicaI Pantaloon +Pantelic Pantera1230 PanteraWalk Panthalassa +Panther_Cap +Panties D0WN Pantix +PantlessDuck +PantsShitter PanzerMarkV +PaoZi41 Paoul +Pap Smoke Papa +Papa Beat Me +Papa Beer +Papa Chibs +Papa Falco +Papa Glock +Papa Hitman +Papa John +Papa Kev +Papa Peck +Papa Penguin +Papa Raniel +Papa Rook3 +Papa Scape +Papa Shaydee +Papa Sheek +Papa Snacks +Papa YY +Papa Zuk +Papa jinx +Papa tim PapaCart +PapaFozzy PapaJohn PapaJoyce13 +PapaMoxie +PapaParsley +PapaSarducci Papabeer +Papagecko Papaija Papalotee Papapa Papaya +Papaya Pete +PapayaGod PapayaPetee Papegaaitje Paper +Paperbag Papi +Papi Baz +Papi Chop +Papi Feb +Papi Fish +Papi Gains +Papi Okapi +Papi Sam +Papi Sean +Papi Six +PapiTron Papicito +Papicodone +Papido PapieLexus PapierHier +Papierschere Papii Paplip +Papo Sauce Pappa Mauly PappaPizza Pappanopolis @@ -17204,65 +36136,120 @@ PapperNapper PaprikaBoi PapuIsThatU Papukaia +Papyea Fruit +Papz Mage Paqan +ParKy_ParK +Parabhjeet Parabolic Paracleis +Paradoos Paradox +Paradox 2277 +ParadoxAU +ParadoxCrux Paradoxal Paralimpian Parameters Paramost +Parandrus Paranosys +ParaplegicIM Parappa ParasiteHunt Parasitoid ParasoxX Parazino Parc +Parc Ferme +ParchedToast Parciparla Parent +Parfour Parhaat Pari +Pariera +PariguayoGL Parikh +Parikkala Parish +Parjesh Park +Parkchae Parkehh +Parker177 Parker1770 ParkerSquats Parkerrr Parkuh Parky Parkz +Parley0 ParmsG8 +Paroni007 +Paront +Parotis Parox3tine Parrot +Parrot Champ +Parrot Le Fe +Parrot Poop +Parsecs Partey Parth4903 Parthnix +Particulae Partly +Partonax Parttime Party +Party Fraud +Party Pete +PartyRock +Partyhaty Partynexdor ParuParu Parvovirus +Parx98 +Parxe kurita +Parzival32 Pasadinas PashkaPushka Pashmina Pasianssi Pasiiba90 Pasikaustes +Pasito PasitoBandit Pasje +PaskaJatka69 PaskaneHomo +Paskie Paskis Pasmo +Pasrules Pasta +Pasta Lance +Pasta Mancer +PastaShel Pastabrain +Pastafreezer Pastagonia +Pasticcione Pastor Pastry Pasu +Pasza1357 +Pat NoScythe +Pat The Nerd +Pat the Cat +Pat twumasi +Pat_y +Pata2006 +Patalopodus +PatchRS Patchley +Patdog666 Pate Patella PatentedName @@ -17271,6 +36258,7 @@ PathTracker Pathogen Pathways Patio +Patious Patmantheman PatoVelaz9 Patojo @@ -17279,19 +36267,34 @@ Patrexion Patrician Patrick PatrickClick +PatrickLaine Patrickp35 +Patrik Laine +Patriot88 +Patriotscape Patriotsp +Patriottj +Patrolliin Patronique Patrouski +Patryk 1 Pats Patsey PattMyGun Patta1 +Patte Pattos +Patty C +Pattycakes19 Pattyrick8 +Patyfatycake Pau1ekas Pauk Paul +Paul 0 +Paul Beer +Paul Ski +Paul0 H Paul007 Paul90333 PaulD @@ -17299,13 +36302,23 @@ PaulOH10 PaulTheRabbi Paulchritude Pauleee +Paulest Paul PauletteRose Paulius +Paulk23 Paulrat +Paulrat 3 +PaulyNFS +Paum No Xeem +PauperPlayer Paupy +PauseGuy Pauwels +Pauwels v2 +Pavies Pavio Pavla +Pavlacci Pavlvs Pawggrs Pawgz @@ -17313,46 +36326,80 @@ Pawko Pawlmeister Pawlu Pawlzer +Pawn 69 +Pawn M8 +Pawrie Pawwsy +Pax Mundus Paxin Paxy +Pay2ClickLol PayMyDeedFWD Payne_Trayne Paznos6 Pazuta Pazzo-Repack Pb Fe +Pb and Jd Pbby Pbkillua +PbyOne PdaddyReborn +PdfPKerNoGF +PdiddyReborn +Pe en +Pe t er +Pe1ipp3r Peabody PeacandLove Peace PeaceNLove31 +PeaceOfMind Peacebuild +Peaceer Peacefrog +Peach s PeachKing +Peaches5000 Peachh Peachhh +Peachy Tank +PeachyBrute PeachyDean +Peaco Peacoat Peak +Peakado Peake +Peake7 Peakleaf Peaky +PeanutBTW Pear +PearOfApples +PearlNechlis +PearlWeed +Pearlito Pearshaped9 Peasant +Peasyy PeatMoss Peatie Peba +Pebbex Pebblez PebisGuan Pebl +Pebu Pebz PecanBread11 +Pecker Punch +PeckerFish +Peckerflexer Pecki Peco +Pecs +Pectorialis Pecuni75 Peddler Pederbuus @@ -17360,30 +36407,57 @@ Pedestrian01 Pedro Pedro5901 Pedtato +Pee Jay Salt +Pee Kay Err +Pee Mud +Pee On Irons PeeJayPlayz PeePee Peeanut +Peeble +Peeeeeekaaaa +Peeke Peel +PeelMyCarrot PeeledBanana Peely Peen PeenLover61 +Peep Taimla Peepo +Peepo Parker +PeepoPants +PeepoRiot420 +Peeps Cx +Peepzilla PeerTheSeer Peernicus Peeshuuu +Peest PeetrusEst +Peevish Peevy Peezerthecat +Peg Boots +Peg My Arse +Pegasian Pegasians +Pegasus51C Pegi18 +Peha Pehkis Pehmolelu +Pei898 +Peighniss Peiin Pein Peipeilaile +Peipi Pekaia +Pekays Pekdon +Pekka Elo +Pekka-Eric Pekka557 Pekkaa Pekkaad @@ -17393,105 +36467,211 @@ Peksaad Pelaa Pelaaja1 Pelco +Pele Marreta +Peli Moapa Peligroso Pelikaen Pelippper +Pelirroja Pelmee Pelosi +PeltiPirkka Peltolammi +Pemiel +Pen Sir Pena +Penally GIM +Penance Boom Pencelis PencilVesta Pendax PendulumC Penetrader +Peng Lightey PengMaster +Penge1616 Penguin +PenguinBelly Penguino Pengwim +PeniAnus +Peniel Peninsula Pennstate Pennsylvania PennyPinchnJ Pennybag +Pennycord Pennywise Pennywise070 Pentagrammi +Pentektonyx Penthera +Penthrox Penthus Pentu +Penward Peopledud Peoples111 +Peor +Pep Kroket Pepar +Pepar Kakan Pepclub101 Pepco PepeGUH PepeHang PepeLaughing PepegaScape +Pepeh Pepemiguel +Pepo Is Me Peppey +Peppi PeppiEnSossi +Peppusieni +Peppy Pete Pepsi +Pepsi Maxed +Pepsi Maxia +Pepsi575 +PepsiMaxL1me PepsiTwist Pepsies Pepsipowars Pept +PeptoGlizmol Pepuszka126 Pequenaud Pequette +Per Ke Le +Perc 3m +Perceive +Perceptivity +Perch Curry Perchlorate +Percy Grail +Percy Nash +Percy Turner +Perduh +Peremees Perfect +Perfect Dark +PerfectCurse +PerfectJerni PerfectProof +Perfectaaa +Performax Perfringens Pergert +PerhapsGuy Peridots Perikles460 Peril Perkinatored Perky +PerkyPorker Perlen +Perm II Mu8e +Permabulk Permded +Permedd +Permer Permuh Pernix +Pero Scoped +Perox Perp67 Perpl +Perplox Perrault +Perrif +Perry Hubes +Perry T Persephatta Perseveranca Persian +Persilja +Perspective +Pert +Perterritus +Perth +Pervy x Sage Pesiz Pesoprkl Pessimism Pest +PestGodd Pestilance7 +Pestilent Bt Pestle +Pet Alpaca +Pet Awowogei +Pet Cape +Pet Crusader +Pet Eric +Pet Hunta +Pet KBD +Pet King +Pet Luck +Pet Meowtain +Pet Smuggler +Pet The Cats +Pet Ty +PetBoost PetCorp +PetHuntBrad PetHuntGrind PetHunta PetHunting PetPlease +PetSpooner PetUrSausage +Petal Petalite +Petar228 Petarss +Petched +Petchy inis +Petcord PeteRePete +Pete_901 Petega +Petelgeuse1 +Peteniice Peter +Peter DIY +Peter Dupas +Peter Kent +Peter97 +PeterLimbeek +PeterPlanker PeterRS PeterTheSalt +Peterh Peterm +Peterszoees +Petey pleb Petit PetitKeBeQ Petite +Petite Poire Petless +Petooted Petpet +Petrenkovitz +Petricsh Petriq PetroX77 Petrosian +Petting GIM PettyName Petuhh Petz +Peuramaa PewTheMeow +Peweherman +Pewming Pex3 PexBoi Pexci @@ -17499,56 +36679,97 @@ Pexezz Pexterity Pextill PeytyPoo +Pez xX +Pez za Pezy Pfiny Pfister Pfle Ph0g +PhD Fred +PhD Funk +PhD in TCG PhaMaTics +Phader Phaero Phai Phainesthai +Phalamon Phallic PhallusBigus Phamia Phamit Phant +PhantomDred PhantomFiend +PhantomLogic PhantomVS +Phantombear7 Phanton PhappleSauce +Pharaoh Chad +Pharaoh Ion Pharmafia +Pharqen Phase +Phasedd Phasing Phasmatus Phasmatys Phat +Phat Dik +Phat Pat PhatAsher +PhatFrat Phathead Phatman348 +Phats PhatsoCallum Phatt Phatty Phattyftboy Phaxe +Phd n Arteez Pheasant +Pheasant Egg +Phels PhenXX +Pheniex2 Phenomenal +Phensa +Pheonixess +Pher Phernix Phetty Pheus Phex Phi184 +Phibes Phil +Phil Coulson +Phil Mcrakin Philip +Philip424 Philipp Philkwl +Phille +Philli Blunt +Phillies +Philliez Phillip +Phillip R Phillipp Philly +Philly Sucks +PhillyFiller +Philoi Philosophia +Philou +PhilsBent +PhilsUnlucky Philth Philtration +Phin_C Phinxu Phinz Phipple @@ -17556,90 +36777,181 @@ Phishn Phizo Phlaja Phlegmy +Phlemming Phloppster +Phlopsy +Pho Z Phobias PhobosDeimos Phoibos Phonatik Phone +Phone Number +Phone Scaper PhoneHC Phonebook Phoneman +Phools Phoque +Phor Skin Phosani Phossa +Phostus Photographs Photon Photonic +Photos +Phragasm Phrak +Phrexyian +Phrez PhriarPhace +Phrizo +Phrocks Phsteven +Phug +Phugma Phuke Phuket Phwan +Phxrm Phylum +Phyrlo Phyro Phyronex Physics +Physics Jedi +Phytz Phyzxs +Pianio +Piano Hands +Pianoanddrum +Piantissimo Piasa +Pic of Feet +Picante Piccoloownsu Piccy +Pichi Slayer Pickl3Lover +Pickle Josh +Pickle Vick PickleKez +PickleSaucy +PickledWater Pickles4Me +Pickles69314 Picklzz PicnicBomber +PicoDico Picolo PictureID +Picuu +Picuwu +Pidbull +Pidbull 1 +Pidgeot18 Pidgey +Pidgy Pidiot +Pidrux +Pie +Pie Dish +PieGPT Piecekeeper2 +Pieces Pieck +Pieerio Piemaksa Piemans +PiemieJurrie Pieper +Piepieweenie +Pier Just +Pierced Wolf +Pierenbadje Pierniczek00 +Piestove Piet +Piet 21 PietKrediet Pieter +Pieter Zwart +PieterPep Pieterjan Pietermans Pietn4 +Pietrangelo +Pietrnogiets Piety Piety Prease Pieza +Pieza de oro Piffen Pigeon +Pigeon Soup +Pigeonmight +Piggi Smalls Pigi373 Piglette +Pigman461 +Pigmeu +Pigpikerush Pigpuffer Pigs Pigwardfrog Pihl +Piip MEEGA +Piipar Piirivalvur +PikaChar222 +PikaChin +Pikachewed Pikachos Pikachu +Pikachu87 +Pikachurine Pikachuz Pikkets +Pikkett +Pikku +PikkuSheikki Pikkupbrix Pile +Pile O Poo +Pile o Dirt Pilgrimage Pili +Pilli +Pilliad Pillifnutten PillowBoy PillowCowCow +Pillukarva23 Pilmir Pilodro PilsToTheMax Pilsners +Pilum +Pim Pam +Pimay +Pimfortune Pimp +Pimp Ralpert +PimpWeazel +PimpWhistle Pimpert +Pimpin Thots Pindaro Ping PingFlopped Pingu Pink +Pink Avocado +Pink Bar +Pink Cow34 +Pink Iron +Pink Lube PinkDrinkSip PinkShopRag PinkVoidZ @@ -17650,99 +36962,205 @@ Pinkywinky9b Pinkyx0xo PinndOutGoon PinnkBunny +Pinnn Pinpi Pinquana Pinsamt +PintOfMilf Pintel +Pinterests +Pinu +Piolin +Pioniers Piovendo +Piparikissa PipeQlo +Pipluppp +Pipo-badeend Pippinmary PippleNinchy Pipposan Pippuri +Pir Alain +Pirat Pirate +Pirate Kanye +Pirate Patch Piratey Pirelly Piri +Pirig0 Pirihuora666 Piripaque +Piripippeli +Pirjo +Pirjo69 +Pirk the pk +Pirkka Olut +PirkkaJokeri +Pirkkamies +Piroskinha PirpleSlirpy Pirres +Pirulitim Pisatronas Pisau +Piscarallius Piscis Piscolaz Pistacchio Pistoliftero +Pit Stain +PitGamin1311 +Pita Diver +Pitbulterje Pitby Pitchfork Pithikos +Piticarus Pitiless Pitinator Pitt +Pittaaaaa PitterPattr +Pittsburqh +Pitudin +Pivach +Pix Pixelle +PixarMarsTTV Pixel +PixelMuffin +Pixie Henge Pixieragnar Pixkekoa +Pizdec Pizza +Pizza Addict +Pizza Box +Pizza Flip +Pizza Mang +Pizza Patron PizzaDaHutt +Pizzaman5510 +PizzasIron +Pizzler +Pj The Pj +Pjotr +Pjt77 +Pjumi +Pk Bot 37 +Pk M4ster007 +Pk Wit P Hat +Pk3iru_Osrs Pk3r Range 7 Pk996 PkGoW PkMeIfUgey PkTheKid +Pker nr 1337 +PkerTrysHard PkforFun Pking +Pkingranged9 PkmnTrnrRED +Pkmort Pksorwd +Pkyr Pl0xed Pl3b PlELS +PlFFMAN PlGGY +PlHLAJA +PlMP PlMPPl +PlMl PlPPY +PlRATE KING PlSS +Plaagen Plaasda Plaat Placedoemax +Plaeggs +Plaid10 PlaidMarquis Plain +PlainIronMan +PlainNoGood Plaininsane +Plamt Plan +Plan B-gs Plane4611 Planet001 +PlanetPaul Plank +Plank Egger +Plank Sodplo Plank2G PlankForBank +PlankTan Planken bos +Planker +Planking Brb +Plankrunner8 PlanktSoms +Plant Herbs +Plantdaddyy Plap +Plasma Taco Plasmore +Plastikos +Plastiscines +Plat Kont PlatGX +PlatScrub Platinum2008 PlatinumHerb +PlatinumSage PlatinumSeif Platnuim Platnum112 Platpus3000 +Platyroo Play +Play Lazy +PlaySoloBro PlayToAFK Playbunny +PlayedBe4EOC Player +Player 0ne +Player 4519 +Player Gap +Player Name Player235711 Player35254 +PlayerIsBusy +PlayerSlayaa +Playpro5 +Plays high +Playtest Playthious Pleasantries +Please pot Pleasurehole +Pleb Nick +Plebbocs Plebiside +Pleblio Plebnex +Plebs Plebz Plece Plegh Plexasaurus Plexx Plez +Pliemp Pliep +Pliep Ploep Plips Plisski Plixious @@ -17750,210 +37168,412 @@ Plocc Plogbilen Plogdog Plomono +Ploop Plootbot +Plop deez Plopi +Plopr +Plopzorg Plorky Plorr Plostic Plot786 +PlovasYonder +Plovilas Plow Plowthrough PlsAName Plsmrlizard Pluc321 +Pluckky +Plug In Baby Plugatron Plugged Pluggen Pluhdl +Plukketje PlumTickler +PlumbThatA +PlumpGiraffe Plumper +Plundered Plunkton Plunukki +Plupian Plus +Plus Vite PlusZack +Plush Mole Pluto Plutonium +Plutonium 94 +Plym Plz LD Nat5 +PlzGiveBonds PlzRnGesus +PlzSpoonFeed +Pm Me Imps +Pm me to spy +Pm4 eloboost PmFun Pmy39 Pnak PneFc Pnia +PnutButtrJly PoachedLion +PoakedSussy +PoaneFoane PoarIIneemn +Pocholo Pocket +Pocket Cards PocketBandit PocketSock +Pockipickle Pocy2 +Pod x +Podvodnik +Poeiermolke Poem Poenes +Poephoofd Poepi12 +Poepjong +Poepsiee +Poerto Poet1321 Pofka +Pog Dog +Pog isma +Pog-kek-Lul PogChampagne PogMeister PogTato +PogTato Iron Pogba +PogoPochette Pogsled +Pogue4Lyfe Poikanen Point +Point Guards PointTax +Pointstormy +Poison Ives +Poison x Ivy +PoisonCobra PoisonX7 Poisonblack Poisonous Pokaroo2 +Poke Champ3 +Pokeaotics +PokedexNo258 Pokefreud11 Pokemaster Pokemon +Pokemon Ruby +PokemonScape +Pokemonguy16 +PokerPro +Pokerboy19 Pokergod720 +Pokifeet +PokimanesBF +Pokoloko +Pol o Polaar PolakYT +Polar PolarTrip Polarin Polarisi888 Polarus Polarward PolderLatina +Pole Met +PoleVault Polio23 Polish +Polish Eagle Polite +Politoed Polixo Polkapolkka Polkastarter Poll +Pollar i Pollekeuh +PollenJ0ck Polllie +Polllo420 Pollnivneach +Pollo Dry PolloGrande Pollofrit0 Pollum Pollywog PoloG +Poloskyy Polter +Polyamorous +Polycoffin +Polyesterday +Polygonise +Polyhedra Polynomail Polyphobia +Polywoggle +Pomi Xd Pommy Pompeyo Pomposity Ponas +Pond Scum +Pondres +Ponkito +Ponobi Pont Ponti +Pontifex Pony PonyOwner938 +PonyPorker +Ponzy FTW +Poo Socks PooAtPVM +Poobanans +Pooby Bag +Poodle Poofpooh +Poogen +Poogster Pooh +Pooh Breezy +Pooh Say Poohead92 Poohsea Poojabber364 Pook +PookiDaPooki +PookieB3ar +PookieBearOG +Pool Noodlez +Pool Toucher PoolboyFiji Poon +Poon Lips +PoonHandleMe +PoonTangPie PoonTappa Poonanjo Pooned Poonjuu +Pooohie +Poop +Poop Shidder +PoopyRico Poor +Poor Advice +Poor Clicker +Poor Content +Poor Nooby +Poor You Poortom24 Pooscaper PootLoops Pootzie +Pootzie_xox +Pop In Smoke +Pop N +Pop-up ad +PopTheIron Popcornachi Pope +Pope VI +PopeChamp +PopeDenis Popeet +Popepu +PopeyezGain Popfumes Popkorni +Poplo Popovich +Popoyoi Poppa +Poppa Bev PoppaChoonie Poppajohns +Poppin Awf +Poppscotti Poppy Poppymatt Pops24 +Popstar2 Popular PopyHarlow +PorWrx +Pordiosero +Pore +Pork Jerry +PorkCH0PZ Porkkanakana +Porksters +Porrie Porsche +PorscheDaddy +Port Khazard +PortUnionMan Porta Pro +Portal of I +PorterRobnsn Portrays Portsari Portuguese Portvakt +Porunga +Porygon-Z PoseidonDrip Posemann Posh PoshPenguin Poshker +Poshki +Poshkii +Posino Positivar Positive +Positivehp Possessed +PossiblyAFK PossumPally Possumi Post +Post Malone +Post Max +Post-Absurd PostCodee Postie PostmanPatt PostureCheck Posty2k +Pot Gatherer +Pot Of Greed +Pot Often +Pot Sharer +Pot cms +Pot v X PotScape +PotScape CC +Potapto Potato +Potato D Ben +PotatoButGay PotatoLlorch PotatoRangr Potatoqueenn +Potecito jr +PotentJay Potezny +Potge Pothaaai PotionFayD Potland +Potland o_0 PotoSekwati Potoo PotsAlots Potsi +Pottawatomie +Potter Paypa Potth Pottieface +Pottsi +PottuTatti +Potzy Poucher +Pouches +Poucie +Pounake +PoundSandNub PourMeBleach +Poussemoila Poutz Poverty +Povvo Powacat Power +Power Aid 4 +Power H +Power Outage +Power Surge PowerJoe +Powerade Powerdude153 Powerful +PowerfulBram Powerfull Powerlines Poweron6 +Poww LUIS +Powwil +Powxrs Poxuistas Poyig Pozar +Ppl +Pposkyor +Pql +Pr0 Ph3t +Pr0pvm Pr0way Pr1MaL +Pr3par3 2die Pr3ttyW0man9 +Pr3y Pra1seTheSun Practical +Prada Praecellemus Praedy +Praenthos Praes Praestantia Praetor +Prage699 Prahlad +Prairiez PraiseCorn Praisemyrng +Pramikon Prankzy Prari Praskle +Pratt Mario Praxahr Praxys Pray +Pray Salah +Pray for me +Pray t o God Pray4TheWin +Pray4me PrayForDeath +PrayForYou +PrayToAres PrayarN +Prayer Pro Prayerr +Prayis +Praynr PreMDPepper PreNew PreRuined Precise Precixion +Precondition Predaxx Predicition Preedy @@ -17961,12 +37581,21 @@ Pregnant PregnantSock Prelash Prelet +Prelex +Prellifunky +Prem PrematureNut Premie +PremierZarry +Premium Dude Premz Prep Prepared2 Preposo0 +Prepotting +PresPoon +Presearing +Preserve PresidentMo Presley93 Presley93BTW @@ -17977,42 +37606,90 @@ Prestor Pretendy Preternal Preto +Preto Ownsss +Pretten Pretty +Pretty God +Pretty moist +PrettyGood +Prettyokqt Pretved Pretz Prevengeance +Previn Prey Prey4Pocius +Preying +Priapismi +Pricy Priestopher +Prif Daddy +Prifddinas +Priide +Priimitive Prilliam Prim Prima Primacy Primal +Primal gain Prime PrimeSeries +PrimeToaster Primed +Primetime190 +Primetime829 +Primevil PrimexReborn +Primid Primiitive +Primilivum Primitive +PrimoVG Primordial Primster Prince +Prince Drt +Prince Ferro +Prince Mate +Prince Tuten +PrinceCrypto +PrinceJozef PrinceZuko Pringle287 Pringles Prins +Prins Pi1s Prinses PrintedCash +Prion Priority +Priorrr +Priselac Prisimenu Prismalitic Prison +Prison Joe +Prison M1ke +Prison Soap Pritje PrityBoiSwag PrivateSmorc +Prix Prixma Prncss +Prncss II +PrntScr +Pro Flicks +Pro Per UIM +Pro SKiiLLz +Pro Slacka +Pro Slacker +Pro Tanto +Pro Tato +Pro Zoe +Pro twin33 +Pro-tag ProForm ProFortnite ProLegend @@ -18020,18 +37697,30 @@ ProSKatona ProSups ProTweakius Proba +Probability Problemski +ProbzDrunk Procedures Proclivitas3 +Procoptodon Proctiv Procts ProddyP Prodigy 99 +Prodigy Matt ProdigyTape ProdigyThief +Prodigy_77 Prodoughtype +Product99 Prof +Prof Bruce +Prof Cheese +Prof Ribeiro +Prof Shroom ProfGanon +Prof_Plums +Prof_Snack ProfanityBox Professa ProfessorBot @@ -18039,50 +37728,85 @@ Proficent ProfoundPnda Prog Project +Project Deku +Project Paat +Project Sept ProjectGamma +ProjektUri Proklus Prokopios +Prolapsi +Prolly High +Proly high +Promacta Promepheus +Promise +Promtel Prone Prongs97 +Pronx Proots +Prop Gun Propagate Propas Proper +Proper bald ProperTroll Prophecy +ProphetSnayk Prophylax +Proponi Propulsions Prosit +Prospicktor Pross +Proster Protagg +Protanopia +Protassium +Protease ProtectdLeft Protectlilb9 Protectorate Protege Proteiini +Protixen Protlong Protocell +Proton Drum +Protopteryx PrototypeGOD Protox +Prouser +Provei ProvidenceL +Providential Proviro +Provoke Rage Provokeskill Provoxo +Prowz ProxDemSox Proxeum Proximitus +Proxymine3 +Prozac Manic +Prozac Peter PrrMeowPrr Prro Prrr +Prrr Perry Prryvdoof Pruillip Prune +Prune Slayer PruneHub PrusaSlicer Prutturp Pryn Pryxl +Pryypsas +Pryza91 PsYcHo130 Psalm Psalms116 @@ -18092,219 +37816,435 @@ Pseudo Pseudomonas Pseudonimas PsiTempest +Psichedeliks Psiki Psiklone Psmaster +Psoup Psuedoniem +Psy0tic Psy13m PsyDellic PsyWaps Psybae Psyc Psyc Paladin +Psyc0-I Psyched PsychicL10n PsychicType Psychinis Psycho +Psycho Fungi Psycho11111 PsychoPatty Psychodeathk Psychohexane +Psychokilla PsychoxX Psyco Psycub420 +Psydvekoosi +Psygo PsyhexGOD +Psykoz Psylocin +Psyminds +Psynar +Psyqualogy Psysyk +Psytoro +Psytrnce +Psyyke +Pt 79 Ptalm +PteShank Ptfo +Ptol +Ptopaz Ptyh Pu-94 Pubeless PubicThumb +Pubicon +Public NJP Publics Publuske PuchaLibre Puck Pudding +Pudding Man +Puddingdude +Puddingtons Pudge +Pudge Pudge +PudgeJackie Pudgeegee Pudnik Pudota +Pudota basso +Puerto Varas +Puff Daddy Puffed Pufffml Puffy +Puffy xx +Pufr +Pug +Pug Boots +Pug Champ +PugToots Pugasaur Puggin Puggzy Puglet Pugna Pugsyy +Pugwest Pugy +Puhd Puhd1staja Puhuri +Pui Puin PuinguimGOD Pukeking +Pukeko Puli1111 Pulkjes Pull +PullOutKing PullOutRange Pulli Pulma1 PulpFlctlon Pulza +PumGiver Pumba +Pumba Bot Pumba89 PumpUpTheJam Pumper +Pumper Joe +Pumpflexin Pumpkin PumpkinLatte Pumpui Pumuckl +Punani MD Puncakes Punch +Punch Main +Punched Pundareen Punde Pune +Pune rouch Punegonde +Pung +PunishinBird PunjabSamosa +Punk-06 PunkPang +Punkt Punt +Puntenjagert +Puntje ket +Puny Duck +Pup +Pup in a Cup +Puppadile Puppana Pupper1 +PuppySeal +Puppysaysftw Pur3 +Pur3 Bow99 Pur3death2 PurMain Purate Purcey Purcs Pure +Pure Evil99 +Pure Great1 +Pure Hunk +Pure Paprika +PureBread +PureFilth PureIronEyyy PureOGIronMn +PureOwner +PureWax Pureanger728 +Purebas alt Purebasalt Purebish +Purell Pureloot21 Purely Purelybo0ty6 Purenerd +Purepappa Purepappa66 Purescarybuu +Purey Arcane +PurgatoryBro +Purgy +Purifyin +Purjj Purka11 Purkkatukka +Purkkaukko Purkkius Purko Purnex +Purolator Pl Purp +Purp Nasty +Purp Nips +Purp Please +Purp or Bust +Purp where Purp1eWizard PurpLightPlz +Purpl3 Lean Purple +Purple Flap +Purple Meeep Purple-Broly PurpleDabz +PurpleGoat PurpleHippoo +PurpleMurple PurpleNinjja PurplePlez PurpleTeemo PurpleThorax +PurpleVex PurpleWhaki Purpledile +Purplefox Purplekills Purplemudkip +Purpleowns Purppurainen +Purpsauce PurrPig +Purse seine PursuantACE Pursuedd Purtherapist Pusat +PuscSquirt Puse PuseSlayer Pushgold +Pushovermage +Pushy Bubes Puss +Pustut +Put Me 4th PutMeInCo4ch +Putaria +Puthiegh Puthy +Putkipommi Putrescent Putse Putyte1 PutziVikat Puud Puujalka10 +Puukko Pekka PuuluuP +Puumba Puuteri Puylayer +Puzzle Drops +PuzzleTheCat +Pv Was Here +PvEmerald +PvM Andrew +PvM Beireh +PvM Bhunt3r +PvM Blake PvM Boganeer +PvM Cas +PvM ColdBeer +PvM Crooky +PvM David +PvM Eestlane +PvM Gemeos +PvM Grindz +PvM Hawk +PvM Hero92 +PvM Items +PvM Jack +PvM MeK +PvM Miku H +PvM Muzzy +PvM Nex +PvM Nug +PvM Oliver +PvM Packers +PvM Panda +PvM Rev +PvM Rin +PvM Spectral +PvM Tom +PvM Wiz +PvM guy +PvM zoom +PvMAlone PvMCerlow PvMKoala PvMNightmare PvMNotorious PvMProfessor PvM_Nugg +PvMalexDR PvManchester PvMs +PvP +PvP Master PvPRoTiGy PvPete +PvPs Pvkk +Pvm 4 Pets +Pvm Aero +Pvm Demigod +Pvm Garley Pvm M0lz2 +Pvm MageBoss +Pvm Runeboyz +Pvm Tigers +PvmBrad PvmQ PvmRNGesus Pvmpets Pvoet PvtStevens Pvul +Pw4 PwDhorizons Pwca Pwdz Pweet Pwew +PwincessK +Pwn Dat Noob PwnTommy Pwnage Pwnbaa Pwnd +Pwnna +Pwnnzz +Pwno +PwnrPizzaman Pwnslayibex Pwpw +Pwxn Px_7UX8Cy8 +Pxcs +Pxie Pxtrick +Pxxch +Pxzls +Pyet Pyfa Pygmysteaks +Pyia +Pyjamas99 Pyki Pyloric Pylseboden +Pyocola +Pyra +Pyrate Aeon +Pyre Lord3 +Pyre Mouse Pyretic Pyrl Pyro238 +PyroEagle13 +PyroF3AR Pyro_OO1 Pyrocore Pyrotemplar PyrrosDimas Pyssu Pyst +Python +Pythonx135 Pyux Pyykki Pyyli Pyzdalupi +PzK +Pzju PzzaPredator +Q 1 +Q K M Nophis +Q Proserpina +Q S L +Q cs +Q l ii Ma X +Q of Spade +Q uincy +Q-Dance Jr +Q-Qs Q1NH4N Q33N +Q53 +Q60 +Q7L +Q8 I +Q8vv QAWSED +QGM QIKNQFRDNUQF +QKen +QPR QPness +QQ3 +QQQ Gang QQQQQQRRRRRR QQuaLLeH +QRcoding +QT Bri +QT0 QTRDS +QTY1 QTZedd QTom +QU0TE ME +QU42TION QWIWRDIGIDFG Qadir Qaem +Qaidos Qajvha +Qapz Qash +Qc power1 Qc-Elfmage Qeassaris +QeeQ Qego +Qeko +Qeln Qemi +Qeni +Qenobii +Qi Kua Mai +Qi Ling QiangxD +Qilat +Qiok QlKNQFRDNUQF +Qlhp xD Qlioux Qmain QnBumbleBee @@ -18312,38 +38252,79 @@ Qnon Qoil Qoki Qombat +Qosmio +QpSc +Qpaki +QpzQ +Qragon +Qrax +Qridan Qrischin +Qrollop Qrwewa Qryptic Qtey +Qtreb +Qu3stm4st3r Quacamole +Quack Attk +Quack Boom QuackForMe +Quacka +Quacker +QuadJake +Quadder 4444 +Quadralobsta Quadrifoglio Quadrioo2 Quaerd +QuaffPotion Quaffle9 Quahzai +Quakbou +Quakenet +Quakoss Qualitative Qualities +Quality Kek +Quality Name QualitySleep Quang Quantities +Quantization Quantuh Quantum QuantumTurtl Quarentitty +Quarks +QuarterToBen +Quarterback Quarters +Quartia Quav Quawka +Quazi +Qucks Qucu QueBolaAsere +QueefInMyEar QueefMaestro +QueefWiggum QueefedOnYou Queeffing Queen +Queen De +Queen Juggle +Queen Keegs +Queen of CoX +Queen0fScots +QueenBadJuju QueenJada QueenOfCorn +Queenmystque +Queenn Elsa Queer +Queer Peter Queerzzly Queijo9 Quelana @@ -18351,131 +38332,329 @@ Quenched Quero Quessswho Quest +Quest Dodger +Quest Giver +Quest Lckd +Quest Noobi +Quest Person +Quest Plug Questikels +QuestsAreBad Quety +Queue Pea +Queueie Quew Quey Quezzimoto +Quf +Qui GonJinn Quica +Quick200 QuickClicks +QuickELMN8 +QuickNDeadly QuickShot +QuickShot x Quicken +Quickman1000 +Quickshot343 Quiddich Quiet +Quiet Place +Quiet Please +Quiet Toot QuietStorm44 +Quiettravlr Quikstache00 +Quilicura Quillninety3 Quimbo +Quinker Quinncidence Quinnyb0y Quintendo Quirkless24 +QuirkyBeaver QuirkyPurple +Quit 4 iron QuitForIron QuitForRS3 Quite +Quite Shy Quitegoddish Quitoris +Quitting Alc Quiz +Quizav Quizzy Dee +QukinoTe Quonloo Quorhum +Qureshi Quria Qurix Quti Qutie +Quukske Quvma Quweix Quyron +Quz Quzzini Qverkuz +Qwagmire Qwaltz +Qwd Qwezz +Qwibz Qwinny Qwinoa Qwozii Qxevym1 +Qzbxd +Qzst +R 0 E +R 0 w d y +R A L L S +R A V I +R A Z T A +R E +R H Y T H M +R I J K A R +R I K +R I P B R O +R L +R N G Pwnz5 +R N Geo +R O B B IE +R O E L +R O O N +R O X +R P N +R S J +R S Life +R S M +R U A Terd +R U MAD BRU +R Y A N +R Y D +R You Jelly +R a uL +R a z u z +R ack +R amon +R eece +R em +R hin o +R i a d +R ift +R l C H +R mr +R o r o no a +R ob +R obert +R oger +R osss +R uiN +R ya n +R yun +R-66Y R00M +R00P R00SE +R00T R0AD R0B0C0P R0BBO +R0FL AT L1FE R0GAN R0KKIN R0LX R0MICH +R0NES R0NNIEB0Y R0OZ R0R0R +R0Y R0YAL R0ad R0bain R0bbby +R0binho R0n13L +R0seofthorns R0yksopp +R14H R1CO +R1chs R1ghtupth3r3 +R1ku R1ng +R2TB +R32 N Z R33c0NN +R34 R3Dtjee R3d3mtion +R3dlegend R3vq +R4 n g 3 r z R4LLY +R4g4n4 R4ndomUs3r +R4ndyM0n +R4ndy_lahey R4ng3 +R4ng3 Nubie +R4ng3r 00 +R4nge +R4nge 2 Lpk +R4re Pepe +R4v2n +R6boi R8nny +RA NG ED RAB9 RACELIS24 +RAD x GLiDeR +RADATOUILLE RADlATAstory +RAFA LOKO +RAG YOUR A55 RAKETTAA +RAPPUHN +RATMON3Y RAUTA ARTO +RAlN +RAlSED RBNY RBeardWBrow +RC Blows RC350 +RC93 RCFreak +RCW +RCY +RD Alten RDHG RDJ94 +RDT King +RDW_Dark +RE2PECT RE4LG4LIFE +REALLY RITCH REBOOTING REC0N +RECEPTED +RED DEM0N +REDBUHLL REDD0GJR REDLlNE +REDRACECAR99 REEEject +REEEsuns REINCARN4TE REKNAW REKTmlg99op REMAlN +REMIIIX +REN0 REZlN +RElNHARDT +RF Bushee +RF Genesis +RFDesigner +RGB Titties RGGregar RGet RHCP-Solo RHK Ezze +RI Sleepy +RIP Base +RIP Meme Man +RIP Mitch +RIP Pork Pie +RIP life +RIPAUGUST +RIPAccount94 RIPT4H +RIPgirthgirl +RIllipieru RIpuim +RJCI +RJE RJL129 RKBM2 +RKN RKOd +RKOd My Mum +RKTA +RKZY +RL Adam +RL Wolf RLBurnside RMAC-97 +RMF Dead +RMG solo +RMax +RNG Alche +RNG GOD +RNG Kevin +RNG MAD +RNG Msg Me +RNG Replace +RNG Tomas +RNG dez nuts +RNG9518 RNGBandit RNGVRNG +RNGiesi +RNGrim +RNGsetMeFree +RNJohn +RNJoseph ROADTO100B +ROBAlN ROBBOsickdog ROCCAT ROCKYY +RODRlCK ROF0LFOR ROFOLFOR ROHTEENMUTSI ROKO +ROLL TlDE ROLLinPEACE +ROMBU +RONNIE COLE +RONZE ROR0 ROSTA +ROT LOST 6K ROVANIEMl +RR Fourshore +RR55 +RRAMPIDD RREKKLES +RRX YY RRX RRayhan +RRevelation RRickkert RRobert +RRocket02 +RS Bread +RS Cinema +RS Jesus +RS Myrthe +RS Nico +RS SLAG +RS UFC NRL +RS ape +RS2 Legend +RS3 Refugee RS3izBetter +RS6 Quattro +RSB Fox RSBadLifeBad RSDonny RSGO @@ -18483,231 +38662,462 @@ RSLtSgtZen RSMAXD RSPSisBETTER RSPup +RSQT +RS_Tytin RSfork +RSmake RStrength99 +RSuomivihu +RTGoldleader +RTK86 RTLadNumber4 +RU B Y +RU Petrified +RUBBERI +RUUNIKUNN +RU_Engineer RUlS +RWB Codeine RWSDOUG +RX S +RX7 FC3S +RXen0 +RY N0 +RY P RYAN RYN16 RZAlex +R_D TRAJANO R_andy13 +Ra +Ra fi Ra1d RaMR0D +RaRaJuana +RaSToG RaaWa Raaagnaar Raab Raaban +Raahe Raahh Raakanipsu +Raamsdonkje Raanduin Raassig +RabarberBarb +Rabbagust Rabbie +Rabbit MD RabbitFlats +Rabbitdude RabbitsDong +RabidDolphin Rabidherring Rabiosa +Rabrt +Rabs xo RacccAttack Raccoon +Raccoon King Raccooncow +Raccoonus Race Rachael +Rachey B +Racholini +Rachscape +Racteal +Rad Renegade RadFeenix Radacia +Radaenne Radar Radeo Radia7ion Radiance +Radiant Lux +RadiantSkye Radiator Radini Radio +Radio DJ Dan +Radio Love Radiohead66 Radiologics +Radish55 Radja333 RadoslavvBG Radrieldor Radsurlak Radsy Radtastic +Radusa-Two Raeghal +Raelir Raen +Raf0da Rafaael +Raffealy +Rafff +Raffineret +Rafi Tafy +Rafiniya +Rafn Rafnar0G Raft15 +Rafy +Rag +Rag Demon +Rag Doll +Rag Gdz +Rag List RagToRiches Ragani Rage +Rage Fuel +Rage233 RageCold +RageCombo RagedIronMan Ragefire1 +Ragegold1163 +Ragez Fury Ragga +Ragga Muffyn Raggedy Jeeb Raggers +Raggnag +Raggy Reapzz +RaginBatts RagingK9Fury RagingReddit RagingTroll +Ragingg Ragnar +RagnarOsborn Ragnariukas Ragnarok96 Ragnell56 Ragni RagsIIRichez RagucciRafa +Ragurain +Ragy rag Rahamasin Rahamies +Raharu RahbHurt Rahdyxc +Rahedo +Rahimo +Rahis Rahjer +Rahy King +Rai Rai_3 +Raibu +Raichue Raicun Raid +Raid Lewis +Raid My Body Raideris Raiderrediar +RaidriarTGK Raien Raihan +Raihou Raii +Raiicrow Raikesy Railee Raimar1 Raimiss Rain +Rain Days +Rain Please +Rain ee +Rainbird +Rainbow RainbowBeast Raine Rainer Rainforest Raining Rainingbroz +Rainingmeltz Rainman446 +Rainnos Rainold +Rainshower Raintown17 Raisedbycows Raiskausrapu Raisson +Raisson X Raistlin RaistlinFasa +Raisya Raivan90 Raizerr Rajat76 Raje +Rajgo +Rajs +Rajvir Rakaah RakadB3 +Rakblood +Rake +Rake ur weed Rakettikala RakiRaki +Rakiata +RakingPurple +Rakkir Rakoins +Rakru1 Rakuko Rakun Rakan Rakupenda +Ralalallei +Ralgurr Ralle1208 Rallis RalorLeetor +Ralos Rise Ralp +RalphLauren Ralphed Ralphie3 +Ralphy Jnr Raltsz RalvekZul RamYe +Ramae +Ramallah Ramathorn +Rambling Rambo +Rambo Prods +Rambo The 3 +Rambo The 4 +RamboBrad RamboDaddy +RamboKiddo +RamboOmega +RamboSambo +Rame +Rame s Ramen +Rameses B Rami +Rami Tsunami Ramleh Rammdude +Rammmsteinn RamonZera Ramonix Rampa +RampageOnly Rampauttaja +Rampenisse Ramrod Ramsas +Ramsay RamsayGrejoy +Ramxious Ramzis Ramztad +Ran-D RanShakHazar +Rana pipiens Ranamen7 Ranarr +Ranarr Bowl +Ranarr Czar RanarrScape RanarrSmoke +Ranarrjuice Ranarrseole Randalf Randalfen Randalicious +RandallOG +Randdall Randeaux Randecker Randinator42 +RandlesAlt +Random Day +Random763 +RandomGuy771 RandomLemon1 Randomguy38 Randomized +Randomkul Randomojojo +Randsoms +Randy Rawdog Randy Rolex RandyBanger Randyke +Randys +Ranestumies Rang +Rang3d Xp +RangPang Rangahhh +Rangatan44 Range +Range 4 mage +Range AR +Range Kiing2 Range4Free RangeGawd RangePs Rangeddddddd Rangedly Ranger +Ranger Fain +Ranger Hood +Ranger Uhle Ranger82592 RangerBoots +RangerFain Rangerofgold +Rangerrr Rangish +RangoII RanjaForLife Rank +Rank 1 +Rank 1 Gamer +Rank 1 Korea +Rank 1 Norge +Rank 1337 Rank1Espada Rank1NA +Rank350 Rank62 RankOneTurk +Ranox Ranty +Ranul Oracle +Ranusian +Ranzo +Raoul +Rap50Cents Rapasuu +Rapid RapidCycling +RapidPancake +Rapidd Rapiers Rapolas Rapolu +Rapt0ram +Rapterzz99 Rapthor Raptor +Raptor Jesuz RaptorLuck Raptorcaw +Raptorjk +Raptorman Raptorsin6ix Raptz Rapu +Raquelo Rare +Rare Arugula +Rare Chance +Rare Doggo +Rare Hat +Rare Panda +Rare Pets +Rare Vibes +Rareinpepe Raresocks Rarity +Rarity Belle +Rarma Rasa Rascus +Raseni +Rasenkage Rashford +Raskasta Raspatil Rasput1n2k13 RaspyLemon +Rassaasolo +Rasta Panda Rastaclat +Rastafarlion Rastamain Rastaman +Rat Digward +Rat Flicker +Rat Has Dice +Rat Hunter23 +Rat L Traps +Rat Lettuce +Rat Sensei +RatKing365 +RatWithAGat +Rata +Ratchet48 Ratcliffe +Ratdrin +Ratenda RathianSP Rathmai +Ratikka07 +Ratlifenerd Ratlordmax Ratm +Ratpno Ratrace12345 Ratrero +Ratsy J RattleSsnake +Rattled Rattlerskill Rattlesnake +Rauhanrekka Rauokse Raur +Raurshank +Rauski696 +Rauss Rauta +Rauta Juoppo +Rauta Sorsa +Rauta Tuomo +Rauta Urho +RautaGoblin +RautaLeksa +RautaPertti +RautaPizza +Rauta_Kessu Rautafantic Rautakuma Rautis +Rauzee Ravac +Ravangerous Ravanth +Rave Pants +RaveBoy21k Ravedeath Ravemaste476 Raven +Raven Frost Ravency Ravensword +Raventodt Ravers Ravesyy Raving @@ -18717,119 +39127,267 @@ Ravlar Ravs RawPhazon RawRyan +RawToast_13 +Rawbean +Rawduggie Rawest +Rawke Rawr RawrItsKirby Rawrr Rawsome Rawssss Rawst +Rawwr Austin Raxen Light +Raxorn +Ray Btw +Ray Kurzweil +Ray Rwars +Ray Sensei +Ray Squared +RayCon +RayMarshall Rayfort +RayiiRios Rayjin_Storm +Raykin Rayleighs Rayleight RaymanXo +Raymo Raymone Rayne +Rayne Drop +Raynel Raynelie Rayner91 +Rayo McFly RayofLight2 +Raypac +Rayrunner +Rays Max +Rayye +Raz Wolf +Razaia +Raze +RazenOh Razer +Razer Elite Razeren +Razguld Razie +Razih RazleBadazle Razor +Razor Beast Razor654991 Razorblat Razoriginal +Razorshark +Razrback Razz1eDazz1e +Razzle Razzzoor +Rb Salvation Rb2790 +Rc +Rc Dark Rang +Rc_Power +Rcardio Rcer +Rckr Rddrz +Rds 44 +Rds Nerd +Rdushi ReDrOc +ReFueld RePeTiiTioN +ReRemakeAndy +Re_Rauzo ReachAround Reachinator +Reactate +Reaction Tec Reactionary +Reactionss +Reactor15 +Read Art +Ready 123 Ready4pwnage ReadyToReap Reah Reaks Real +Real Cute +Real Earth +Real Friends +Real Jesiah +Real Kev +Real Me +Real Reasonn +Real Skyline +Real Umbreon +Real Unlucky +RealAndBased +RealBoobs +RealBruceU +RealDrSeuss RealJonner RealKing11 +RealKingBee +RealLifeBot +RealLyre RealMemeVPJr +RealPeelBoat RealRicFlair RealScythe RealShyGuy +RealSpeed RealStoney Realcorkpig Realdent Realflamesss Realismi Realissm +Realist Knut +Realistg +Reality RealitysGod Really +Really Spicy +ReallyToxic Realpk2004 +Realtank +Realtor R1 Reap Reapa Reaper Reaper0321 ReaperLucid Reaperkiller +Reaping Inc +Rearrange +Reaver Tru5t +Reavus +Rebaulten Rebel +Rebel Serj +Rebelatto9 Rebelgian Rebelican +Rebellgutt Rebelqt +Rebir7h Rebirth +RebirthFlame +Rebis +ReboKhaihang +Rebooting Reborn +RebornMuscle +RebornNips +Reborninc +Rebounder234 Rebuild Rebuild4free RebuildLewi RebuildMitch Rebuildep Rebuilders +Recable RecentKill +Recess Recharge +Recited +Recker1o1 Reckless +Reckless Ell +Reckless Fyb +Reckless Lad Reclaimar Reclaiming +Recline +Reclined +Recnamalad +Reco Fam +Recolddone Reconjack Recore Recover +RectalRoni RectalRumble Rectophobia Recuder +RecyclePls Recyr +Red Asia +Red Cavalier +Red Courier +Red Duke +Red Hick +Red Hippo +Red Hood +Red Hot Go +Red Kool-Aid +Red Nine +Red Osrs +Red Pepper65 +Red Rays +Red Rockin +Red Simon +Red Staal +Red Style +Red The Pom +Red Wings +Red XIII FF7 +Red hat +Red partyhat Red3 +Red6 RedCavalier RedDwarf RedGraceful +RedMare +RedRambler RedRatedGame +RedRathalos RedRegent RedRusker RedTwisted RedWarlock31 +RedWol +Red__Mage9 Redael +Redarekun +Redbackpker Redben45 +RedberryLean Redbull +Redbull Od Reddo Reddragon884 Redflame +Redgit Redikarp +Redisleft Redius RedkaWodbull Redland +Redlonghorn RedneckYoshi +Rednecks Rednex +Redninja02 Rednipplee Redo +Redo Undo Redouan94 Redrevolve11 Reds Redshapes +Redshok Redshoker Redsk1ns Redskin @@ -18838,12 +39396,16 @@ Reduced Reductive Redus Redux +Redux Lux Redz Redza14 +Ree Mastered Reeb Reececup Reecesoa +Reecie ReedBadass +Reee Reeebow ReeeeZ Reeeps @@ -18854,7 +39416,10 @@ ReefyReefer Reel_Arphios Reels Reemov3d +Reer Reeyu +Reeze Tech +Reflection44 Refleksfrode Refleksi Refluxerino @@ -18863,168 +39428,346 @@ Reformer Refried Regal Regan +Regelios Regement +Regent Pve +ReggieWeggie +Reggin Cx Regie +Regiis +Regio Regular +Regular Iron RegularJerry RegularPlank +RegulusAurum +Rehbein RehlapzZ Rehoboam +Rehst +Rehzzy Rei-chan Reibnitz Reichart Reidar +Reids +Reidtheweed Reign ReignInBlood ReignOfThor Reigns +ReikenGIMP Reimie0x Reimo ReimuHakurei +ReinLassen ReinMoose Reince +Reinkmyster Reipas Reisnom Reisy +Reita Reizzaz +Reject q p +Rejected Alt +Rejected Son +Rejected btw Rejects +Rejet-01 Rejey8 Rejuvenating +RekaScape +Rekans Rekenz Rekkaboi Rekkerta Rekkt +Reklats +Rekna +Rekt +RektHavok Rekunleashed +Relaaax +Relapse Relapses Relative Relatived +Relax to Alt +Relent1ess +Relevancys Relianah +Reliefed ReligionBad Reliinqish Relik Relinquishh +Relit RelivinYouth Relizent +Relizent2 +Relizents Rellnquish Relloktion +Relmu Reload ReloadFaster Reloox Relrekis +Reluctants +Rem Dogg +Rembs Remcodingho Remedial Remiejj-BV +Remiel Remillia +Reminded Reminiscon Remitin Remix +Remixed +Remmos +Remmyy +Remn +Remo Remorsed Remspoor +Remtar74 +Remvrkable +Remylz +Remytouille +Ren to RenLady +RenZelus Ren_Otori Renacan +Renall Renarin Renas Renato Renauddd +ReneeIsMaxed Renegor Renesau Renewed +Rengar +Rengeki Renger +RengokuRS +RengokuSmile +Renixion Rennuts Rennz Renovato +Rensafari Rent +Rentb0y +Renzo Bamf +Repathor Repeats +Rephia Replayroyke +Replenished Replikantti Replo +Reply To Me +Report Biden Reported +Reporting U Reppin519 RepresentRS +Reprexain Reps4Jesuz Reptile +Reptile God Reptiliano Reptillian +Republic55 +RepublicofRS Reputism Reqtile Requaahv Requilog Requin RequireBone +Reredrum +Rero +Resallude ResenBallZ +Resentfully Reseriant Reserv3D +Reshop Resident +ResignWonki Resilient +Resistzz Resizable +Resk +Resoluutio Respaze +Respeat +RespecTheMax +Respect Me +RespectMyDab Respek Respire +Responders +Respy +Respyy ResrvdFinest +Ressara RestIess RestInPce +RestTooLaid Restinp3ace +Restless99 RestoredIron Restrial +Restrio +Resultss Resultzs Resupplying Retendous Rethie +Retired Dead +RetiredMaboe +RetiredStic +Retr0virus11 Retro +Retro PvM +RetroDeviant +RetroRaz +Retrohiili +Retrovision Rettent +RetuKettu Retupelle ReturnToOne Reub +Reubon +Reuborn +Reudo +Rev Hayter +RevDragon RevZamorak Revamp +Revamp cF Revanche +Revellius Revelwood +Revenant MKX +Revenant Rag RevenantBoy RevengerII Revent ReveredB3ard Reverenciar Reverenz +ReverieDC +ReversEffort +Reversedd Revi21 +Revilia Revofev Revoke Revolted Revolving Revs +RevsRebuild Revus +Revvanth Revx Revzvy +Revzy +Rewbs +Rewinds Iron Rewnlite Rewns +Rewo +Rewriting +RexCox RexM +RexMouser Rexicur +Rexkat Rexun +RexxNotReal +Rexxasaurus +Rexxer69 +Reyes407 Reyko ReynoldsWrap +Reystov +Reyswaldo +Rez X +Rezi +Rezident Rezka +Rezki +Reznx +Rezy +Rezz Main Rezz79 +Rezzn +Rfsu +Rgimenez007 +Rgk +Rgnfrg Rhaegalion Rhaegar Rhaegard +Rhaegor +Rhagaea +Rhastae +Rhcprule6 +Rheal Rheece Rhette +Rhezmyn +Rhianne +Rhien +Rhiley +Rhino +Rhino Art +Rhino Prime RhinoNuts +Rhit Rhiyia +Rhk +Rho Ur Boat Rhoads +Rhocky Rhodesia Rhogue Rhondda +Rhorrn +RhuBarb3 +Rhubarbino Rhuina +Rhyio Rhyl +Rhyme Rhyming +Rhyninn Rhynoob +Rhys Irl +Rhys25 RhysieBoy Rhysos Rhythm +Rhythm Games Rhythms +Rhyw Peth +Ri v en +RiJect RiKoCheP +Riaever +Riamo +Rias Ribb +Ribeye1611 Ribinha Ribitz Riboku @@ -19038,30 +39781,63 @@ Riccario Rice RiceAndTacos RiceWrangler +Ricefishie +Ricepicker89 Rich +Rich 1 Hita +Rich Noob +Rich Snoe +Rich13 RichAround RichGuy X RichHarambe9 +RichMansDrip +Richaard Richard +Richard Baer +Richard Moss +Richard12391 Richards2705 +Richart 123 Richguy3213 Richie Richterr +Richxrd Richy +Richy Rich Rick +Rick scape0 RickAndVorki +RickDeckard RickEscobar RickRab +Rick_NLD +Rickard +Rickeh 1 +RicketyReck Rickhs +Rickky Bobbi +Ricklet +Ricklewinks +Rickness666 +RicknessAlt Rickolas +Rickos Ricksking +Rickstaverse Ricky +Ricky Bob E RickydeRoach +Rickyj13 +Rickyrevine +RicoMangos Ricoo Ricotayqueso Riddim RidePine +Ridemyhomies Rider +Rider Galara RiderOfRohan Rider_99 RidgeRacerR4 @@ -19070,166 +39846,309 @@ Ridley Ridley1990 Ridored Rie1yReid +Riektanminol Ries2 +RiesBatsbak +Rif +Rif T +Rifampicin Rifen +Rift Archer RiftOversoul +Rig Pig Riga +Rigelius +Riggas Rigged1 Riggerlyworm +Righ Right RightKnight5 Rightthisway +Rigid Tony Riglr +Rigondead Rigondeaux Rigourlas Rigr Rigtop25 Rihmakallo5 +Rihsky Riickkert Riiggs Riii +Riiico Suave +RiimuRatigan Riippptttt Riisi Riitasointu Rijst +Rik M +RikCastle RikSavage +Rikador Rikalero +Rikeez +Rikka-kun +Rikka-san +Rikky Flames +Riksaah btw +Rikten X +Riku887 RikuLehDeku RikuRNG RikvWesting Rilah1212 +Riled Up RilesWright +Riles_Nation +Riley Mort +Riley1098 RileyReidx RileyVoelkel +Riltor Storm Rimbton Rimorix +Rimppa97 +Rimuru BTW +Rinby Rindos Ringboi5 +Rinhx +Rini Keeper +Rinky +Rinoa Rinrus Rinsumageast +Rio-Dono Riolu +Riona Riot +Riot Breaker +Riot Starter Riotdeath +Riotz v4 +Riou Riouha +Rip David +Rip25kChins RipBigDoinks +RipFeKeenan RipLo RipMagikarp RipRoidie RipSnorter46 +RipTheBilly Ripd RipePineappl Ripper Ripperhino RippleBear +Rippn Ripsin Ripstart Ripulieinari Ripulirulla Riri488 RiseOfTerror +Risencambrie +Rishhh Rishloo +Rising serum RisingHonour Risingodslay Risk Risker RiskinPixelz +Riskule +Risky Pete +Risky Ryan +Riskz92 Rislearn Rismani +Risotto Risperdal +Risque Moose Risqy +Ritchi026 Ritle Ritopikachu Ritrole1 +Ritthback Rittz Riubuli RivalIron +RivalTitan Rivalguy25 Rive RivenGasm +River Kelda +River OSRS RiverOfIron RiverOut +RiverToSea +Riveriea RiverzRaging Rivy Riwer Rixhy +Riyazzz RiyuK RizeNSkrine +Rizi Bizi +Rizla King Rizos +RizzardWizrd Rizzhole +Rizzzoo Rizzzyisback Rj8532 Rjtyyi +Rkaksi RlCE +RlCEHEAD RlFK RlGBY +RlP Harambe RlPMYMANX +Rlly G Rmus1 +Rmve RnBieber +RnGator +RnGisFocked +Rndl +Rng Depleted +Rng Maestro +Rng Rami Rng4Display RngIshit Rngclown Rnjeesus +Rnkji Ro The Boat +Ro s Ro2no RoBoRhino +RoBoat RoNNalDis RoSki +RoT Nick +RoT is GAY Roach Road +Road Run +Road sign 73 +Road to kek RoadBoat RoadSpartan RoadToALLPet Roadbiker15 +RoadetoMax +Roadways Roadz Roam +Roaming Sky Roanen97 Roastedsteak +Rob Aero +Rob Hot Dog +Rob Iron +Rob Pooner +Rob Zombie +Rob2G +Rob94401 RobDirkson RobThePole +RobWilliams RobWorker Robb +Robb uwu Robbbana +Robbbbb Robbiboi +Robbie EN +RobbieJ547 Robbin +RobbinDaHood Robbo Robby +RobbyMatrix +RobbyRott3n Robeartoe Robejose Roben +Roben Jr Robert +Robert Pires +Robert Stein +Robert T +Robert1f Roberto700 +Robidoux Robigo Robin +Robin Van H +Robin564 Robinhoodnow Robjee +Robjon7 +Roblit Robln +Robln l-l00d +Robodinho Robodyx Robok0p +Robokiller86 Robolisten Robologist Robot Robpar6 RobsonV +Robtoe123 Robust Robyn550 +Roc3 RocheLimit Rochette Rock +Rock Knight +Rock Nin +Rock Rage +Rock The Red +Rock Wizard3 +Rockabbages Rockadelic Rockafellah1 RocketRock88 Rockfists1 Rockford +RockfordT Rockin +Rockin Ness Rockland Rocklore +Rockmaker Rockrets +Rocktail +Rockwell Rocky +Rocky 1535 +RockyYourMom +Rockydig Rocokoko Roczor +Rod Goesinya +Rod Man +Rod Monan +Rod My O +Rod i +Rodefe Rodeva Rodimus55 +Rodje Rodney +Rodney Farva Rodnirt Rodnizzle Rodrick @@ -19238,77 +40157,133 @@ Roe2 RoeGut Roebie1 Roei +Roekoeloos Roel Roerbakei +Roexzy Roff +RoffXD +Roffie Roffy Rofie RoflOs +Roflaye Roflmao +Roflmaomg Roflologist Roga Rogerthatxd +Rogier504 Rogiertjuuuh RogretheOger Rogue Rogue nr2 +RogueSoul03 Roguestoney +Roguor +Rohafin Rohekonn +Rohman Rohmu +Rohr Roice Roid Roidsy +Roihuvuori +Roithamer +Roixie +Rojas +Rokec993 Rokki Rokushoo Rolann +Rolav +Rold Rolde Roldeh Roldie Rolex +RollOurOwnJs Rolla +RollandSmash +Rolleston Rollin +Rollin Clean Rolling +Rolling Kush Rolling2Hard Rollingo +Rolls Rollsie Rolluik Rolly83 +Rolpharoni Rolson +Rom3 Roma Romad +Romare Romarigo +Romboy619 Rome +Romein Romen +Romen Ranges +Romeo for u +Romeos GIM RomeowL Romic Romka Romo RompLord Rompmaninov +Romway +Ron Swansong RonBurgundy +RonCumtastic Ronald +RonaldReagan Ronbiara Ronch Ronco6 +RondVierkant Rondey +RoneRackal Ronescape +Ronggo Rongor Rongrongie +Roni Hagert RoniKysh +Ronn Coleman Ronnicle Ronnie +Ronnie Fe +Ronnie Ponny Ronnie518 RonnieKray +Ronniebob Ronny Ronokroo +Ronpoo Ronti Rony Ronz Roof +Rooftop Laps +RooieRotzak +Roolon +Roomhoorntje Roommaster1 +Roon2h +RooneyDUNX +Roonscape Roosa Roosevelt19 +Roosevelt69 Roosevelt79 +Roost Coffee +Root Exoi Rootman34 Roover Rooxy @@ -19316,77 +40291,146 @@ Roozom Rope RopeDart88 Ropemaker +Ropew +RoqeSVK +RorannoaZ +Rorek RorekMalc Rorr Rorvis +Rory Gall +Rory Stone RoryBurnout +RoryJb Rorys +Rosalktha +Rosco Jenkn Rose +Rose Fritz +Rose of May +Rose tiara RoseGold_A +RoseOnCasket +Roseanne +Rosemarrie Rosemary +Roses R Red +RosetaStoned Roshidragon +Roshyz RosieBtw +Rosieflower +Rosin0nly RosinHead710 RosinScape +Roskamaster Ross +RossOSRS Rossaboy Rossed Rossssi Rossys +Rosters +RostiKz Rosv0 Rot3x +RotJofaJofa Rotagilla +Rotated Rotation +Rotelli Rothen RothesLatrin +Rothgor RotiPrata Rotiforms Rotom Rotta Rottapoju Rotten +Rotten Vale +Rotten Wang +RottenEyeMoe +RottenGurl Rottencotten +Rottenzotten +Rotterdam +Rotzschrank Rouge RougeDev RougeManiac RougeThief02 Rough +Rough Games RoughINSERT Rounded +Rounded Xp Rounder +Rounding Rousey Rousseau88 Route Rova Rove +Rovicus +Rovka +Row Sripple +Rowdy Tobias +Rowe5000 Roweeee Rowg +Rowinovich92 Rowls Rowoep RoxanX Roxasroxs564 Roxer +Roxie Valor +Roxxe Roy385 RoyLay RoyZay Roya2Face Royal +Royal 69 +Royal Chief +Royal Death +Royal Rain +Royal Violet +Royal Wax RoyalD3sire RoyalMess RoyalPurps RoyalRolf +RoyalScumbag RoyalShaco +Royal_Shock +Royal_inc Royan +Royboy16 Roye +Royo Royollie Roysrols Roytang5 RoyyyAfca +Rozensho +RozirPanda Rozkol Rozlucka Roztomily Rozzaa RricketyREKT +Rro +Rs Bartender +Rs But Afk +Rs D +Rs God +Rs Jamal +Rs Kajcsa +Rs Olm +Rs Pikachu +Rs Wiki RsBryce RsGoku RsOverGirls @@ -19396,59 +40440,116 @@ Rs_ReeCe Rsanaded Rsebb Rset +Rsh Katje Rsh10 +Rsky B +Rsn Kmt +Rsn_Adam Rsn_Dillon Rtlo18918B +Rtslash +Rty +Ru Ru +Ru2uo +Ru6 RuMoRRs +RuRu-nyan RuRu09 +Ruan Rubber +Rubber Alt +Rubber Apple +Rubber Luffy RubberApple Rubbery +Rubbery Ra Rubee RubenD +Rubenich RubiconGuy +RubikMouse +Rubinx81 Rubish Rubrek RubsSandwich Rubss Ruby +Ruby Opal +Ruby Runes Ruby5001 RubyBlue RubyBoltSpec RubyEvelyn RubyLvledUp +Rubystealer +Ruck +Rucked Faw Ruckus Ructions Rudadoodadoo Rude +RudeBoiElj Rudekid1035 Rudetopia +Rudi Andre +Rudii Rudin +Rudin Alt Rudolph Rudy RudyGiuliani Rueben +Ruel Rufie +Rufles Rufu +Rufus Shaw +Rufus xD +Rug Klachten Ruge Rugg0064 +Rugpijn Rugrat Ruhl +Ruhpetitive Ruhtrik +Rui HIMimura +Rui Sand RuiMariz Ruimte RuimteMan Ruinationnn +Ruined +Ruined Kap +Ruint +Ruizoeki Ruk1a +Rukavi Ruker +Rukias Feet Rukusama +Ruky +Rule Elite +Rule34 Grogu Rulesy Rulesyy Rullmane +Rum Lad +RumJeDobry +Rumble519 RumbleYT +Rump +Rump Kicker +Rumpetask +Rumpkondens Rumpleminze Rumpstag +Run Alt +Run Down Mid +Run n Alch Run1t3 +Run1t3 Cape +Run2paradise RunCMP RunFreek RunNhideZom @@ -19459,104 +40560,199 @@ Runcatsmith Rundamental Rundi Rune +Rune Scimmy6 +Rune Strg +Rune Toi +Rune Trophy +Rune Tunes +Rune Woolf +Rune l Scape +Rune lennyFe +Rune mendigo +Rune-Taneli RuneAlt1 RuneArguero RuneBri RuneFiend RuneKing2h +RuneLight RunePuuro +RuneShape +RuneWeems Runebie93 Runeblaizer +Runebryter Runechi Runecraft +Runecrafts +Runed Ltd Runeiro Runely Runeman3134 +RunenSohn Runepalmu Runeranta1 RunesCrafted RunescepxD RunescepxDD +Runeshaft16 +Runesniffer2 +Runesr4nerds Runester9999 Runeukko431 +Runeveeti +Runeventure Runey +Runey Toons Rungne14 RunicXanadu Runita Runite +Runite Ricky RuniteNerves +RunkoPalkki RunnerTwoD2 RunninBlood1 Runnn +Runny Rectum Runnynumber2 +Runolf Runs +Runs Laps Runtellthat4 +Runtu Reiska +Rup +RupOSRS +Rupea Ruperd +Rupert Whale Rupiss +Ruptured +Rupus +RureScape Ruri +Rus s Rush618 +RushAl0t Rushana Rushflame555 +Rushing RushnSuch +Rushoo Rusinahousu +Rusinapulla Ruskajan +Ruskeareika +Russano RussianLives +Russian_Fire Russkill1000 Rust +Rust Oxide RustLasagna +Rustaaaagh Rusted +Rusted Ape Rustee +Rusticis Rusticus Rustig Rustigggggg Rustix Rustu Rusty +Rusty Spoons Rusty99 RustyFoot +RustyPlastic RustySimon RustyStipps RustyTuna +Rustydog125 Rustynice Rustyw Rusy002 Rut469 +Rutgar +Ruthacus Ruthers +Rutje Ruto +Rutten +Ruttuperse Rutu +Ruudcz +Ruuddie +Ruup Ruut Ruutana +Ruwe Dollo Ruzafa Ruzy +Rvght Rvilleboy +Rvndy +RvneHQ RvrseGiraffe +Rvsta +Rvvvy Rwkw +Rwolfe +Rx bones Rx-ll +RxHarmacist +Rx_Sparky +Rxscro +Rxzm Ry Jones 21 +Ry T +Ry n +Ry-07 RyGuyyy1 +RyKush RyQzz +RyRgrMcFrly +Ryaite Ryalae Ryan +Ryan 178 Ryan8529 RyanApollo +RyanC203 +RyanFar25 RyanKristoph +RyanNagato +RyanPick RyanTW Ryanandneal Ryaneal RyangalO +Ryanmattin0 Ryann737 Ryanpage RyansRebuild Ryanwouldsay +Ryawh08 +Rybizzle Ryca +Rycerz Arek +Ryd Ryder Ryders +Ryderwear +Rydwarf RyeAnn RyeEx +RyePie +RyeYun +Ryeron +Rygelon Rygo111 Ryhan +Ryi Ryjgar Ryking +RylanIsLive Ryleegh Ryley Rylios @@ -19568,76 +40764,216 @@ Ryokojin Ryolm Ryoma Ryougi +Ryougi Shiki +Ryouma Ryoush +Ryronman +Rystaloid +RystyRane Rytacus +Rytis +Ryu Deadass +Ryu L Ryugo Ryuk Ryukiral +Ryuko +Ryul Silvyr Ryvik Ryxidius +Ryyd Ryzelf Ryzema Ryzho Ryzloh Ryzou Rzasa +Rzy4k +S 0 R A +S A S H O +S A VV A G E +S C N +S C U Z Z +S E T C H +S G M B +S I N +S J H +S M A S H ER +S M I L E S +S O Z O +S P E E E D +S Q5 +S Rye +S Spirit +S T ACK E D +S T E F AN +S T E N +S T I L L +S T R 4 ever +S T R Pwnz5 +S U F F +S V N E +S W A N N +S a z z y +S acrificed +S aevar +S aii +S ammmy +S co t t +S cruffy +S e 7 e n s +S e a f o +S e e j +S ebbe +S emi +S enu +S err +S h a n e oo +S hadw +S hayzz +S hea +S hep +S imply +S k u ll y +S kari +S l M B A +S l3 +S nipz +S ofa +S offa +S ofus +S orrow +S oulz +S outh +S p00ky +S secy dy +S t e v e n +S t i +S t i g +S t i x +S tas +S u b j e ct +S uffa +S unz +S wan S-525 +S-Market ll S00000O0000k +S0FTPUPPY S0L0 +S0L0 SL0AN S0MALISLAYER S0O0O0O0O00S +S0S JERRY +S0UVLAKI +S0Z4 S0ar +S0ciety +S0dra +S0gg3 S0ldern S0lomon44 S0lty +S0nical S0phie S0tg +S0thra +S11om +S1MPSLAYER S1N6 +S1NA +S1ORM S1SU +S1ayzAllDay S1n0fWrath S1ngul4rity +S287 S2u2 +S3 Matt S3ID S3W3RSLVT +S3n4_Hc +S3oulful S4M0HT +S4M20N +S4v4s S5peedy S60RDesign +S7arburst +SA alter ego SAAB_Toxic SAAIXX SAGLAM SAINt +SAINt Steff SALM00O00N SALM00OOON SAMCRO SAMMMMMY +SANDFROG53 +SANFEWLUVR78 SANO +SANRIPOSYCHO SANTERCOMTER +SANTO5 +SANYANOSTRAH SAPl SARAH SARPBC +SATAN GOD +SATORIIN SAUCEnJUICE SAVVON SAWPREME SAlNT SAlNTS +SAlYAJlN +SB DRIFT +SB Luke +SB Mac +SB Mully SB2K SBSBSBSBSBSB +SC0V SCARED SCHOOTSFIRED SCOTUS John +SCR0TUM +SCRAMMMBLED SCRIMS +SCRT SAUCE SCYukino +SC_Josh +SClarky +SDC Thursday +SDV SDVX SDemotivated +SE Alaska +SE N SE SECDEF SELF +SEMI CHUB ON +SEMl DEAD SEPTlC +SESACO SETU +SEXY GRETA +SFTYALWYSOFF +SG +SGNG SGTA +SGTX SH333S +SH5 SHAD0WBANN +SHAGED +SHANK SAMA SHELDOR +SHERMnNATOR +SHElD-HEDA SHIA +SHIA_WIRE SHIDDED0N SHIIIELDS SHINY @@ -19645,76 +40981,143 @@ SHINZ0N SHOTGUNSUGE SHRIIlIlIIMP SHlESTY +SHlFTER SHlNl SHlVER SIBS SIDB +SIGMA MALE69 SIGNZ SIKKaudio SILENT SIMAA +SIR KIRSI +SIR_WHAT_NOW SISDIS +SIayer +SIoopie +SJ7 +SK octorock SKBToast +SKBerk +SKD +SKDMRX +SKDee +SKEEZUZ SKKi63 +SKlDMARK SKlNNY +SKlTZO SL0AN SL1T +SL3DNECK SL3VEN +SL90 +SLAAYEEER SLAP +SLAP A SL0TH SLAY SLAYER +SLBM +SLE Casper2 SLEEEZY +SLNT SLOpro +SLV +SM Esura +SM Tech N9ne SM0KE SMANisonfire +SMEGMAEATER +SMGO SMHeMbRBoB +SMKoolin SMOrc +SMOrc Weeds SMOrc3000 +SMRT KO SN0W SN0WBUSH SN3AKBO SNAX SNAlIlIlIlIL +SNUIVEEEEEH +SOCIAL SCARE +SOLO D0L0 +SOLlD SOMALISTEVE9 +SOUL MASTER +SP1NK +SPAICC SPANKWlRE SPLEEBTEZ SPLODGE +SPOODERMENNN SPOOKAH SPlCER +SPlCY RAMEN +SPlDER-MAN +SQLite SQSHD SR0o0RM SR20 +SRH IM +SRSwiper +SS Iron +SSF Fe BTW +SSJ2 GhostMO SSS-Latch SSamm SSco0by1 SSironMage +SSlavic +SSnakeling ST0n3 ST3AKS STAIGZOR STALlN STAMPEE +STARSZSZ +STAUNCHEST STEEZ +STEEZ UwU STERGS +STEVEYZERMAN STEVIO STElNSGATE +STElNSGATE 0 STIFT +STM32 F103 +STOERE OMA +STPN +STR m8 +STRZI STRlCKEN STRlDERMAN STSTSTSTSTST +STUB0RN STYG STZY STlFFMElSTER +STlNGRAY SUBAROO +SUJET0 +SUP3RCLAUDIA SUPA SUPERSET q SUPERTAIKURI SUPREME SURPRlSED +SV_Exon +SW3GG3RZ SWAGL0RD +SWE4TY +SWlPE LEFT SYMBI0TE SYMPATHY SYRpaperclip SZP-Qlimax +S_nacky SaHiB SaItbender SaSoeur @@ -19723,61 +41126,144 @@ SaZz Saagarius SaakeliMies Saambellah +Saaq Saarinen Saassz +Sabba Sabbatix +Sabbelaar +Sabeket Sabel26 Sabelt +Sabeltann26 Saber +Saber Alter +Saber Lilli +Saber Six Saberloco +Saberos +Sabich Sabina +Sabitoo Sabler Sabo +Sabor Fresa +Sabotaging +Sabre Doge Sabretooth Sabu549 +Sabuwu +Sac Sacck +Sacha Boeyy Sachets +Sack 2 Dirty Sack_Lunch Sackofeyes +Sacolyn +Sacre Sacred +Sacred Eli +SacredArtist +Sacrificed +Sad Boi J +Sad Fat Ugly +Sad Juggler +Sad Leaf +Sad43 SadClownP +SadJB +SadPanda94 SadWhiteFalc SadamBHangin Sadass Sadcatxd +Sadge Izzy +Sadge2407 +SadgeCry +Sadgetseg Sadiq Sadism +Sadistic Sadivy Sadness +Sadting Sadystic Sadz +Sadz Rax +Sae Bae +Saena +Saenmin Saeph Saerdna97 Saerom +Saetama Saetre +Safavid +Safcon +Safe N Sound SafeFromWork +SafeUp YOLO Safecamp +Safelyfast +Saff +Saffat Saffi Safiir +Saftsack8 +Saga +Sagar Sage +Sage Lao Tzu +Sage Lily +Sage North Sage Vegas SageO6 Sageinventor Sageme Sager +Sager Main +Sagev Saggy +Saggy Weenis +Sagittarios Sags +Saguaro Joe +Sah D +Sahin +Sahonym Sahra +Sai +Sai Chosis +Sai Saici Sai1420 +SaiPhai Said Saifphire +Saigyouji Saiin Saika Saikoh +Saikoo +Saikou Saikshin +Sail Door +Sailing Prod Sain Sainola Saint +Saint 7 +Saint Acura +Saint Andrew +Saint Bjorn +Saint Fabioo +Saint Fellow +Saint Hatred +Saint Hyde +Saint JJJ +Saint Silver +Saint Tmi +Saint Zero SaintBurgs SaintDienda SaintDovey @@ -19786,253 +41272,466 @@ SaintMilk SaintPablo68 SaintShiba Sainted +Saintri Saitam Saitama Saivaa Saiyajin Saiyan +SaiyanSkinn Saiyanns Saiyans Sajjad +Sajzi Sakhmett +Saki Nikaido +Sakix Sakk +Sakke Sakkyun +Sakobi SakooR Saksa +Sakuragi +Sal Magluta SalBobo Salacity Salad +Salad Car +Salad Kareem Saladhead25 Saladsoup SalamPacanam Salamalion98 +Salbo Salcal Salda Saledor Saleen Salford +SaliBronze +Salih +Salii +Saliis Main Salista Sallad +Sallariina +Salllamander Salma Salmelainen Salmo Salmon +Salmon Ikura SalmonCookr7 +SalmonsRule Salmos33 Salms Salomon Salomon666 +Salone Salorassi Salsa SalsaMurango Salt +Salt Mines SaltInTheCut SaltPJ SaltasVolfas Salte 55 SaltedCorona +Salten Saltia Saltigast Salty +Salty 4 Life +Salty Cris +Salty First +Salty Fooker +Salty Gimp +Salty Guava +Salty Slimy +SaltyNakul SaltyPears SaltyPilgrim SaltyQuackr +SaltyShrimp +Saltydivo Saltzpyre +Saluskenas +Salvats +Sam Biddle +Sam F +Sam II +Sam Knight +Sam S +Sam Tha Man +Sam Zi +Sam btw +Sam1 Sam5453 SamFC +SamGaspacho SamManSnow SamV007 SamW +SamWisely +Sama ntha Samadier Samadieron Samaji Samalorian Samanthix +Samantics Samay Samb0Slice +Sambal Sauce Samblader +Sambwo +Same Deal +Same Kid +Same Thanks +SameerM0 +Sameling Samfew Samfundet Samgonz3 SammGemm Sammi80 +SammieRose Sammito2 Sammjoey +Sammstera Sammuel +SammyGer Samo Samoski +Samphet +Sample size SampleText Samprini Samps0n Sampson Samqqa Samri +Sams Main +Samsara Kama Samsoniene Samsora +Samster8812 +Samu Saukko Samubidladin +Samuel Hall +SamuelBrian +SamuelP223 +Samuell C Samurai Samusar7481 Samwse Samxy Samzh +Samzju Samzor +Samzy +San Quentin San0 +San200 SanHolo SanPaid SanSheng SanTie +Sana Sanada +Sanark +Sanbir Sancta Sancte Sand +Sand Raider +Sand Shrew +Sandal Slap Sandbar +Sanddemon527 Sandelzi +Sanderr +SandhillFrog Sandhog +Sandhur Sandiey Sandman1 Sandmannen9 Sandogan Sandokan +Sandoval Btw Sands +Sandviper40 SandwichBag Sandwichfish Sandy +Sandy Claps +Sandy Land +Sandy OS +SandyLand +SandyMonkey SandyWexler +Sane Panda +SanePizza +Sanellyyy +Sanfew Serun Sangers +Sangi Sangotha Sangtuary +Sanguinala +SanguineHawk Sanguinezti +SanguisDurus +Sanitary Poo SanityCntrl Sanjachi +Sanjai13 Sanjin +Sanka +Sanka93 SanodersNL Sanoske13 +Sanphew +Sans Soleil Sanshou Sansos Santa +Santa 07 +Santa Chielt +SantaChristo +Santapwner Santasos Santeri Santeri333 Santhacine Sanzoku +Sanzoku HC +Sanzu_o SaoriHayami Saoro Saosiiin +SaphiTheBear Saphie +Saphirakush Saphiro Sapin +SapphicDiana +SapphicEmmmy +SapphicJade Sapphirebear +Sapphirelove SappieWappie +Sappihron Sappphire +Sappx +Saqi Saqib +Sar a Sara +SaraNotDomin Saradominas Saradontmin +Saragomin Sarah +Sarah Hagan SarahWalker +Sarahsaurus Saraie Saran +Saran07 +Sarangae Saraph +Saras BBD Saratomi Saraziel Sarbles +Sarcasmder Sarctopus +Sarcy Csp Sardaukar Sardlz +Sarecren Sarfar Sarge +Sargon III Sariel Sarkie Sarmagedonas +Sarms Knight +Sarodin Sarrafo +Sarrdukar +Sarri Sarriesque Sarro Sarrz +SarthaMewart Sarthe +Sarthinox Sarthorm Sarumite Saryit +Sarytis Sascha +Saserdoti Sash Sashadow Saskel SaskiaNaka Sasser Sasslax +Sasssie Sassy +Sassy Rookie Satada88 Satamari Satan +Satan Claus SatanSquared +SatanarchyXX SatanicGrill +Sataniciocus +Satans Ktten Satchmoi Satchyl Satisfyed +SativaDreams Satizfy +Satoo +Saturdayxz SaturnHippo Saty +SauLau +Sauce McBoss +Saucestad +SauceyFox +SauceyHorsey Saucy Saug +Saugy Saul +Saul Bloom +Saul Pvm SaulMozarela Sault Sauna +SaunaPaska Saund Saunders SaundersRNG0 Saundo Saunty92 Saurogar +Sauroiv SauronsTower Saus +SausageRyder +Savabeel Savage +Savage City +Savage Gamer +Savage Kush Savage Mind +Savage Pimpn +Savage Titan +Savage izJkD +SavageBigL SavageSource Savaged Savakuda Savalar Saved +Saved Me Savg Savilahti99 Savior +Saviour +Savj Savjry Savoureux Savpryan Savu +Savu Nahka Savustettu +Savvo +Savvune +Savvvy Savvy Savy +Savy Neals +Saw Em Off +Saw Siege Sawanne Sawaz1 +Sawbonez Sawdey +Sawrik Sawzall12 +Sax +Saxerpillar +Saxlord2500 Saxon +Saxon_knight +Say Allo +Say Freeze +Say Geronimo +Say Go Put +Say Gz Rn +Say aligh SayMyName +SayNo2Ebola Saya Sayadzin Sayersi +Saylorbtw Saymouseart Sayonara +Sayooo +Saypa Sayrim Sayrr +SaysNiceAlot +Sazch +Sazere Sazme Sazzarull +Sboy_90 Sbraga +Sc ruffy +Sc0nesy Sc0ttishDave Sc1ttl3 ScOx +ScOx ChrisM +Scabrick Scaf Scaggy +Scaha ScalerSlut +Scales +Scampr ScandalousHC ScannerBen Scape +Scape Jam +Scape Snake +Scape Steve +ScapeChad ScapesGhxst Scapeskater +Scapin Scaping Scar +Scar TNL +Scar of Time +Scarb OS Scare077 Scared +Scared Jr +Scared Zebra ScaredOfAll Scarfade Scargut @@ -20041,63 +41740,99 @@ Scarlett ScarredScape Scarsx Scarves +Scary Face +Scary Me +Scary Parrot +ScaryBrandon ScaryShadows ScaryTerry ScaryVacoom Scat Scat19 +Scatheful +Scatter +Scea +Scemblix SceneGfX Sceneryy Sceptile Scew Schaapers +Schams Scharnhorst +Scheemz +Schepo Scheubz Schienenwulf SchijnWerper +Schildkroote Schildpad +Schileru Schiller1994 Schimy Schiphol +Schismo +Schizphrenia +Schlaide Schlak182 Schlanged +SchlipityDop +Schlitz Schlock Schlowmo Schlynn Schmaltz +Schmelting Schmidtty641 Schmokeyboii Schmoovin +Schmuck Schmuel Schmuk +Schneemann90 +Schnei Yo Schneidster7 Schneyy Schnitzel Schnitzl +Schnocks +Schnoob Schnops Schnozz Scholi Schoolies Schools +SchoonCombat Schooner Schoonzoon Schoopity Schorr Schout Schovaval +Schretty +Schricky +Schrodingus Schuabinator Schuck Schuyler SchwanzLord +Schweiaos Schweigende +Schwiemann Schwingy +Schwog Schwoopity +SciCloan +Sciamachy Sciario Scids Scils Scimi +Scimista Scimmy2face +Scion 1T ScizR +Scizorp Sclass707 Scodran Scoffs @@ -20105,79 +41840,160 @@ Scofiz ScoobaQ ScoobiedO0 Scooby +Scooby T1 +Scooby Yew +ScoobySnack +ScoobySnacks +ScoochPoooch Scoopie Scoops12 +Scooter999 +Scootr +Scoots Scoped Scorchbeast Score +Scoreox +Scoreyy +Scori +Scorial Scorialator Scorlibran Scorpiex ScorpioBoy +Scorpslay +Scorqion Scortyx +Scot ty ScotianHerbz Scotse Scott +Scott 0888 +Scott Men ScottJ +ScottKZ Scotteh Scottie ScottieP ScottsTotlol +Scottsdale +Scottvc Scotty ScottyPippen +ScottyThrall Scottyx Scourging +Scouse Lyfe +ScouseBandit +ScouseThanos Scout +Scout Dorvis +Scout Troopr +Scout a raid +Scouting UIM ScoutnStake Scowder +Scp-2786 Scr0t Scradmaster Scraex +Scrafo Scrambledleg Scrap Scrappy666 +ScratchGolfr Scratchzilla +ScreamIM ScreamSavor Screeb Screen Screws +Screws Floor ScrewstonTex +Scrig +Scringo Scrkidzl12 Scrotboy +Scrotetseg Scrruff Scrub Scruba10 +Scrubgod Scruffy +Scrums Scryzen SctyDsntKnow +Scuba Steev7 ScubaSnacks +ScubaSteveOG +ScubaStweeb Scuff Scuffed +Scuffed Jesu +Scuffed Ming +Scuffed Sire ScuffedGoose +Scuggie ScumBagAlex Scumbag +Scumbag Joe Scummy ScummyMonkey +Scumpi Scurlll +Scuro Scurrilous Scuto ScuttleAway +Scuzz OS Scvthe Scwubs Scybin +Scyld Scythe ScytheOrNeck +ScytheShreds +Scytheer Scytheplease Scythes Sdelta230 +Sdsdsd789 Sduckk +Se Ki +Se rena +Se7en Rye SeBambi +SeDzz SeLeV +Sea 7urtle +Sea Anemone +Sea Buoy +Sea Hawkins +Sea Lobster +Sea Monk +Sea More +Sea Saint +Sea Slugs +Sea Turtle +Sea Turtles +SeaManTaster +SeaShanty +SeaShellKing Seagal +Seagaru +Seagate Seal Sealab +Sealegs Btw +Seamlessly +Sean E +Sean Is Sean278 +SeanIsHiding +SeanRich1 +Sean_C Seande4 +Seangie 91 Seanii Seantjl Seany4444 @@ -20185,22 +42001,54 @@ Seanye Seanz Seapy Searched +SearingPain +Searob Seas +SeasTheDay +SeatGeek +Seated Seater +Seater HC Seath1552 +Seatoad Seaweed +Seazeee +Seb Fe +Seb Lt +Seb Sob +SebBTW +Seba Iron +Sebis Sebla +Seboeber +Seboobs +Sebukai +Sebzy +SecBongToke Secho +SecondMars SecondStage +Secondary +Secondes Secret +SecretlyACat Secretly_Bad +Sectokin +Sector Six Seculish Secwai Sedap Sedentary +Sedlom +Sedrf23 +See Too Far +See u em +SeeMeGoing SeeYou Seed +Seed Of Dee Seed386 +Seeeek Seeejay Seek SeekerofIron @@ -20208,222 +42056,425 @@ Seekerz Seeking Seeliss Seems +Seems Legit SeemsFair Seen +Seen A Babe Seenoevil +Seery Seerz Seffer Kover +Sefirah +Sefka Sil +Segelpaatti +Segma Sego +Segs69 SeibaRaion +Seifeltz +Seifer666666 Seig91 Seighilde +Seigneur5000 +Sein Blut Seiskalehti Seiverna +Seiya216 +Seize Sejaeek +Seje Sejj SejjNesta +Sek Loso +Sekaiyatra +Sekava Seko SektorQ Selaphiell +Selastiri +Selbyen Seldrium Selectic +Selena Gomes +Selesi Self +Self Attempt SelfStanding Selfie +Selina Kyle Selj SellMaxMain +Sellerz Selling ROTS +Sello_Hunter Sellu Selmer Selostaja +Selyk +Semantic +Sembient +Seme Semestro Semeul Semi +Semi-Stable SemiReliable Semih Seminary Seministi Seminoles +Semirare Semlan +Semours Semper SemperOP +Semperlex Senarii Senbonzakra Sencillo +Send Backup SendItKing +Sengster Senhor +Senhor Prego Senia +Seniab88 Senior +Senior Wells +SeniorCui SeniorLep +Senis6 Senjor Senkaiye Senkuu +Sennno +Senny Bridge +Seno 45 Senor +Senor Grumpy +Senor Nub +Senor Patata SenorMarcSux Senpai +Senpai Avv SenpaiDecer SenpaiiGod +Senpenbanka Senpukyaku +Sens Army Sens249 +Sensas Senses +Senses Fail Senses12 +Sensie SensualSnail Sentinel Sentristi Sentrosi Senturia Senzel +Seoyeonnie +Separi Sephiore +Sepi testaa Sepper Seppiee +Seps +September 26 Septic Septimus +Sepv +Sequenced Sequin Sequinex Sequissimo SequissuAnau +Ser Bone +Ser Boris +Ser Kelvin +Ser Paddles +Ser Percy +Ser dracarys Seracid +Seraff Fe Seraph +Seraphine BF +Serblicious SerenShadows +SereneMarine Serenity +Serenity Now +Sereri +Serfival SergeiSativa +Sergonomicus Serial +Serialist Serine +Serioga One SerionKiller SeriousLip Seriousruss +Serkr Serkus +Serls +Sernara Sero87 +Seroplex Serori SerotoninBTW +Serpent Sin +Serpico Serpula +Serpy +Serros SertCocuk Server Servia Service +Service Jobs +Service user Sese Sese778 Sesil +Sessanna +Set h SetItToWumbo Seta Seth +Seth1711 Seth6191 +SethH350 Sethalas Sethliu Sethmare +Setko Seto292 Settled +Setzal Seut Sevadeg Sevalt Seved223 +Sevenation Seventh +Seventh Son Seveoon Seveoonn +Severith Sevie Sevvy Sewdri +Sex Beast +Sex Gods +Sex Sea +Sex Vibe +SexEZ SexFerguson +Sexi Rat +Sexperience +Sexsi Sext0n Sextor +Sextuple +Sexy Carl +Sexy Cholo +Sexy Style +Sexy Will +SexyFatGirls +SexyLefty +SexyPeaches +SexyShooterr +Sexyteurs +SeymourAses Seyriu +Seytan Sfa05 Sfannie +Sfd Sfen +Sfouf +Sg Mini +Sgn +Sgs flames +Sgt +Sgt J0hns0n +Sgt Jacques +Sgt Moogoo +Sgt Ru642 +Sgt Salliss +Sgt SaltySac +Sgt-Sub0_99s SgtBuurman +SgtSausy +SgtSlaughtur +Sgtbea93 Sgtfatboy Sgtsoldier Sh00t3r2O2O +Sh0rt Lived Sh0rty Sh0w Sh3pathome Sh4d0w009 Sh4dowfox Sh4rice +Sha r k Shaan ShabooBopWoW Shabot +Shaboun Shabuski Shaco +Shaco Bot ShaddyB +Shade T ShadeSlay +ShadedWizard Shadedmedic Shadeknightt +Shadesypoo Shado +Shado Man69 +Shadonnon Shadow Shadow Flare +Shadow Left +Shadow Specs ShadowBobado ShadowBoy001 +ShadowFink +ShadowGodEU +ShadowJosh ShadowMakerz +ShadowPrism9 ShadowSinz ShadowSniper +Shadow_006R Shadowclysm Shadowcra Shadowlimes +Shadowmax666 +Shadows Fall Shadowscreen +Shadowsun +Shadowwheel Shadsnp2017 +Shadum ShadwRoca Shady +Shady 716 +Shady Glade +Shady Shin +Shady417 Shady78 ShadyMilkMan +ShadyMinkins +Shadys Bro +Shadysider ShaftyKrafty Shafu Shagnarok +Shags Bussy Shagzy +Shahe D +Shahub ShakaLakaInU Shake +Shakeem +Shakeman ShakenSoda Shakkas Shakuuuur +Shalamaar Shalendra Shallistera +Shalomga +Shalysa +Sham on Osrs +ShamSavior Shaman ShamanJon ShamanLizard Shamanletics Shambler96 Shame +Shamiina Shampoe +Shampoo Shamsal +Shamu +Shandaie +Shandooobie Shane +Shane F3 ShaneSJ Shanee-oo +Shanem24co Shaneobrahhh Shaner Shanfew Shania +Shania Twain +Shanizmo Shanked +Shanked it Shanks +Shanks Haki Shanksen +Shantaaa +Shantar +Shanteven Shantideva +Shapalo Shapaz Shape Shaper Shapii Shaqs +Shaqster1k +Shaquayquay Shard +Shard 2 +Share E R +Share Sucks Shareit Sharing Sharingan +Sharingan x SharishaXd Shark SharkTheBait +SharkiFan Sharkie200 +Sharkie92 Sharktail Sharkyyyyy Sharmac Sharmz +Sharn Sharoxi Sharp Sharpeyy Sharpgut +Sharpi e +Sharpie Sharpman767 SharpyClaw Shart +ShartEnjoyer +Sharven +Shasan501 +Shat 2 Hard Shatllef Shatter +Shatter Day Shaun +Shaun R Shaun135961 +Shauna Vayne +Shaunhunni Shaunni1 Shaunrnm3 Shaunyx @@ -20434,234 +42485,460 @@ ShawnBW ShawnBay ShawnXL Shawni +Shawnoh +Shawrysx +Shay Kirbuti Shaya +Shaya Rene +Shayd Shaykolade Shaymuz ShaynRS Shayne +Shayne 1 +Shayne Topp +ShayneW +Shaziyen +Shaznon Shazu00 Shazzys +Shckizm +She Moist +She Slackin +She is lvl18 +Sheashanera Shebbi +Sheep SheepKhalifa SheepTrainer +Sheepi Sheeppo +Sheer freeze +SheeshSkicka +Sheeshlor Sheetm3tal Sheetz +Sheev +Sheff-Rah +ShegoSimp Sheguey +Sheikk Sheilaaaa2 Sheivattu +Shelbgasm Shelbi +Shelburz Sheldore Sheldozer Sheli Shelios +Shelkun ShellBeRight ShellLeeBee Shelldunk Shen +Shen Btw +Shen-pai Shenfu Shenkie Shep +ShepShep95 +Shepher +Shepherdess Sheq +Sherbert96 +Sherkey Sherlock +Sherlock 07 +Sherlockness +Shernz Sherry +Shertie +Shes Nasty +Shes Royal +Shesterkin Shev64 +Shevzzz +Shewolf Nova Shezwick +Shh +Shh Im Maxed ShiaLaBuff Shiba +Shiba Miyuki +Shibidy Shiddy +Shieldy +ShiftWorker +Shifteroo +Shifterr Shiftless Shifty Shiftynifty Shiftyy Shifu +Shigure +Shihyi Shiifty Shiiftyy Shiit +Shiit head Shikhar Shilo +Shilo Void Shilomies +Shilvah +Shimmeister Shimosh +Shin Nohara ShinMalphur Shinchi +Shine tales Shing +Shinichiro Shinigami +Shinigami 07 +Shininess ShiningStar0 +Shining_Bind ShinnGee Shino +Shinobi Shinook +Shinox Shintaz Shintygod Shiny +Shiny Dragon +Shiny Glue +Shiny Mew +Shiny Olm ShinyMimikyu ShinyNoctowl ShinyShyvana Shionono +Shioshii +Ship I +Ship s +ShipCaptCrew +Shipoden +Shipppo +Shippy +Shir +Shir0u Emiya +Shirakami Shiramasen Shiranaii +Shire Fox +Shiredragon Shiri +Shirlan Shirts +Shishkemax Shiskey +Shiv HD +Shivals Shivered +Shiveron Shivers888 Shivoc +Shiyah +Shizlo +Shizzus +Shmazza +Shmeckington +Shmecko +Shmelf +Shmerlin +Shmew +Shmexy +Shmidtie +Shmo Shmoah7 +Shneeb Shnoobed +ShoToy +Shoarma Shoarmadyl Shocka +Shocked Shockedme +ShockerMe +Shockzeyy Shogaol +Shompy Shongrislomg Shonion +ShooK em Shoog +Shook Shoopdiesel ShootYaSkool Shootem40 +Shooty Tater Shop +Shopferix Shora57 Shore +Shorelyy +Shorez Short +Short Mike +Short Tale ShortHoppe +Shortec Shortguy Shortstop819 +Shortz360 Shot Shot1200 Shotixx Shotoer +Shotzz +Shoulderr Shouto Show +ShowFeet +ShowUrPits Showby14 Shower +Shower Maxed Shown Showtek Shozen Shpee Shpikey +Shpongle +Shrabbaa Shran Shredded +ShreddedMD Shregz Shreikkiller Shrek +Shrek 6 +Shrek BTW +Shrek2 ShrekLovr +ShrekazoidPR Shreksalot Shrik Shrikems +Shrimp 72 ShrimpForx ShrimpStick Shrimpa +Shrimping Shrimpster Shrimpy5 Shroden +ShrogTheBarb Shromik Shromu +Shroom God +ShroomLord17 Shroomjak Shrtct +Shrumes Shtankybruce +ShuZ Shuaston Shuckle Shuddie Shuffleee Shuiin Shultzy +Shun Conery +Shundo Mew +Shungite Bar Shuno +Shunolog Shunpown Shunrai Shunseh Shupa +Shure Shurty Shut +Shut Up Megg +Shut Up Mmeg Shutnik +Shv Shvne Shwift +Shwiftzy741 +Shwoompy Shwoop +Shxtn +Shy Kirino +Shy Mew +ShyElfTrap ShySphincter +Shyhorsegirl +Shyphii +Shypsena +Si Ya +Si d +Si mp SiFu +SiIver Fang SiRzZ Zeref +Sia +Siallus +Siamees SiameseCat Siamogale +Siane +Sianna Siber Sibling +Sic Mundus SicSolaFide +Sicariiarum Sicily Sick +Sick Degen +Sick Ego +Sick Giraffe +Sick Irony +Sick Main +Sick Mark +Sick Pet +Sick Skill +SickFam +SickGainsBru SickNasty SickPete +SickPump Sicka Sicker Sickhuman +Sickhunt +Sickle76 Sicknez Sicko +Sicko Stronk +Sickvibe +Sicxness +Sid and Geno Sidabras +Side B +SideChump +SideMeatt +Sidecutters Sides Sidewinder15 Sidge SidijuS +Sidin1 +Sidka60 Sido Sidocahn +Sidro +Sie SiebScho +Siegmeyer14 +Sielunveli +Siemke SiennaEhtycs +Sierra Echo Sierzant Sierzy Siesta Sifu +SifuPlankton +Sig Man +SigSauer Sigarda206 +SigeFrid +Sigefride Siggen Siggie Sigh Sighlent SightUn +SightUn Seen Sighted SightlessDog Sightlines Sigiis Sigin +Sigma Blood +Sigma Oasis +Sigma Seven +Sigmarz Sigmazeous Sigmet Sign Signd0g +Signoth +Sigrudson Sihana +Sihl SihuiRS Sihva +Sihva Dark Siida +Siiiiiiix Siimon3 Siimse Sijmen Sika Sika-Mika Sikauss +Sikerrim Sikko +Sikko NL Sikkosaurus Sikn Sikruz Siks Sikskilla Silanz +Silasco Silavex Silcaria Silcooper Sild SilenceSC2 +SilencedAF Silent +Silent Sky Silent too SilentEnmity SilentFabric SilentFaux +SilentQ Silentzsword Silicon Z +Silinsh Silixi Silky +Silky Beauts Silly +Silly Asian +Silly Kev +Silly Rum +Silly Virgin +Silly Zilly SillyPsybin Sillyibexe Silmarilli +Siloxane SilvaAlzir42 Silvaa Silvado +Silvanla Silver +Silver Cave +Silver King +Silver Lugia SilverForM SilverLining +SilverPuni SilverRizlas SilverTeej +Silverado Silverang Silverbluds Silvercrux @@ -20671,89 +42948,244 @@ Silverimo Silverxlion Silviii Silvoan +SilvrLining Sim Aero Simeeon Simel Simetra +Similuck +Simmcheck Simmi091 +Simmie Simmololol +Simmondz +Simmumah +Simno Karys +Simoggy +Simon Bruh Simon Jnrr SimonCookie +SimonCowell +Simone Weil +Simp Andy +Simp4Jessy +Simp4Science Simp4Tanz +Simpa +Simpinz Simple +Simple Helm +SimpleSlays +Simplekinz Simplest +Simplex +SimplexDabs Simplicitey Simplicityx Simply +Simply Quiet +Simply Sam +SimplyBadass SimplyBetter SimplyFresh SimplyLlama +SimplyNikki SimplyPro +SimplyRiolu SimplySendIt +Simply_JS +SimppCatcher +Simpson +Simse SimulatedYou Simutrans +Sin Cena +Sin Cere +Sin City +Sin Dragon Sin0fWrath SinCrux +Sinappihauki Sinasappel Sinatra Sinbad Sinbvd Since SinceOldDays +Sinclair Oil Sincoura Sindo +Sinefeld Sinerule Sinetine +Sinferna SinfulDesire +SinfulDingo Singerderek +Singulares +SingulariTx +Singularry +SinikOG Sinister +Sinister C6Z +Sinister Key SinisterLeft Sinisterz06 +Sinistr Dave Sinitank Sinixx Sink Sinka +SinkingUnder +SinnerUK Sinner_Blue Sins +Sins of Thor +Sint Truien Sinta +Sinterglass +SiontC100mph Siorri Sioux +Sip Cleeko +Sipa SippinBeers Sippy +Sippy 1 +Sipsta +Sipuliparoni +Sir Zhao +Sir 0wnalot +Sir Ali +Sir Ante +Sir Boberton +Sir Botje +Sir Brandito +Sir Burritoe +Sir Chancho +Sir Colossos +Sir Daven +Sir Deedge +Sir Delwin +Sir Doland +Sir Doobies +Sir Elusive Sir Epic 3rd +Sir Ferreus +Sir Fire Ki +Sir Frekkel +Sir Fudmire +Sir FurDude +Sir Galleth +Sir Godfree +Sir Graj +Sir Ial +Sir Idwaly +Sir Iron 4th +Sir Jamie N +Sir Jinhai +Sir Junn +Sir LafaLafa +Sir Lanofg +Sir Leadfoot +Sir Lidd +Sir Lobster +Sir Luke1627 +Sir Max Tb +Sir Mordacai +Sir Mr Bro I +Sir Nak Sir NichoIas +Sir Nuggers +Sir O Tonin +Sir One Shot +Sir Peg +Sir Poisonfa +Sir Pur Paul +Sir Queeffin +Sir Reflex +Sir Reos Lee +Sir Rhaenir +Sir Rolf exe +Sir Seifer +Sir Shrimps +Sir Slyck +Sir Son Goku +Sir Sparhawk +Sir Stidi +Sir Stitch +Sir Sucellus +Sir Sven +Sir Tanner +Sir Ton4 +Sir Towliee +Sir Truble +Sir Var4 +Sir Ving +Sir Vkk +Sir Whipit +Sir Wismar +Sir Wojtek +Sir Zakar +Sir friezer +Sir philippe +SirAirik SirAmikVarze SirAngo SirArcAngel +SirArimal +SirBabbers SirBerus +SirBjustice SirBoma +SirBoopin SirBroderick SirCapper +SirChknNuget SirCoolAsian +SirCumsAlil +SirDanSolo55 SirDarrBear SirDeimos +SirDouglass SirDougles +SirDoyvid +SirDude SirEfficient +SirEskimo +SirFroggits +SirGillespie SirGoki +SirGrimsby SirGrizzly SirHines SirHmm SirHollywood SirHumanBean +SirIronyMan SirKakoiml SirKefir SirKill SirKulls +SirLarry55 SirLoinalot0 SirLunarias SirNexALot +SirOcean +SirPegAsians +SirPhockQ SirPoo SirPwn SirRebs +SirRuck +SirSanders +SirSchmoopy SirShakes SirSilky SirSlayalot SirSpicius +SirSplinge +SirSunTitan SirSwaggzz SirTrea SirVenompool @@ -20763,49 +43195,92 @@ SirYiffer Sir_massmo Siraxis3310 Siraz +Sircamm +Sircarenot2 +Sirdedalot +Sire Edward SireSucks +SirenMan Sirhca Sirius Sirixen +Sirjoshihad2 +Sirkuspelle Sirlagger Sirlightboy Sirmordred44 Sirnuclear +Sirroyce +Sirsa +Sirsteve99 Sirstynkalot Sirswish4 Sirtippy23 +SisiJones Siste +Sit Quietly +Sit xD +Sita Koll +Sita Rama +Sitharii Sithlord Sitinduck Sitt +SiuMan Sivior000 +Six 3 Ohh +Six Dix +Six Kills +Six Seasons +Six Sen6e +SixFootAmigo SixOhFour Sixcess +Sixfoot0001 Sixint Sixpkabs Sixpounders +Sixten106 +Sixthflag Sixty +Sixty N9ne SixtyNine73 +Siynistr Sizashi SizeMan Sizer +Sizzle Cat +Sjaak +Sjak Sjakk +Sjakk Spill Sjappy Sjeb Sjele Sjenjatje Sjenkie +Sjokoladebit Sjoni SjonnieDon +Sjonsen Sjotha Sjulstad99 +Sk Gollum +Sk Scooter +Sk ky +Sk u lly Sk1llzy_RS Sk1ttlz Sk8rgrl474 SkHiCharisma +Skaaddoosh +Skaane Skachoo Skada +Skada N +Skade Skaduw99 +Skaf SkaffeAgent Skaicius Skaikru @@ -20813,69 +43288,124 @@ Skailas Skakkae Skal95 Skanderbeg +Skank Hunt32 +Skarboeblie +Skarking SkarmBliss +Skars Iron Skaryth Skate +Skate Squirt +Skatemyboard +Skater 1299 +SkaterJord SkaterSkillz Skatergod Skaterlegs Skaterune3 +Skaufel +Skcoot +Skedeby Skedsauce Skeeb Skeer +Skeesh +Skeeterstein SkeetlzPopz Skeff Skeggy Skelebral Skelethon +SkeletonSex Skelex Skelnik +Skelpy Skely527 +Skelytom +Skepp +SkeptasMum +Skeptical +SkepticalSol Skere +Skere Bert Skermy Skerp_Perp Skertt Sketch1e +Sketchiin +Sketti Water +Skewp Skezi +Ski Gim +Skiba +Skibidi Tob Skibidibills Skidoodlee SkiemLord Skifree +Skilane Skill +Skill Will +Skill issues +SkillFatigue SkilldSkitzo Skilldriver Skilled +Skilled Boof +Skilled Roy Skiller SkillerC4 +Skillerbabes +Skillersj +Skilless +Skillexi Skillhunter1 Skillian89 Skillius Skilll +Skilllzdan Skilln +Skillpace Skillpadden Skills +Skills Ahoy +Skills Boss +SkillsPets SkillzGainz SkillzLmao Skillza Skillzzz Skilor +Skimer SkinStitches SkinTone5 SkinnedYoshi Skinny +Skinny Mage Skinthix Skinyoualive +SkipTheTask Skipi Skipper996 +SkipperMcgoo SkipperPing Skippy +Skiptutorial +Skito +Skittlz Doc SkitzRs +Skitzad Skitzpatrick +Skizzles +Skj Skjaera Skjeberg Skjelve Skkarpz +Sknnywhteboy Sknor +Sko Birds +SkoalSnus Skodem Skoh Skol @@ -20883,6 +43413,7 @@ Skold Skolder Skolzera SkoobiDooby +Skooier Bibs SkoomaPls Skopix Skopusnik @@ -20892,22 +43423,37 @@ Skorne Skorned Skotten Skov +Skovduen Skovtt +Skox +Skral +Skramlan99 Skreecher Skreeeech +Skreeeech Z Skriptz Skritman Skrl SkroTam +Skroooodge Skrote +Skrrrtle Skrudzas Skruf SkrumpKing Skrychi Skryze +Skubert Skuddar +Skul SkulbIaka Skuldebrev +Skull 2148 +Skull Cove +Skull64 +SkullDemise +SkullFkdNex +SkullFricker SkullTrailYT SkullTricked Skulled @@ -20915,46 +43461,77 @@ Skullhead6 Skullking199 Skullpit Skulls +Skulls Jr +Skumbag Xell Skummi Skummy Skumpy Skundos Skunk +SkunkAsylum +Skunkerinho Skunkieblow +Skwat MD +Skwurtle +Sky BIues +Sky Em +Sky Mages +Sky Satan +Sky VR46 +Sky and Sea +Sky is mine SkyBouncer +SkyBroadband SkyFlyPie SkyKnight +SkyRizzy1 SkySailing SkySkyClover +Skyblownet +Skybussa Skyda SkyeKuro Skyenss +Skygirl Tami Skyleosaurus Skymonster77 Skymore Skynet1188 +Skyom +Skype Call Skyreacher Skyrider Skyrider50 Skyrion993 Skywalkingyo Sl yx +SlGURD SlGlL SlLPH +SlRCUMSlZE Slaats SlabOfCorona Slabs Slackington Slacky +Sladdbarn Slade9100 +Sladist +Slagter Slain +SlainThemis +Slaked Slakito Slakje Slakoth Slam +Slam Daddy Slambo +Slamdabooty +Slamdark Slamer1993 SlammDaddy +SlammalS Slamz Slance Slap @@ -20963,35 +43540,71 @@ SlapShot777 Slapen Slaphead28 Slapmeister +SlappChopped SlappaBogan +SlappeStront Slappenn +Slappers SlappinMango +SlappybagsFC Slaps +Slaps Nuts Slapzinger Slaqk +Slarkan Slash Slasher +Slasher z99 Slasher0708 Slaskepott +Slate Snake +Slats Slaughta +Slaughtered +SlaughtrMeat +Slav Kings Slava Slave Slavish Slavtonio Slay +Slay Addict +Slay More +Slay Or Bust +Slay Pets +Slay R +Slay Tim Slay0rDie Slay3rmate SlayAChicken SlayEeryDay SlayForFame SlayForJoy +SlayImpulses SlayIsMyfame SlaySir +SlayToSkill Slayaholic Slayborhood Slaycation +Slaydenoob Slaydo +Slayem Maul Slayer +Slayer 247 +Slayer 267O +Slayer Azye +Slayer Clues +Slayer Helmz +Slayer King +Slayer L0G +Slayer Mid +Slayer Rome +Slayer Shark +Slayer Task +Slayer XPs +Slayer bond +Slayer n gp Slayer314 Slayer360 Slayer7515 @@ -21000,6 +43613,8 @@ SlayerKingv2 SlayerRyan Slayerburger Slayerdog +Slayerg1g +SlayerisGame Slayerknox Slayerman Slayers @@ -21009,22 +43624,32 @@ Slayhades383 Slayic Slayin SlayinSkills +Slaying Poon SlayingBooty SlayingDave Slayingit14 Slayn +Slayology Slayosaur Slayr Slays SlaysIronman +Slayscaped +Slayter +Slaytr +Slayv Slaywolf Slayyer59 SlayzyDayz +Slck Mark SleanClate SleazySEAL +Sleazyscape Sledgendaddy Sleeep Sleep +Sleep Cycle +Sleep When Sleepercell Sleepgoood Sleepierz @@ -21032,181 +43657,376 @@ Sleepiness Sleeping SleepingCow Sleepinonice +SleeplessC47 +Sleepnaut Sleeps Sleepy +Sleepy Fr0st +Sleepy Hoop +Sleepy Mulli +Sleepy Tired +Sleepy sound SleepyPlantz SleepySus Sleepybear Sleepzy31 Sleet56 Sleete +Sleighbor Sleightyyy +Sleighyour Slemmy Slender SlepinHose +Slepinn Slepping123 +SleppySnek +Sletmar Kets +Slettenbak +Sleuth +Slev711 +Sleve +Slevenderrrr Slewwyy Sleya +Slibbon Slice +Slice Dice85 +Sliced1Bread +Slicer3 0 Sliceseau Slick +Slickslipply +Slicore +Slidecast Slides Slidpanther Slidz +SlieNinja +Slienced +Slievemore +SlihgtyWrong +Slikjee Slim +Slim Gandalf +Slim Paul +Slim Yogurt SlimJD +SlimeShat +Slimey Fish +Slimjim Slimy +Slimy Uim +Slingin Slinkeh Slinky +Slioter +Slipery Peet Slipory SlipperySnek Slise745 Slit Slizzle +Sll8 SlnOfWrath +Slo Slo w th +Sloanee SlobOnMy +Slojsarn Slokei Sloopie Sloothy Sloper +Sloppy Joey +Sloppy WAP +Sloppy Zoot +SloppyGnomes +Sloppyninj Slorkie +Sloshpack +Slotche +Sloth +Slothenly +Slothery Slothhs +Slothly Sloths Slothy SlottedPig +Slough Slow +Slow Down +Slow Spirits +Slow blow +SlowRoaster +Slowky +Slowly Dying Slowpoke SlowrolI +Slowxpgamer Sludgy1 +Slug Kiss +Slugggy +Slugjob Slugr +Slum Village SlumberGoose Slumptality Slurggi +SlurmsMcnzie +Slurmz +SlurpDaTerp Slurpez +SlurpinBrews Slus Slush Slushhy Slushii Slushiiii Slushyy +Slusserbust Sluthra Slutism +Slutzilla Sluwe +Sluwe Odin Slxpz +Sly CHRlS +Sly Guy Matt +Sly Shy Guy +Sly Spyro +SlyPancakes Slyfocs Slyjack Slymax Slypes Slythiren +Slyzuh Sm0keyMcpot +Sm0rc420 +Sm1thyy +Sm6 +Sm8 AJ +Smaarips Smac +Smack Snr +Smacka Fish +Smackatosh +Smacking 0s Smackintoshh Smaeow +Smai Smajli +Smal Iron Small +Small Chief +Small Idea +Small Iron +Small Paul Small3y SmallBlock SmallBrained +SmallPepino +Smallemans +Smalley +Sman Smang +Smart Dog +Smart Foam +Smart One Smartbabe SmarteeRS SmarterMop +Smartfon Smartiest Smartyross +Smash Vials Smashing Smaug SmaugSlayer +Sme Cape Smeared Smecher +Smeeezy Smeegoles +SmegGIM Gr8 Smeggyweggie SmegmaJesus SmegmaL0rd66 Smegmatism +Smegmboy123 +Smekkes Smeklius Smeli0das Smelix3 SmellMyClam +SmellingMill Smelly +Smelly Butt +Smelly Guy +Smelly Kip SmellyGymSox +Smellyjeans Smellypillow Smess +Smetvrees +SmexyBaker +Smezzie SmiTHSaNiTy Smiddels Smiddle Smidjorgen Smii Smil +Smil3r +Smile My Boy SmileBro Smiled +Smilee Smiles +Smiley AK SmileyCyrus +SmileymanTim Smilf +Smiliprophet Smilts +Smimi Smumu SmiqelAngelo +Smirk Smit +Smite Bait Smite4Ags SmiteForAgs +Smited Time +Smites Smith +Smith Inc +Smith a Cat Smith2109 SmithRebirth Smithin +SmithingWhip Smithinz Smithoxmagic Smithy +Smithy NZ Smittyk15 +Smo3 Smoak Smob +Smoel Dicht SmoggyB +Smokahontaz Smoke +Smoke A Bag +Smoke Brb +Smoke J Brb +Smoke Oil Smoke2Fly +SmokeChedFTM +SmokeCheds +SmokeM0B SmokeSocial +SmokeandCum +Smoked Bacon +Smoked Ed 92 Smokedale Smokee SmokeeLoki SmokerOfDank Smokes Smokey +Smokey Eyes Smokey201 +Smokeynutz Smokeynz +Smokiecat +Smokin Clans +Smokin Perks SmokinBlunts SmokinChills Smoking +Smoking Hash SmokingFlax SmoknDReefer Smol +Smol Big Toe +Smol Kupo +Smol Lyra +Smol Pikachu +SmolDeer Smoland +Smolrice Smooooove Smooth +Smooth Draft +SmoothRabbi +Smoothlu Smoothpossum +SmoqueWeed +Smork It +Smoss +Smot Poking Smpli Smuddy Smug +Smug Advice +Smug Grin +Smulknul Smurf +Smurfboard Smurfed Smurfingt0n +Smurfman254 Smurfukas +Smurghilda +Smurky Maart Smurphington +Smush +Smush Things +Smushma SmushyCows +Smuvies +Smuzzle +Smythy Sn0op Sn0rkath420 +Sn0wb4ll Sn1p3 SnYp Snabba +Snack Bar SnackJack +Snackspace Snacktime SnafuPC Snaggapus +Snaghyrnd +SnailNipples Snake +Snake Boss +Snake Jazz SnakeSpec Snakebite37 +Snakebites Snakedeath2 Snakedogbear Snakeling +SnakeskinRag +Snaks Snaky +Snaky Snake SnapMyCarot +Snapa7 +Snapboog1e +Snape Grass +Snapeeh +SnapperSnafu +SnappySplash SnarTheCook +Snarbo +Snarf Snarflaxus Snarfsnah Snarglefox @@ -21214,62 +44034,110 @@ Snarl Snarx SnaszAndrejj Snatchquatch +SnazzyLt Sneak Dissin SneakEnergy SneakKhajit +Sneakbo Sneakee Sneaky +Sneaky Chair +Sneaky IM +Sneaky Shark +Sneaky47 SneakyBaloup SneakyCake SneakyEmu +SneakyFrogg SneakyGnomne SneakyOD SneakyPete SneakyTay +SneakyZoot Sneakymag3 Sneakyvicn Sneakywaffle +Sneakz Snee Sneekerz Sneekey SneekyBeeky +Sneekydied +Sneeuwpoeper Snefnuk +Sneide O_o +Snek zy SnekInMyBewt Snekkerboden Snekling Snekty +Snekty Jr +Snelms Deep Snelmz Snibzy Snickers Snickersbite +Snicklesz Snide +Snide Senpai +Sniff K +Sniff this L +Sniffi +Sniffin 24-7 +Sniffin Bags SniffinBags +SniffingClue Snifflematt SniffmySmoje SniffyMonkey Snike4 Snikepaven Snipe +SnipeOne045 Sniper +Sniperfrank1 Sniping Snipor +SnkyGreninja +Snlly +Snny SnoWorm Snobby +Snobby Elite Snoep +Snollen Snoobsteri +Snoogens +Snookies Snoop +Snoop D9 +SnoopSiah +Snoopfyzle Snoopy Snoot Boops +SnoozeBolton SnoozingBear +Snoper +SnoreLunaLax Snorff1 Snorklarn Snorlax Snorlax9030 +Snorlaxz iLy Snorona Snot +Snotlapje Snow +Snow Day +Snow Poff +SnowBunnyhvn +SnowEmpress6 +SnowManSam +Snowangel18 Snowballerz +Snowbaru Snowclub +Snowdaze Snowearth Snowelle Snowfall @@ -21279,71 +44147,144 @@ Snowiest Snowii Snowmen Snowscythe +Snowsmith43 Snowvof +Snowy Winter Snowy2653 Snowyo26 +Snowys Main SnuSnuShi Snubby +SnugLikeABug Snuge +SnuggleSnail Snugglez +Snugins Snuift +Snuite SnusMumr1ken Snuskig +Snusti +Snuup Snuus Snuuska +Snype_U +So Far To Go +So Flattered +So Inagawa +So Iron BRUH +So Jamiezing +So OSRS +So Quiche +So Warm SoHighhhh +SoLoH DoLoH SoMoist SoSimPol SoSleepy SoStronk SoUhBtw SoVeryInvis +Soaa7 Soad +Soally Soap013 Soaphia +Soapybubble Sobe +Sobe VII Sober SoberFarmer +Sobibor +Sobotka Soburin +Sobzy Socca Soccerc12 Soccermom02 +Soccy SocialAnxty +Socialism SocialistGuy +Sociality +Sock Jesus +Sock Starch +Sock Stealer Socket +Sockks Socks Sockum Socrates Socrates001 +Socratestes Soctch +SodaGrab SodaLambz SodaPopPunk Sodaseg Sodasokwa +Sodd +Sodo Pop Sodobrasil1 +Soecara +SoegLeppel SofaKingHI6H +Sofakingdom Soffachka Sofia +Sofia Cooper +SofiaVergara Sofiero +Sofoni Soft +Soft Chicken Soft Dump +Soft Geeves +Soft Jesus +Soft to Hard +Softboil +Softcorejmac Softer Softest +SoftestFox +Softice SogSteelrock Sogeking Soggy +Soggy Napkin SogxNeutro Sohcahtoa090 Sohh Sohl Sohrac +Soi +Soi Cowboy Soija +Soisox +Soivio Sojuah +Sol Buendia +Sol Heredic +Sol Heretit +Sol Leo +Sol Rock +Sol o +SolTeevo +SolaDuaeManu +Solakoust Solan +Solar Stone +Solar754 +Solarized +Solarrr Solaryohm Solarys +SolasLexeth Sold +Sold GF 4Gp +Sold My Name SoldMyRNG +SoldMyWife SoldUrDad4GP Soldaat Soldaat824 @@ -21352,80 +44293,169 @@ Soldjer Soldtheman Sole226 Solek +Solely Soley Solibiobois Solid +Solid Snack Solid Stache SolidSnape +Solidtag Soliform +Solimanx Solitary +Solkrieg +Sollor +Solmlet Solo +Solo A7X +Solo Aero +Solo Arron +Solo Blitzy +Solo CM +Solo Chumb +Solo Dani +Solo Foxy +Solo Geeber +Solo Gira48 +Solo H3llz +Solo Hayden +Solo Herbo +Solo Idenn +Solo Jawn +Solo Jones +Solo Jord +Solo Kev +Solo Mace +Solo Mus +Solo Road +Solo Romte +Solo Russian +Solo Sieb Solo Sirva +Solo Trojan +Solo Umbreon +Solo Ward +Solo Wind Solo Xenopus +Solo Yoyo +Solo kris +Solo snapper Solo2424 +SoloBandit +SoloBongo SoloCanadian SoloDeicide +SoloDeth SoloDynamix SoloFireFist +SoloFlar SoloFletcher +SoloHotDog +SoloIron30 +SoloMerx SoloMishMosh SoloMission +SoloNotAlone SoloProject SoloRob SoloShow SoloSloop SoloSmackbar SoloSnhaas +SoloSupOnly SoloTibbs Soloable +Solobussy +Solocek +SolohellRat SoloingLife Soloman50 Solomasi +Solomon +Solomon Kane +Solomopp +Solos Turn Solowerkz Soloyo Solsa +Solucki +Solufana Solus +Solus RS Solvent +Solvent less +Soly Handal SomalianRats Somalor +Somavrana Some +Some Pets +Some Ranger +Some Use Some mad dog +Some1youno SomeDirtyOar SomeGoldDust SomeRSIdiot Somix +Somniac One Somnolent +Somoshoho Somppup +Son Goku MF +Son Huntr +Son LeGeND +Son o Rous +Son of Akkha +Son of Hail SonArtorias SonBuns SonIron +SonNamedBort SonOfDecay SonOfGandalf SonOfWright SonVsStepmom +Son_Jo Sonc +Sondey +Sondr Sondra Sonekta Sonett Song +Songs Of +Songsteel Sonhov +Sonia Strumm +Sonic 513 +Sonic Kp3 +SonicYouth Sonicgg1 Sonics +Sonics Alt +Sonidoo Sonjini SonneTeufel +Sonol Sonsofkyuss +Sonx SonyVegas17 Sonycboom SooCrispyy SooUnlucky +Sookadiik Soolo Soon SoonAHusband Soonifer +Soop Pock Soop3rpig SootSpritez Soothe SootyWhale32 +Soph Sophinx Sophlex Sophomaniac @@ -21436,18 +44466,31 @@ Sora Soraaxle Soradin Sorado6 +Sorarpegius Sorbits Sorbosander Sorcere10 Sorcerer5555 SorcererOdin +Sorcerio SorceryFish +Sordnatra +Sore Sorec +Sorenisbad Sorenn +Sorgrum +Sorinvv +Sormeton Sorose Sorry +Sorry Iron +Sorry1mLate +Sorryganster Sortable Sorted +SorthIon +Soruve SosBoerrr Sosig Soskiller6k @@ -21456,131 +44499,244 @@ Sosraid Soss Sossukorva Sossumafia +Sosuke Aizen +Sotamage +Sotetseg Sothe1 +SotonSteve +Sottetseg Soujy Soul +Soul Burger +Soul Scaper +Soul Sleep +Soul v9 SoulEater957 +SoulMadness +SoulOfMidir SoulSteala SoulUnleash +Soulbarrier Soulbearer +Soulcape +Souldia +Souled 0ut +Soulja Lance Soulkilled3 Soulkn +Soulles SoullessMask SoullessWood +Souloh0 Soulololol Soulplay Gee +Souls Mate +SoulsRampart +Soultiller Soulxicution +Sound Soul Soundbar +SoundsOfSoul Soup +SoupEyes +SoupOfTheDay +SoupTheDuck +Soupshi Sour Sourzilla SousChefLuna Sousse South +South Dakota +South Park55 SouthPillar SouthSide Southampton Southenders Southern +Southp0le Souvenierr Souvis +Souvis5 Soux +Sovacam Sovakat Soveth +Sovetskie +Sovi Soviet +Soviet Union Sovryn Sow Love Sowodasoap Sox207 +Soxinder +Soy Duro +Soy Sauce +SoyBhoy SoyJuanEuro SoySoySoySoy Soyez +Soylemagne Soylo +Soz Misclick Sozan Sp00n Sp1cy +Sp1cy Ramen +Sp1cyAvocado +Sp33Dkillz Sp33dy +Sp3c Deck Sp3nC SpARioN SpBongile +Spaar Lampje Spaca Space +Space Bussy +Space Lily +Space Marine +Space Orbs SpaceC +SpaceEnter +SpaceScape SpaceToker Spacealt +SpacedPinata +SpaceeCowboy +Spacejumper0 +Spacing Outt +Spade-e Spadey Spag +SpagBolCol SpagHacked Spaget1111 Spagett Spajina Spalling +Spam Lite SpangeBerb Spangebob Spangl +Spangledbun Spanish +Spanish Dave +SpankFox +Spankies Lit Spanky +Spann Sparacino916 Sparc +Sparc Mac SpardaWallet Spare Spark +SparkRS Sparkles Sparklesbean +Sparky3433 +SparkyD5 Sparkyo +Sparre +Sparta2 +Spartac_us +Spartacus855 SpartanDrgon SpartanSheep SpartanSlick +Sparte Spartin028 Sparty Spasian +Spat Fastic +SpatialMagic +Spattu +Spaustin80 +Spauz Spaynce Spctwm +SpdrBiteJosh Speak Speakerbocks +SpearRue Speat +Speats +Spebi +Spec A Ho +Spec Master +SpecAgent713 Special SpecialBus SpecialGuest SpecialPVM Speciiik +Speckles SpectrlHeist Specz Speechwriter +Speed Colas +Speed Wobble SpeedPony44 +SpeedSouls +Speedalot ak Speedball1 Speede +Speedlund +Speedrun Speedster +Speedy Cd +Speedy Click +Speedy Rulzz Speedy9921 SpeedySpider Speeldoos +Speen Big Speeze SpejsonNM Spek +SpekKas Spektur Spellgoth Spenc +SpenceSuh +Spencee Spenceey Spencer +Spencer O Spencerr Spencerz Spend +Spendlove Spengineer Spennel +Spennel V2 +Spenno 1 +Spensaurus Sper Spermlet Spero Speshal +Speshl +Spesho Spettkaka1 +Spewis Spewler +Spewlie Spezza Sphere Sphinx +Sphinx66 Sphooner Spice +SpicelessJoe SpiceyBoy39 Spici +Spici Boi Spicy +Spicy Noods +Spicy Rahman SpicyMemeGod SpicyMoney SpicyPepe @@ -21588,41 +44744,71 @@ SpicyVitus Spide Spider Spider1357 +SpiderPhenom Spiderhead +Spiderpig Spidersnot8 Spiderw5 +Spiderz 3 SpideyC +Spidoo +Spiering +Spierpijn +Spigniv +Spike05 +SpikesterHC +Spillage +Spillingx Spin911 Spineweilder +Spinkle +Spinnenking Spinnenweb Spinolyp Spirit +Spirit Box +Spirit Cube +Spirit Owner +Spirit Rok +Spirit Sin Spiritcraft Spisek +Spit man SpitfireSR +Spitiz Spizazzy SpizzyMarz Splarf Splarn +Splash LT Splash-8 Splashattak +Splashcarrot Splasher +Splashes Splashley Splashworlds Splasion Splatter300 Spleaner +Splessp +Splezaa SpliceTFY6H Splidge SpliffMaster +Spliffore +Spliiffy Splinta +Splinterhand Splitarellie Splitfaction Sploof +Spluge Splyce Spo0n Spocuch Spodey +Spoice Spoilted Spoka Sponch @@ -21631,17 +44817,36 @@ Sponkz Spoodersussi Spoog Spookachtig +Spookadoodle Spookfish +SpookiBoogi9 +Spooky Beech +Spooky Ramen SpookyCarl SpookyMain Spookyou Spookytoot Spoon +Spoon Full +SpoonFedFred +SpoonFedii +SpoonMePlz +SpoonTracker Spoonay +Spooncera Spoondow Spooned +Spooned Simp +SpoonedBunni +SpoonedNormi +SpoonedWhen +Spoonfed BTW Spoonihomo +Spoonku +Spoonletics Spoonmannn +Spoons +Spoood Spoookems SpoopyDooToo SpoopyNooper @@ -21649,191 +44854,365 @@ Spoorwijk Spooxky Spop Sporer +Sport Leader +Sport425 +Sports Bike +Sportsnut911 Spotifee +Spotmaster 5 SpottedBass Spottednoble SpotterN Spottie SpowSaus +Spr1ditis SprLemonHaze Spraahz Sprattet SprayM0re +SpraynMantis SpreadButter +Spreader Spria Sprice Springer Springii +Sprinty +Spritbilist +Spro max +Sprog Legend +Sprogdor Sprooti Spruit Spry Spubb Spud +Spudalumps Spudge Spudinator Spuge +Spuhcific +Spuhgetti +Spuitopbruid Spunknik SpunkyLlama Spurted +SputtyBTW +Spyder Sin +Spydig Spyike270 +SpykeZim Spykes Spyriano Spyro +Spyro 3 Spyrooooooo Spytech44 +Sq Head Sqe3zy Sqeat Sqiit +Sqix +Sqoub +Sqreech +Sqrwl +Squab Cat Squabs +Squad of one Squadleader +Squaire Squall Squall44444 Squallicious +SquanUK +Squanch Rat Squanchhy Square +Square One Squarebodies +Squat Slav SquatCobbler SquatJogsBro SquatNation Squatting Squaw Squeakes_x +Squeaky Cow +Squeedly +Squeeeegs SqueegeeLord Squeeze +SquidNumber0 SquidSquad +SquidTofu Squidby Squiddle +Squidgling Squidie +Squidler +Squigiglius Squigs +Squigtime +Squinch +Squinch Alt +Squinton Squintts SquintyNinja +Squire Yaper Squirlruler +Squirly69 +Squirrel +Squirrel Pop SquirrelTM Squirreled8 +Squirrely W +Squirt2God +SquirtsAlot SquirtyHersh SquirtyMcD +SquishySir Squonking Sqwalle Sqwarka SqwezMyLemon +Sr Dipper Sr8d +SrBambino SrMick SrMuerte Sraracha +Srelek +Sri Srogi Wujek +Srs SrslyTired SryAFK +Sshscaptain Sshuggi05 +Sssnakepit +St Chrewin +St Liam +St Newman +St eve +St itch +St un +St0kStaartj3 St0ney St0oge St4bU +St4rCh11d +St8hunter +StBasilthGr8 StDecker +Sta Mama StaIemate StaJeOvo Staasi Stab3r +Stabalot +Stabobis Stacii100 Stackdude +Stackey Stackieks Stackin Dosh +StagBeer Stagden Stagmuss StagnantAlt Stagnation Stago +Stahlinski +Stain Master Stak +Stake Me StakeOrQuit +Stakebril Stakens Staker +StakerOhWait Stalactites Stale +Stale Chips +Stale Dough +StaleBagle Stalefloe Staley +Stalifax Stalk +Staller Stalline Stalphie Stamin +Stamina Pot +Stamkoz Stammer +Stampie Stams Stamuhnuh Stan StancedMK Standard +Stanimal Stanimal244 +Stanjuuh Stank +Stank Rat StankBreath +Stankfist Stanley Stanleye Stanlux Staparik +Staparik Lt Stapper6 Star +Star Doctor +Star Say 962 +Star Scourge +Star Spoon +Star zy StarDreamSam StarFell StarGlimmy StarKist +StarSnitcher Starboyyyyy +Starbuckss Starcharts +Starchild Starcry Starfallx +Starfight789 +Starfish +Starjoker8 +Stark Btw +Starlette Starlighte +Starmaker Starmemoria Staropramen Starr Starrlightss Starryfina Stars +Stars Hockey +Starshark +Start Game +Started Late StarvedLlama +Starvi Starwulf +Starzhine Stash +Stashes Stasik25 +Stasik77 Static +Static Peak +Staticshook Statoke StatsisZero Stattelsson Statuhs +Status Bar Statutory Statykk +Statzy +Staubach +Staunch +Staunch_BJD +Stax I Stay +Stay Breezy +Stay Frosty +Stay Hurt +Stay Hustlin +Stay Ready +Stay Salty +Stay Shady +Stay Sic +Stay West +Stay wise +StayFinessed StayPulls +StayPullsBTW +StayThirsty +StayinClassy StaysmallEZ +Ste Gerrard +Ste f SteSkillalt Steady +Steady Loot +Steady Mobn +SteadyFlexin SteadyetiBTW +Steak Ramen +SteakWitWiz +Steaked +StealCutOats +Steals +StealsThings Stealth +Stealth Ownz StealthChop Stealthcy Stealthi Stealthweed +Stealthwolf Stealy Stealy Boi Steam +SteamboatJim +Steamed H4ms +Steamfitting +Steammm +SteamyBuns SteamyCreams Steanox +Steb Stedy Steeam Steebert Steeermy +Steekkha Steel +Steel Gods +Steel Stud +Steel Tarkus +Steel VIK SteelRoxas +Steelbird16 +Steeleos +Steelpan Steen Steenkoe Steezed0ut Steezi Stef +Stef West Stefan StefanLivNo1 +Stefar Stefen Steff SteffenHax Stefo +Stego +Steiger Steikluet +Steinbeck Steinphite Stela +Stelisss Stellacea +Stellamara StellarLG StellarWhey Stellard +Stellas Dad +Stelli StembaWalker Stenfen Stengo @@ -21841,21 +45220,43 @@ Stenicki Stenny Stenuism Step +Step Barrow +Step mummy StepBroHung +StepBroImZuk +StepDabs +Stepbro +Stepbro Paul +Steph Browne +Steph a nee Stephan +Stephand Stephane Stephen9320 StephenMoore Stephenns StephhRS +Steppage Steppaz Steppenwulf +Stepy Stereofuzz Sterlander Sterlington Sterrenstof +Stervolz15 +Stetko +Steum Stev +Stev en Steve +Steve Beanie +Steve Tobs +Steve Tombs +Steve Zissou +Steve ffs +Steve is Pro +Steve07 Steve51 SteveAustin SteveChamp @@ -21864,38 +45265,66 @@ SteveMCOG SteveMerch SteveOwner09 SteveSnow15 +SteveStamos +SteveTheGimp SteveTheMuss Stevee Stevefr3nch Stevemck Stevenrds +Steves Blade Stevet7125 Stevey +Stevie ESQ Stevo +Stevo Lad Stevo29 Stevoguy +Stewge Stexie Stian +Stian Olsen Stian2 Stibby +Stickasaurus +Sticker Stickers Stickman +Stickman Zeb Stickman0011 Stickmeister SticksNbugs Sticky +Sticky Icky +Sticky Nut StickyBeardo +StickyShroom +Sticky_BIBLE +Sticky_Lip Stickypooman +Stickz Alt StierK +Stieren Lul +Stiffies Stiffish +Stifighter X +Stiflers mum +Stigel Stigiam +Stigmaster Stijco +Stijf Stefke Stijin StikSt0f +Stikjob Stil Still +StillANormie +StillCoughin +StillFap2ash StillFarmin StillNoBan +StillNoTBOW StillRemains Stillblazing Stillen @@ -21905,16 +45334,24 @@ Stiltz Stimu Stimulated Stin +Stindebinde StingWisher Stingy Stink +Stink Soep Stinka Stinker Stinks Stinkwiener Stinky +Stinky Adam +Stinky Wench StinkyFatBoy +Stinkyfeat1 +Stinkypooper Stinkywon +Stino33 +Stiorra Stipples StirG29 Stirner @@ -21922,118 +45359,222 @@ Stitcha Stiven117 Stixc Stiznai +StlthyPanda Stnmn Stnyzky StockMyRam +StockOlm +Stocker T +Stockphish +Stocksund Stocktone +Stockyard Stodie Stoel +Stoere Kip +Stoerebos11 +Stoern Stoffer Stoffins +Stoggy188 +Stoic Christ +Stoic Sloth +StoicGod Stoke +StokedMaggot Stolen +Stolen Ego Stolen Grunt Stolen Herbs Stoli +Stoli za Stolid Stolpz Stolte +Stoltzkin +StolzRS +StompaHhh +Stompadile +Stompea +Stomped +Ston3d Arrow Stone StoneDwarf StoneOkami Stoneator Stonebeech Stoned +Stoned Abra +Stoned Sober +StonedGSXR +StonedNormie StonedTTD +StonedTurtle Stonedtime +Stoneplus Stoner +Stoner Morty +Stoner Pov +StonerGod +StonerL0ve +Stonerling Stonesoul15 Stoneyvangel Stonkx +Stony 420 Stoobie Stoogaroni Stooley +Stoolz Stoonly Stoopy +Stoopy Scape +Stoovey Stop +Stop Acts +Stop Mules +Stop Now +Stop StepDad +StopCapping +StopDabs StopDontDoIt +StopStepSis Stopitjoe Storgie Stories Storkie Storm +Storm Monkey +StormFly +Stormlight +Stormmaker98 +Stormy RS Stormzy Storn42 Stortford Story +Story Arc +Story of Man Storybot StoryofPete Storys +Stothelayer Stouse +Stouty +Stovall_9 Stover +Stovete +Stowa Stowty Stox7k +Str Owner07 +Str Takes U Str0ng8ad Str8 +Str8 Maxed Str8backatya Strabz Stradarts +Stradinger Straf Strafe +Strafes +Straffen +Strafi n StraightSimp +Straighter +Straka Stralia +StralianBtw +StrangeChris +Stranger bud Stranger56 +Strangerz Stranges10 Strangler Strap Stratazz +Straton Stratty StratusQc Straubrey Strauss Strav Straven89 +StrawHatMatt +Strawbs +Strawhat01 Straya Strayday Straynaneeee +Streakin +Streammmmmmz +Streammz Streepken419 Street +Street Fever +StreetSweepa +Strefi Stregano Strelitzea StrenIron Strength +Strength Lvl Strengthy43 Strepski Stresset Stretch +Stretch 07 Stretchy Strickend +StrictNein Strictly Striddle +Strideless Strife Strijden Strijder Strikedown +Striker796 Striker8 +Striker8 0 Strikes Strikingvipr +String Benis StringsLogic +Strip Club x +Stripa +Stripgwyn +Stripred +Strive Strix Tactic +Stro Sr Strobax Strocks3 Strocules +Strohs StrokeMuh StrokeMyWand Strokemon StrokmyGroot Stroller StrollerBaby +Stroma Stromboli +Strong Chonk +Strong Left StrongKush Stronger +Strongman613 Strongrune +Strongsad Jr Strongtank11 +Stronkmoscle Stronku +Stroople +Stroppy +Strosity +Stroxers Strr Strubber Strudelis @@ -22044,47 +45585,82 @@ StrydarGrim Strykijzer Stryneguten2 Strytegy +Stu Pid +StuartLittle +Stubo Stud +StudMonster Studderd Student +Student t +Student tort +Study Hours +Stuffe Stuffed +Stuffed Hog Stuffmypanda +StufnDatMufn Stugey Stuggo +StuieShadez Stukatz Stuksken Stumbles +Stunflame +Stunlax +Stunnaz Stunts +StunuuR Stupendous +Stupid My +Stupid Swagg +Stupid444 StupidMagnet +StupidTrader Stupidcoin2 Stupsus +Sturdy Base +Sturdy Wrist +StureStork Stureplan Sturminator3 Stussy Stuxi +Stuzington StvnSmth +Stvx Stxrbursts Stye Style StylesP +Stylistx StyxHatred SuBRifleS SuNnY_AuStiN SuRviVoR SuaNorte Suadela +Suavity +Sub Ironman +Sub Taz +Sub3Marathon SubEntity Sub_Void Subaru +Subaru Bow Subarue Subarus Subatinijo SubiSpeed Subiaco +Subiaco Oval Subie +Subie_rex22 +Subigrl +Subkultured Sublanza Sublimation6 +Submerging Submug Subnautica Subnet @@ -22095,56 +45671,103 @@ SubtleAsnTrt Subtotal Suburu Subwaysurfer +Subwooferman Subwrx +Suc +SuccMyMilk Succeed Successful Succulent Such +Such Mlg Suchislifee Sucjk +Suck At Zuk +Suck my dig +SuckItBrandn SuckMyBot SuckMyDuels SuckTube Suckle +SucksTehSuck SucksToSuck +Sucuk Sudan7a7 +Sudas SudoBash SudoFox +Sudsy Mule +Sudz +Sue Lynder Suede Suedezor +Suemi +Suephoria Suffer Sufferance +Sufferi +Suffering +Suffi Sufflavus +Suffspector Sufwah SugaNoCoffee +Sugab Sugar +Sugar Leafs +Sugar Lily +Sugar STR +Sugar Shilo SugarDaddyNL SugarFr3 +SugarFre +Sugarbunny +Sugaree Sugarly Sugge +Sugma Newt Sugmabum +Sugru Suhado Suhec Suhgundees +SuhhP Suhk +Suhkmedaddy Sui29 +SuiSaii Suikerwafel Suing Suited +Suizy +Sujn +Suket +Sukit Trevek +Sukiti SukkerLyn Sukondikis Sukoru_VIII Sukotto-Sama Sukz +Sulcius +Suldan Serar Sulg Sulliusceps Sully +Sully Bear +Sult an Sultan +SultricMY Sulu34 +Sum +Sum 1 +Sum Tuum Sum41 +SumBeers Sumh Sumin Sumlettuce +Summ Summah Summer Summerson1 @@ -22152,8 +45775,16 @@ Summit Summit603 Summon Summond +Summoneering Sumper1 Sumuinen +SumwanSpeshl +Sun Devi1 +Sun Isukki +Sun Muijja +Sun Riser +Sun Rising +Sun Sioux SunBar SunG0han SunaLAD @@ -22161,34 +45792,84 @@ Sunbite Sunchester Sunda0wner1 Sunday +Sundo +Sundxy SundyWundy SunflowerMan +Sungravel +Sunguinesti +Sunine +Sunky Kong +Sunlust Sunni Sunny +Sunny Boy +Sunny Coast +Sunny Otso +Sunnyi +Sunoric +SunriseEagle +Sunrises +Suns in 2025 SunsShine Sunsa Sunscape6 +Sunset +Sunset Riot +Sunshadow Sunshine +SunshineBus +Sunskit Sunta Sunti Sunuwar Sunyikata +Sunzz Suola Suolane Suolitussari Suomen SuomiKP Suomiprkl +Sup Mike +Sup3r Ziko +SupAndSupply SupDutch Supa +Supa Saper +SupaHottFiya +SupaWarmFire +Supaidahman Supdude Supeerbusy Super +Super 16 +Super Bossy +Super Cinos +Super Cool +Super Duke +Super Fish +Super Fr3ak +Super Katze +Super Tails Super4 +SuperChunk3 +SuperFlow SuperHeroWiz +SuperJoy SuperJuicy +SuperKoi +SuperKriss +SuperMcFresh +SuperMiika +SuperMuffins SuperNJ +SuperNinja0 +SuperPPMan +SuperPochaco SuperScaper7 +SuperSem1 +SuperShane SuperShif SuperT0aster SuperTussu @@ -22198,351 +45879,759 @@ Superb Superbigblnt Superbusy Superdoer +Superdrol 50 Superfire444 +Superguaygix Superior Superjim111 Superjoden +Superkman12 Superkoi3000 Supernate91 Supernatti Supernova Supersam142 +Superstition Superstuffz +Superwarz96 +Superzu 0ne Supo +Suppertmain +Supple Flaps +Suppp Suppression Supra Supra2JZ SupraTurbo +Supragirl94 Supreeme Supreme +Supreme Iron +Supreme NYC SupremeDanz SupremeSpike SupremeTeam +SupremeWoody +Suprie Suprreme Supsep +Supultura +Suq Maddic +SurNtly +Sura Lust +Suraato +Surah An-Nas Suraii Sure SureDeth +Sureal Surfboarder Surg1n Surge SurgeHunter +Suricate Suris +Suriv Surkastunut +Surkee pelaa Surlygrump2 Surok Surrey Suruinen +Surullista +Susan Boyle Suse +Susej Dog Susell +Sushi Cult +Sushi Eater +Sushi Life +Sushi Water +SushiToyota Sushidame Susilapsi +Suspence Suspiria +Susser Tod Susurrous Sutdellen Sutho15 Sutty +Suur L6vi +Suvalkietis Suvorexant Suxe Suzakuin Suzn Suzshenron +Sv +Svampus SvartaOdhner Svartalvheim Sveden Sveitsi +Sveka Sven +Sven med D Svenpai Svenskafyren Sverd Svetta +Svikkipedia +Svinepels +Svisha +Svt500 +Svurt +SvvK +Sw0llenPlums Sw3Frost Swaars +Swabby Swabski Swacked Swadloon +Swaffeldomin Swag +Swag Ponu Swag420 Swagbopeep Swageroneus Swagex +Swagg Goat Swagger +Swagger Pkr +Swaggy Ballz SwaggyMaggee +Swagittarius +Swagohod +Swagomancer Swagslicer Swagturtle Swagunit Swahilson SwamiNate +SwammyHolds5 Swamp +Swamp Crotch +Swamp People Swampy +Swampy Sloth +SwampyAce Swan +SwangleSauce Swanheart Swanney +Swanni D Swanny Swapski Swarm243 Swarme +Swarme d Swarmyard Swatfighter7 Swatson Swaxel +Swe Flame +Swe Fred +Swe Jerry +Sweatiest Xp Sweatscaper Sweaty +Sweaty G0OCH +Sweaty King +Sweaty Nurse +SweatyBeard +SweatyBurger +SweatyMoobs +SweatyScrot SweatySockZz SweatySunday Sweden Swedgeville Swedish +Swedish Fika +Swedish Myth Swedushi Sweensicle +Sweepstakes Sweepyjoe +Sweeqy Sweet +Sweet Boyy +Sweet Dee +Sweet Es Mmm +Sweet Guy 94 +Sweet Pigeon +Sweet Potato +Sweet Vodka +SweetSugR SweetVan420 +Sweetchild0m Sweetermanz Swell Swer Swerve Swerve0311 SwerveJ +Swervy +Swerze Swift +Swift btw Swift738 SwiftCobra08 SwiftSteps Swiftamine +Swiftly546 Swiftmend Swiggitywall SwiggyMcSwig +Swiigs +Swiim Shady +Swiirl Swild0 Swilza Swimfatman +Swimmor908 Swimpa Swine Swingers +Swip3rR +SwipeMyCard Swirly Swirly248 Swishers SwissPigeon +Switch Dropz SwoIe +Swole Milk SwoleBadguy Swolerbear SwoleyGhost +Swolga +Swoli SwollSoul Swollbroham Swolverine Swoofii +Swootz Sword +SwordBoy110 +Swordcode205 Swordied Swordillo3 Swordlord524 Swordman1173 Swordmank Swordmast756 +Swordmother Swords +Sworzis +Swoule +Swown Swtbnd +Swtshrt +Swuido Swurl Swxv +Swyxia +Sxng +Sxrup Sxstyl Sxves +Sy Syaniide Sybe Sybke +Sybr Sycamore +Syche Sycily Syck Memes Sycrem Sycther Syed +Syfer +Syh Syjac Sykeaux Sykes +Sykes Xo +Sykes33 +Sykezer Syliith Sylist +Sylite Sylixx13 Sylosis Sylph Rings Sylth +Sylthrakis +Sylvaria +Sylvee Serum Sylveon700 Sylveonn Sylvian +Sylwia Symb Symba12 Symblic Sympathize Symphonicx Symtai +Syn-er-gy +SynGates07 SynTechRS Synacyde +Synaii Synced +Synchronizer +Synchronous Syncire Syncronia Syncshot Synd +SyndaXatrix Syndalen +Syndicete Syndok Syndra Syndrious Synepxd Synepxo +Synergy Sam Synesthesian Synfidel +Synister9090 +Synizta SynkNZ Synn Synnri +Synoz Synq Syntax +Synthy Syntipukki +Synyster +Sypanite Syphikins Syracusa Syrile Syrilius +Syringe Syrius Syrups Syrus +Syrus Virus +SyrusDaVirus +SysTeM 07 Sysf +Sysfea +Syssla System_Fail +Syte +Syvette +Syzgy +SzechuanJuan +Szenarien +Szethe +Sznd Sztarky +Sztr +Szyrup +Szyther +T 0 0 A S T +T 0 B +T 1 ta n i c +T A B S +T A R O +T Bagmotion +T C 3 +T C J +T D +T E L O +T H C +T H O R M +T IV +T McLeod +T Montana +T Nymphadora +T O M M M Y +T O N N l +T O N Y N Z +T OXI C +T P I E +T R A V +T R U 3 +T S M +T S O M +T Shadow T +T T E X X +T U B M A N +T U R K 96 +T U U M A +T W I S T Y +T W l C E +T a v e r +T alon +T aqn +T emby +T enrin +T h a w +T imboy +T imm +T omahawk +T otem +T otz +T r as h +T rigger +T ripwyre +T rist an +T u m p p i +T ubby +T ylor +T yrr +T-A nina +T-BONE STEAK T-Hugs +T-Lai +T-Rabb T-city +T0 BE FRANK +T00K3N +T00LB0X T00ManyCooks T0AD +T0KEN T0KK +T0M +T0M ATO +T0RB3N +T0RlN T0bbbE +T0ber +T0fi T0ilah +T0lne T0mbak +T0mz +T0oth T0othbrush T0ry +T0tally lll T0vergasje +T1gBits +T1m +T1mmaayy +T2NK T3KT0N +T3T +T3URASTAJA46 T3mu T3vas +T4TE +T4a +T7 +T70TYE T7mon +T8OW +TA Greenie +TA xBravo TAA66 TAARA +TABS1E +TANK ED TANKTOPTIGER TANRfromHS +TARFUII +TARV05 +TATERT1TS04 TB12 +TB3N +TBA Ness +TBA Poppi +TBAC TBNinja TBOW +TBSE Stupid TBSG-Baine TBonFirstCoX TBoneZzzz TBoyd4138 +TC NeverLift TCHAMl TDPred TDRS TDie +TDog +TE Omni +TE-toimisto +TEAMFORTDUDE +TEATMCBRIEF +TEAxBAGGER +TEBA +TEDDl +TEEMUXXD TERMlNATE +TERRORHYPE +TESTOKEIJU +TFS TFreeze +TGCONCEPTION TGDekuTree +TGI Vendredi TGOBS +TGSH TGSpaghettiM +TH0MAS TH0MM0 +TH0TDETECT0R +TH5 +THA CHR0NIC THANIT0 +THANKS D0C THATSCARCASM +THAl LADYB0Y +THC BOOSTED +THC and EXP THCGods +THCiron +THE CH1N0 +THE JEDl +THE MOOR +THE MUUMI +THE TOSH THEHAZE THEIKOS THEST0RM +THEchronic 8 THICC +THICC UIM +THICCCBWANA +THIIIIITH THRALLGOBRRR +THT THUMBTHUCKER TIIIIIIK +TIM BEREN TIMBO TIOTEEE +TITr fishy +TJ UCF TJay +TKO Rage +TKOsh TKfromNC TLT5 TLTBT +TM Riddle +TM8 +TNA INUS +TNDSH +TNF +TNT Stealth TN_Biscuits +TOA Main +TOA Rebuild +TOA3 TOASTA +TOB Inc TOBplank +TOHIGH2FLY TOLIPTSET +TOM RlDDLE TOMMMY +TOMMYSHELBEY TOMMonyzzz +TONNI re mix +TOOlateN0B +TOR0 +TORVA BTW +TPD-Vladik TPGG +TR Ugur +TR0UT CURS0R TR0X +TR3N ABUS3R TR75 +TR9 +TRABZ10 +TRAJANO RD +TRAPH0UZE +TRAPorGTFO +TRAVllS +TRCSup TRESTOLONE TRI0DE TRIPPlE TRUMP +TRUMPbtw +TRUTH OF JFK +TRXeatsRAPTR TRYNAHANGWU +TSA +TSI TSMCharizard TSMsOAZ +TSR Mishiah +TST TSWRX +TSwiftSucks +TT17 TTBtw +TTT TTTSpiceTTT TTTTT TTVCardyUK TTVPandaBear +TTommynator +TTurret +TTyrannical +TULK4S +TURBOPEN59 TURDENATOR TURK +TURKISH HERO TURM0IL22 TVAnime +TWISTED T TWITTERSUPP +TWL +TWO000 +TWlNKE +TX Bonefrog +TX-15 +TXR3 +TYC Beatrice TYCANN TYEY +TYL0RD +TYTYTYYYTTYT +TZTOKHUGEKOK +T_ShelbyLtd T_Swishh +T_apka +Ta C oS +Ta ks +Ta1ntzilla Ta2kaz +Ta7e +Taakxic +Taargus Taathum Taavik6iv +Taavit Tabagie TabascoGrind Tabbed Tabbscoot +Tabby Cat4 +TabbyCat97 Taberknackle Tabesco +Tabiun +TableLamp +Taboo Tim +Tac +Tach +Tachr Tachycardy +TackTick Tacklebox Taco +Taco Bit +Taco Krydder +Taco Log +Taco Paws +TacoCat +TacoKittenz +TacoTimma TacoWithGuac +Tacos Pump Tacotueaday Tactic TacticNoodle Tactical-RSP Tactics +Tactics Ogre Taders +Tadz Taekwon-Do +Taekwondoo +Taelium Taelos +Tafboy Taffarell +Tafff +Tag 7 Tagei Taggeman Tagi +Tagz Tahdeton +Tahdonvoima +Tahfi +Tahimik +Tahm83 +Tahuna Beach +Tahx +Tai +Tai Mai Shuu Taikajim Taikanz Taikapoika +Tail Gory +Tail Raiser Tailight Tails Tailsnake Tainoo1 Taint +TaintFondler +Taintedhappy +Taintehds Tairoun Taiwan Taiyi2 Taizur +Taj Mahballz +Takalaaaa Takaloo Take +Take My Sp3c +TakeARedPill TakeNaps TakeUhSeat Takea12 +Takedown Jr Takeitilslay Takens +Takeout24 Taker Takfil Takimoto +TakingADab Takis Takji +Takobocchi +Taks Taky Talal +Talaxim Talcron +Taleah +TalenteDK Tali Talia Talito Talk +Talkamar TT +TalkingMoose +Tall Greg +Tall Vince TallChair TallPaul24 Talla +Talla Keyali Tallented TallerKiwi Tallink @@ -22551,57 +46640,104 @@ Tally Taloroar101 Talos Talppa +Talrith +Taltt4 Talu Talvedon +Talviel Taly +Talzn +Tam Ranch +Tam The Bae +Tam k0nijn +Tamacti Tamadra Tamaki Tamale +Tamara +Tamaraa +Tamayura Tamber +Tamberi Tame Tamerr +Tamis Tamjam Tamlin Tammii Tamminga +Tammy TampaTHC +Tampered +Tan Toad +TanDumb Tanatos +Tandanus Tanden +Tanduay Rum +Taneesha +Tang Eater Tangar +Tangela +Tangelo T TangerineFly +Tangibility Tangle +Tangle Root +TangleEllis +Tangleboot Tangledroot Tango +Tangshan Tangzu +Tanie +Tanime +Tanis513 +Tanjiro Tank +Tank VS Bear TankMageJon TankProphecy Tankarino Tanked TankedAgain Tanker +Tanker 685 Tanker773 +Tankerton +Tankkimies Tankky +Tanknique69 Tankster360 Tankytank +Tanna Tannnk Tanny Tanoak +Tanoak alt TanqueRamos +TantusV Tantza +Tanuliina Tanz +Tanz Mutagen +TanzFang Tanza Tanzagen TanzerReborn Tanzoo Tanzu Taozi +Tapanui Tapas Tapdaddy Tape Tapir +Tapir Squad Tapirslayer6 Taplop +Taplu +TapoinItteni Tapu Taqi Taradrial @@ -22610,122 +46746,262 @@ Tardysoap Tarezed Taringa Tarki +Tarkista Hv Tarlach Tarns Taro +Taro Buns TaronRS +Taroshik69 +Tarouco Tarpon Tarroo TarzanNinja Tarzzan Tasarorm +Tascar +Tase T Tashee Tashkas 007 TaskMan +Tasset Man Tassoth Tassy +TastefulNote Tasty +Tasty Burger +Tasty Nan TastyBoiMilk TastyKnight TastyToilet Tata Tataa Tatanchis +Tatankaa Tatapie Tatepon Tater +Tatertots Tatimary Tato +Tatorz Tattoo +TattrTots Tatuu +Tau Lord45 +Tau Neutrino +Tau Tau Taucher +TaunkChicken +Tauno Taunos Taurideum Tauros Taut Tautvif Tava +Tava Monster +Tavern slut +Tavernic Tavi Tawa Tawakoni Tawer +Tawhid Tawny +Tax Audit +Tax Wax +Tax Wizard +Taxing +Tay Lore Tay3rell TayMoney Tayleth Taylor Taylor672 TaylorMarcus +Taylort07 Tayluh +Taynq +Tayri Tays +Tayunu Taz762009 +Tazmina90 +Tazner +Tazplan Tazy420 +Tazz2006 +Tazzin +TazzoTezz +Tb knakworst +Tbix +Tbk Tbone5876 Tbow +Tbow Joe +Tbow Todd +TbowCourtois Tbrs6 +Tchambz +TdTapsa +Tdblindmonke Tddun +Tdmiro Tdogg31 Tdurocher +Te +Te Awa +Te x a s +Te zzz TeBroHimself TeCurt TeJay TeMuD +TeQuiL A +Tea Farmer +Tea Witch +Tea n Milk +Tea on Wayne +TeaIe +TeaMerchant +Teaandliquor Teabz Teachan +Teadribble69 +Teafuse Teagan TeagueDaBoss +Teal AV Tealer Team +Team Chubby +Team Flow +Team Rocket +TeamCleaned +TeamJono TeamSoloMid +TeamVaChimpy Teamwork +Teand Tears +Tears of Avo +TearsOfWeezy +Teazor Tebal1 Tebowowns +Tebus +Tec-Grind-95 +Tecc Legacy Tecco +TechCo +TechColor TechContraps +TechFreakTwo +TechOnMaxed +Techart TechiePicker Techmenjoe +Technician Techno177 Techno9 +Techo +Techtonique +Teckczar Teckerz Teckie16 +Tector OSRS +Ted Beneke +Ted Striker +TedRS +Teddii Bear Teddy +Teddy Brum +Teddybareman TeddysMoo +Tedication Tedsticles +Tedua +Tedzudo +TeeBee +TeeBee11 TeeSchaf +TeeTee1772 +Teebo 727 Teegious +Teegzie +Teekiz Teemu +Teemu126 +Teemuz +Teena +Teenagers Teenyduck +Teequoze Teeqy Teeray Teetoh +Tefak Teff +Tefilah TeflonCancer +TeflonJavon TegridyF4rmz +Tegriidy Teh Only God +Teh W H I P +Teh Yumm +TehBigNub TehBriBri +TehKillaaa +TehPum TehShowerMan +Tehebow Tehh +Teigur Teittinen +Teivanna Teixo Tejmaster +Tekannan +Teke Toucher +Tekkenfury Tekkies +Tekkies nub Tekknow Tekkuza Teknoid Tekoflex +Tekryael +TekstPlekshT Teksti-TV666 +Tektiny +Tektom Tektonio Tektons TektonsTaint +Tektos +Tel3 Telboy Teledogs Telee +Teleport 125 +Teleportoise TelesBehindU +Telesh69 +Tellum Telluric +Telope +TemBROross +Temdom Temeria +Temmer +Temmie TempVVS +Tempal2 Tempest +Tempesta1 +Tempick Templaris Temple Templooit @@ -22734,177 +47010,477 @@ Tempoctrl Temponazz TemporaryBls Temppuliina +TempstRimuru Tempthric Tempz +Ten Letters TenOnTheFlop TenPieceNug +TenPly Bud Tenacious +Tender Nuts Tenderrrrr Tendinosis TendoTheTux +Tendulkun +Tenebri TenebrisMeam +Tenenwasser Tenereus Tenga Tenh1s Tenhou Tennis +Tennis Socks TennisLad +Tennnessee +Tennu Tennysee Tenorman Tenraikash1 +TenryuuKaiNi +Tensilean Tensor +Tensor Trace +Tentacle +Tentpolepie Tenya Teotl +Tep3lstreel Tepeksi +Tepezki +Teplan +Tepoa Tepponen Teqila Teqq TeraLokien +TeraVit Teras Terbleg Terial117 Tering +Tering Tiete Term Termite Termiz TermnaLcpL Termoil Tero +TerpWrangler Terpedout +Terpily +Terppa1775 TerpySlurpy TerraToffey +TerraTony TerresFatum +Terrible Edd +Terro Terror +Terror Earth +TerrorJaxx Terrorise Terroristi Terry +Terry Munro +Terry61RS Terrybear Terva Tes Iron Tesaticles +Tesco Teserve +Tesla bot TeslaDiva +TeslaHero +Tesni +Tessei Tesseria +Tessies Bits Test +Test Dummy +Test Strip TestStrip Testate TesticularCa +Testikeln +Testoepa +Testsubject TetYun +Tete3 0 Tetragrams +Tetrah Blue Tetsu +Tetsu Nurtaw +Tetsu Steel Tetsu2 Tetsunohigan Tettekop +Tettezotteke Teurastamo Teus Teus777 Tev0 +Tevreden Tewocp +Tewty Tewwer +Tex Zen TexanzOS Texas +Texas Hou +TexasAggie TexasPlayer +Texasholdems +Texastea2 Texman Text Texx Teyrill +Teyzr +Tezyn Tflo +Tfue Tfulkyou +TgMofo +Th Abigor +Th0m +Th3 K1ng P1n +Th3 Wolf Th3IronMan Th3KiNG +Th3KiNG_Paul +Th3Tool +Th3Villager +Th3_DoN Th3uns +ThAngelSlayr ThEDievolved +ThSheerman +Tha Bser +Tha Crazy L +Tha Decided ThaDankantor ThaDragonSM +ThaGiz ThaLawl +ThaNewArcher +ThaRealRambo ThaStepBro ThaaMunchies +ThaaOne Thaerokem Thai +Thai Girl +Thai ler Thaichili Thalarios ThaliN1 Thamasta47 Thameslink ThanaWee +ThanatosRise Thangkang Thanked Thanks +Thanks Jeans +Thanks4Pet +Thankz Mom +Thano +Thanos btw ThanosIsLife Tharendel Tharic +Tharin +Tharok +Tharrogant +Thasos That +That Noob +That RNG ThatBoiii ThatBoyBurly +ThatDamAss ThatFishhGuy +ThatGuyGoob ThatGuyJordy +ThatLipGrip ThatLuck +ThatManBez ThatOldskool +ThatOlmlet +ThatOneAsian ThatSandNoob ThatSickBoi +Thatonesock Thats +Thats Gang +Thats Not PC +Thats Thicc ThatsNotRite +Thaumat +Thaurison Thav022 +Thawk410 +The 0ld Nite +The 0xymoron +The 1 liquid +The 11th +The 2nd GIM +The 3rd Main +The 90s +The Actuary +The Aegis +The Aod +The Apina +The Atreus +The BPO +The Baad Man +The Big Chum +The Bleez +The Blue Owl +The Blyat +The Bonk +The Booger +The Boys +The Brawler +The Broskie +The Bubbsy +The Buffalo +The Cage +The Catowl +The Champy +The Chopper +The Cleaned +The Cleaning +The Coffin +The Comeup The Crogamer +The Crows +The Dabbler +The Danny +The Dark +The Dark165 +The Data Guy +The Debated +The Decided +The Deli +The Diamond +The Dink +The Dipshit +The Dothraki +The DrNick +The Dragona +The Dre +The DripLord +The Duffman +The DwOrfe +The Echo +The Eco +The Effected +The Em8 +The End +The Engine +The Ex Zerkr +The Expanse +The Fat Toad +The Fe Woman +The Fig +The Fisher +The Fugitive +The Gas Tank +The Ginga +The Giznooch +The Grouch +The Grower +The Guppy +The HRE +The Half Man +The Harambae +The Havok +The Hibbs +The Hivemind The Hobo +The Hoffner +The Hundred +The Hunter +The I Am +The Iron Cpt The Iron Era +The Is0lated +The Jedi Way +The King 023 +The Kiwi +The Labfreak +The Lager +The Last Act +The Latvian +The Law 98 +The Locust +The Logger +The Long Day +The Lope +The Lord Ra +The Lovers +The Lurifax +The MCG +The Magic +The Maiden +The Marco +The Maskara +The Matth +The Mediator +The Midlands +The Mks +The Mouldy +The Mr Spec +The Murder21 +The Muscles +The Nexian +The Nicollai +The Noob +The OSU +The Office +The Old Fonz +The Old Kite +The Old Mike +The Omun +The Onceler +The Only Sin +The OnlyPyro +The Paladin +The Peak Pro +The Pet Farm +The Playoffs +The Pocket +The Proline +The Prophet +The Ptolemy +The Pwnes +The Qwinner +The Real Cat +The Sabre5 +The Sarge +The Schnopps +The Sea Bee +The Seahawks +The Serval +The Shy Guy +The Shy Oni +The Sly Fox +The Snail34 +The Snapback +The Steele +The Steward +The Stranger +The Surveyor +The Tardis +The Thanator +The Tils +The Tiny Dog +The Trap +The Triple T +The Use +The Victory +The W0rst +The Wael +The Warp +The Wraith +The Wupp +The keho +The thin 1ce +The-Wind-Up The0G The1 +The1_2watch +The1stmage +The3dge The3rdOlive +The3rdTrike The888 TheAdzz TheAirIsDead TheAlbatross TheAllSorts TheApe +TheArcheType +TheArchthief +TheAsic TheAssailant +TheAusSpade TheAvenger56 TheAvgJon TheAzimuth TheBandit777 TheBassIsRaw +TheBazaBrown TheBean TheBearJ3w +TheBeltMan TheBezal TheBidness +TheBigShield TheBigZofNYC +TheBlackest TheBlindy +TheBlueShore +TheBlueWrath TheBoltzy TheBoomfire TheBopp10 TheBotReaper TheBowJob +TheBrain +TheBranFlake TheBrundone TheBudWiser +TheC0W +TheCanada TheCapist +TheCarrotMan TheCaseAce TheCheezywiz +TheChosnOnes TheCokeFiend TheCollected TheCondemned TheCorrupt TheCuckening +TheCzarnian TheDaedalus TheDalek TheDampBush +TheDangs TheDankShow TheDawg +TheDayWalker TheDayman TheDeadMann +TheDeadTeam TheDeen TheDisgusten TheDog +TheDoubee TheDreamKing TheDrips +TheDry TheDuckChris +TheDuckDaddy TheDucksNut TheDuud TheDyr61 +TheEricShaun TheEstonian +TheEvaElfie TheEvlManRay +TheExtracted +TheF0rg0ten9 TheF1ash TheFabDabber +TheFallen1x TheFeOdyssey +TheFeres TheFizzCC TheFlammers TheFlopyTaco @@ -22916,51 +47492,78 @@ TheFunkyHomo TheFunnyLove TheFuzzball TheGaGee +TheGaryy TheGiggleMan TheGlawce +TheGodFathxr TheGodGuthix TheGodfather +TheGoodLife TheGoonie TheGordinfla +TheGoryGlory TheGr8Jimbo TheGrainGoat TheGreat +TheGreat One TheGreatThor TheGreenBowl TheGugguru +TheGurrag +TheHabduL TheHackedOne +TheHapa TheHartstopr TheHerbSack +TheHuffDaddy +TheHugLife TheHungOne TheHungRoid +TheHydra69 TheInilator +TheIronBarra +TheIronBoy TheIronDolan +TheIronHoser +TheIronMouse TheIronTwist TheIronVault TheIronZoid TheIsamaru +TheJele TheJosephe +TheKappaCorn TheKhun TheKid TheKillerB TheKnight TheKnightman TheKolector +TheKop +TheLaggyDad TheLampKing +TheLastTheef +TheLaxBrah TheLazyNinja TheLewhole TheLionn TheMaadKing TheMachine39 TheMadWolf +TheMainZeus TheMamba TheManInBush +TheManJordo TheManatee +TheMaskie TheMavrick TheMaxPvMer TheMayne +TheMetaNow TheMikkel +TheMorloc8 TheMuel +TheMuffin8or TheMursk TheNegative TheNerve @@ -22968,47 +47571,80 @@ TheNewLue220 TheNewMonkey TheNexu TheNinjaH0b0 +TheNoPurp +TheNooby +TheOG Logo TheOGGrimm +TheOGslacker +TheOSRSWiki +TheOllieBoi TheOlmlet +TheOne772 TheOneMatrix TheOperative ThePTWY +ThePaceAce ThePardos +ThePariah +ThePerfect G +ThePolak +ThePraetors ThePrenti +ThePrestiege +ThePrideS1n TheProfess0r TheProvider ThePureRingR TheRanger +TheRealBean TheRealBew TheRealDest TheRealIdean TheRealKanye +TheRealKush +TheRealKyle TheRealKyle9 TheRealMidus TheRealShway TheRedNas +TheRedRaider TheRevRip +TheRewriter +TheRobin129 TheRoulette TheRsBug TheSaggyOne +TheSaltyYew +TheSandFoxx TheShadyMile TheShyFn TheSimpSonny TheSinner TheSkippyBoy +TheSlim1 +TheSneakyOne TheSoggyOne +TheSoloHades +TheSpaceSaus TheStonedElf +TheSwumpMan +TheTKsmith TheTankProd TheTerug +TheTimeLord TheTinPeach +TheToyMaster TheTree7 +TheTrue Goku TheTrueNorth +TheTrueOOGA TheTrueSatan TheTruthOnly TheUnbeloved TheUndified TheUnluckyIM TheValuable +TheVerve TheVeryBest TheVnom TheVoodoo2 @@ -23016,313 +47652,603 @@ TheW1tcher TheWerebear TheWetDuck TheWhlteWolf +TheWiseLoner TheWitcherr TheWizaad TheWrongName +TheYahtzee TheYak +TheYimYim TheYugo TheZoracks TheZurvan The_Dave666 The_Dunster +The_Eoline The_Hillboy The_Jimmy +The_Krang +The_Man146 +The_Sturg The_Zob +Thea1a Theatres Thebano +Thebig76 Thecascade +TheclawMVP Theconn Thedriesj11 +Thedyolf +Thee Khed TheeMohican TheeSkill +Theel Theem Theeweaver Theez +Theezak Thefunto Theguymann Thejessman1 ThelAvent +Thelastmane +Thelegend4uk +Thelmacat342 Thelvereas ThemanwhoisB Themenchman Thengalin Theoatrix +Theodensa +Theodora605 Theohhhh Theoklitos Theoneburger Theophobia +Theorized +Theory Theoryist +Thepawgchamp Thepiefour +Theracords +Theralion +TherapyGroup +Theravasa ThereTheyre Therealhook Therens1 +Therer Thermynator Theruler333 Thery Thesaurusus +These +Thesonicking +Thespok Theunfrgiven Thew Thewoodle They TheyTukMyJob +TheyXciteMe +Theynika +Thgll Thibaut Thibi +Thic Glizzy ThicBudget +ThicCreature ThicKoontang Thicc +Thicc Aku +Thicc Budget +Thicc Fil A +Thicc Flair +Thicc Momma ThiccBird91 +ThiccCowboys ThiccDaddyXL ThiccDonut +ThiccQueen ThiccSkips ThiccZwans Thiccapedia Thick +Thick Cut +Thick Nick +Thick Red +Thick nun Thick2g Thick4Head +ThickGlute +ThickIronBum +ThickMike ThickSenpai ThickSpak +Thickenei Thickest Thickkmommy Thics +Thiery Thies Thiesen +Thievette ThievinKills ThievingL +Thievs Thigh Thighhighs ThiiComplex +Thiibaut Thillam +ThinBlueL1ne ThinPeepoSad ThinkB4Hit Thinkoclet +Thinxo Third +Third-ages +ThirdAge ThirdAgeBoss ThirdEye Thirdborn +Thirsty 4PvM +Thirtys This +This Gimp +This Leo +This Schmuck ThisAint +ThisAint-Wow ThisAintSkil +ThisGuySkip ThisPieIsDry Thisious +Thissa Thlrd Thoakline +Thocasu Thogdad +Thogidar +Thohon Thom Thomarse Thomas +Thomas Juice ThomasticIM +Thomastic_1 +Thombstone +ThomiusTeGr8 Thommetje +Thommyy Thonack Thonq Thoomin Thor Thoradin +Thoraldd ThoraxPurple Thordej +Thorgal +Thorgoth1 Thorkar96 +Thorn Thornet Thornnforge +ThorntonM Thorvesta +Thot Jadiels Thotalopolis Thoth +Thotmince48 Thotscape +Thoughting +Thoughtseize Thounde Thoupeppi Thrasmion +Thrax OS +Three Twelve ThreeOneNine +Threemars +Threesunders +Threkeld Threno ThreshDaOg Thrihyrne Thrilbo +Thrilerrr Thrillhousee +Thrisel Thrivaldi Thrlll Throat +ThrobGodTod Throbba Throbbing Thrombi +Thromur +Throupled +ThrownFury +Throxx Thru +Thru ur poo ThruDaStorm Thrust Thrustaxe1 Thueh Thug +Thug bone4 Thugbug808 Thugg +Thugge ThugsBunny +Thugsbunny73 Thulean Thumb ThumbBwana +Thumper +Thunadaja +ThundaBear ThundaJunk +Thundac Thundahcatz4 Thunder Dog Thunder Gate +Thunder Nerd +Thunder Zeus ThunderBirdz ThunderRolts +Thunderbo1tz Thundercat Thunderite +Thunderoxgod Thunderpb28 +Thunderst0rm +Thundito +Thur go Thurbs Thurison Thusly Thutmose +Thuvian Thuzd Thve1ivan +Thwart +Thy Odama +Thy Victory ThyIronGiant +ThyLegend ThyVonR +Thybo Thyclops Thyhead +Thyming +Thyreus +Thys Thysa Thyymabotnus +Ti Blade TiXN +Tia Tiaan Tiaeuth +Tiafoe +TiagoM Tiak +Tian Guo +Tianzi Tiazen +Tibadis Tibador +Tibaul +Tibbsyy +Tiberium SvK +Tiboot +Tic Fart +TicImperfect TicTacSensei Ticano Tice300 Ticina Tick +Tick Behind +Tick Ma Nip +Tick Manips TickAteUrMom TickTickRun Tickable +TicketGoblin Tickets +Tickflow +TicklMySickl TickleBerry +TicklesIM Tickmark Ticks +Ticks missed Tict Tictacdingus +Tid Eez Tidders Tiddy +Tiddy Winks TiddyLactate Tidev Tidy Tiedemanns +Tiedustelija +Tiegra Tielemans Tier +Tier 05 Tierney +Tierra Bella +Tiesto +TifaL123 Tiffs Tiftanlar +Tig Bittty TigTheWelder +Tigas TT Tiger +Tiger Tea +Tiger Trap +TigerYouDied +Tigerheart07 Tigerheart09 Tigerlady Tigerlady203 Tigerr Tigersrule23 Tigerwolf +TiggoGnomes +Tiggrat +Tighe Tight +Tight Helmet +TightSpace42 +Tigor +TigreRosso Tigrio +Tigy +Tiiimon +Tiimari Tiistai Tiistia +Tiit Hepa Tiivo Tijmen Tijn040 Tijs Tijskid Tijuude +Tiki Haha TikiTyrant Tikk1s +Tikka +Tikkix Tikru Tiktok +Tikwah +Tila Tilburg +Tild0 +Tilfreds +Tilidin +Till Bored Tillah +TillerPloww Tillykke Tilted +Tilted I Am +TiltedGoblin +TiltedIM Tilur +Tim Pedwar +Tim Puri +Tim The Jedi +Tim bo Slice +Tim-O-thy +TimShutDown TimSkilling +TimTheLegend +Timaaaay +Timaaay +TimbaWimba Timbeettius Timber +Timbertail Timbito Timboball +Timbuktu25 +Timbulz Time +Time For Me +Time Leap +Time Voyager Time2Lose1 TimeFlies +TimeIsStrnge TimeLion TimeMuffins +TimeSink2000 +TimeSpan TimeZebra +TimedxBeast Timespacing Timetokill19 Timew8ster Timex +Timex 07 Timka Timkempp Timm Timmay111865 Timmeh Timmies +Timmuuhh Timmy +Timmy Jim +Timmy Tbow +Timmy Tiime TimmysCoffee TimnI2 +Timonkey Timos TimosTime +Timotej Timsey +Timzee +TinFoil Joe TinHongetech +Tincoinco Tincup +Tindatinn Tindell23 +Tinder lvl 1 TinderMatch Tine Tinfawn TinfoiledHat Tinfoilhat +TingSumWong TingleTingle +TingleUwU Tingot +Tingsha Tink Tink200345 +Tinkelsia +Tinmanone +TinnMan +Tinnitus Tinsmith +Tinted Rock Tintti218 +Tinuvial +Tinvicuna Tiny Tiny Bagel +Tiny Buddha +Tiny Bun +Tiny Dck +Tiny Feet +Tiny Lego +Tiny Secrets +Tiny Teemo +Tiny Triceps TinyFnRick +TinyIronDong TinyLebowski +TinyLes +TinyTaro TinyToasters TinymafaRick Tinypns +Tinytiger17 Tinzo +Tip Zee +Tip of Dik TipTheTank +TipeF Tipeeee Tipit +Tipoz Tipper +Tippin_toes +Tips Iron +Tips Touched +Tipsy PvMer TipsyBeard +TiptopSundae Tipu Tiqu +Tiques TiramisuTart +Tire Slayer Tired +Tired Hero +Tired of IRL TiredPidgeon +Tirex Tiring TirmenaT TironTula Tironade +Tirpz +Tirsonek Tisalia Tisch +Tism Tanner +Tit Bow TitMcghee TitPoker Titan +Titan Luke TitaniteSlab +Titanium Mag +Titas P TitePoire Title +Title Fight Titsferdayz Tittsnbiches +Tittyboi5 Titus +Titus Furius +Tivaaa Tivinter +Tizra +Tizzcdn +Tj Russo +Tj Watt +Tj0epert +Tjaa Tjabalabaaa +Tjalo Tjar Tjarie +Tjarles Tjbakel +Tjf12 +Tjob TjockaBengt +Tjs109 Tjuv Tkit Tksquad Tktn +TlCK LOST +TlLLER +TlLT +TlME 2 QUlT +TlNUS +TlTANlC Tliltocatl TmSmT Tman Tmarvy +Tmilllz +Tmm +Tmmm Tmoe Tmoe123 +Tmoneyyyy123 +Tmppa +Tmtiger16 +Tnt Harder +To Ashes +To Be Sure +ToAPlanker +ToBeAgile +ToLoNi +ToMyTailFin +ToNFisKrs07 ToTheRanch +Toad Pond +ToadKar TV Toas20 Toast ToastBTW @@ -23335,125 +48261,239 @@ Toasterly Toastie Toasty Toat +Tob Braidy +Tob Carvery +Tob Marley +TobOnMyCox +TobSpoon69 +Tobak +Tobbeloba Tobias TobiasFate +Tobiasz Toboogan3 Tobser Toby +Toby Raz3 +Toby1889 TobyMcCrier +TobyRax +TodWhispers +Todays N00B Toddlet Toddo25 +Todt Thot +Toe Biden +Toe Crocs +Toe Moss +ToeRag +Toedeloe Toedels +Toeh5 Toek +Toekie +Toeristje +Toermalijn +Toes B4 Bros Toets Toews Toffenboi Toffer_99 +Toffffu +Toffoli Tofs4pk +Tofthagen Tofu +Tofu Python +Tog +Toge6343 +Togepi +Togica +Togo Mouri +Tohni Tohveli Toilet +Toilet Humor ToiletBowlbb +Toiletpaper9 Toimin +Toiney Toinzy Toivo_43 Tojosodope +Tok in +Tok-xik-Hex TokHaar Tokah Toke +TokeSevere Tokedaddy Toker11 Tokin +Tokin Ranarr Tokin99 TokkHaar Tokkie01 +Tokonu +Tokoya Tokoya11 +Toktz-ma-cox Tokyo +Tokyo Ghost +Tokyo Prose +Toldasor +Tolhuis ToljaSo +Tolo Ar Nin +Tolweg +Tom Adamo +Tom Cx +Tom Decoene Tom Fn Brady +Tom Is Huge +Tom Shanks +Tom T +Tom Vercetti +Tom Waited +Tom btw +Tom from 561 +Tom is Sharp +Tom o_0 +Tom vs Log Tom9 TomAce +TomFlinn7 TomHilRigour TomMazilian TomMerrilin TomOfTheWest TomTehCat Toma +TomaMvp +Tomaatti169 Tomarti Tomastor TomatoAndEgg +TomatoFarm19 TomatoTom9 Tomazon +Tomb +TombLooter +Tomba Tombalo Tombat Tombazv2 Tombea09 +Tombing Tomdabom +Tomdoc14 +Tome TomehhG TomiL Tomiee Tomik85 +Tomlyn Tomm TommieSalami +Tommm Tommmo Tommy +Tommy 901 +Tommy J C Tommy2Tick TommyGunn204 TommyJay TommyTalapia Tommyhawk Tommyyy +Tomn Tomo Tomori Tomorrowlxnd Tompi +Tompp1 Tompsi Toms +Toms PvM Tomsdk Tomson177 Tomtastrophe Tomtom032 Tomukas +Tomvdh Tomxi +TomzodoubleO +Tond3 TondeK18 Tone +Toneez Tonester03 Tonfa Tong Tongo +Tongue Baths Toni Tonicto +Tonk A Wiz Tonka742 +Tonkade TonkatsuLife +TonkerEx Tonnie Tony +Tony D +Tony Gwynn +Tony P +Tony Soap +Tony Soprano +Tony Tuna Tony23 TonyCaawk Tonyde Tonydidles Tonyhood Tonzaww +Too Original TooBasic TooBigDad +TooManyCooks +TooManyKinks TooMuchIan +TooMuchSauce TooMuchTuna TooReal TooShredded +TooWhite4You Toobias +ToogaTank Tooheys Tookkul +TookyDaWooky +Tool Toolbox +Tools1977 ToomBooii Toomas +Toomi Toonic Tooodley Tooomo Tooq +Tooqan Toortles Toostie Tooterz +ToothhurtyPM Tooves +Top Gear +Top Glock Top Milk +Top Monents +Top Mong +Top Trends +Top V1 +Top Vestain +Top10 Top5Worst TopGlitch TopGunt @@ -23463,34 +48503,58 @@ Topez Topgolf Topi Topkeklethal +Topkerel Topman Toppavenger Topstad TopsyTurve +Tor Btw +Tor Cool Guy +TorBlueJays +Torag Tony Torags +Torags The C Torchbringer +Torchfall Torchiclover Torchpix +Tordenknold Tordue Toreador Toreransu +Torgonis Tori Torille +Torille btw Toris Torkoal +Torky Bow +Torlux +Torm TormentingU +Tormood +Tornaddyne +Tornado Kim TornadoGang TornadoShit Torned Tornjak TornoDB +Torok Toronto TorontoOVO Torr3nHunt3r Torra +TorraTwo +Torretto +Torrfly +Torrud Torsinclair Torso +Torstol +Torstol Todd Tortanium +Tortcher Tortelini Tortew TortiIIa @@ -23498,36 +48562,68 @@ TortillaChip Torttunaama TortugaBooga Tortugas +Tortuous +Torture Iron +Torva boy Torvee Torvesta +Toseki Tosetti +Toshiba +Tossin Tostada +Tot1 Total +Total Lvl Total Pede +Total Spoof +Total Vanity +Total Zero Totaldumm Totaled3 Totalis +Totallymad20 +Totalxq +Totato Tote +Totemas Totnum +Tott +Totti +Tottie Toucan Toucann +Touch My Wii +Touch Tablet +Touch Touch TouchPinis TouchedByXp Touchkin Touchmydig Touchpad +TougeAttack Tough Tounii +Tour Guide Tourino Tournx72 Tousart Tove Towely +Tower Guard TowerOfGod Towerbros Town +Town Square +Towney Stark +Towton II Toxic +Toxic Dice Toxic Emre +Toxic Joda +Toxic Mfer +Toxic Outlaw +Toxic Waltz Toxic017 Toxic125 ToxicBropipe @@ -23535,12 +48631,22 @@ ToxicDroPipe ToxicKenny ToxicSimp ToxicWaster +Toxzeek +Toy Chest Toycutter Toyger Toyne Toyocoma ToysRusK1d Toysalami +TozzinSalads +Tpc Chris +Tpc Jimmy +Tpc Ken +Tqnks +Tqrb +Tr Farmer +Tr hoca Tr0gdor Tr1ckyD1cky Trabelco @@ -23548,85 +48654,164 @@ Trac Trace Tracing Trackpad +Tracktix Trackzor +Tracto r +Tractorjoe13 +Tracxy Trad Trade +Trade Me 70k +Trade Parade +TradeForItem TradeMeBro TradeMeUWont +Tradebarrier Tradeophobia Trae47 +Traenalai +Trage Gast Tragick +Tragon33X +Trail +Trail Sodas +Train Track +Traincore Trained Fish Trainer +Trainer Bad Trainin +TrainingDay TrainingDays +TrainingWill +Trainor BTW Trains Traiths +Trakiya Traktori Traktorman Tralan +Tralfamadori Tramayne Tramfix Trample +TranSfused Trance +Trance Heals +Trance666 TranquilGod +TranquilHaze Tranquillia Transfer Transgressor +Transpiler Transpose Tranziztance Trap +Trap Carrot +Trap the Cat +Trap-A-Holic TrapGdReptar TrapGood93 Trap_Capo Trapking +Trapking 8 +Trapping Trapski Trasclart Trash +Trash Pvmer +TrashBlast +TrashManJ0hn +TrashServers Trashu2 +Trashua Trashy Traumahh Travee Traveler Travis +Travis 42 +Travis on Rs Travis473 TravisThott Travish Travor TravviePatty +Travy D Law +Traxic Traxxed +Trayvon King Trazaeth +Trazez +Trazza001 Trebluh Trebyzond +Tredderss Tree +Tree Form +Tree Oils +Tree43210 Tree50 TreeNut11 +TreeTopsFart +TreeWeasel +Treedemption +Treehuggers Treelo23 Treenut Treinen +Treio Trejoracine Trekhoar +Treldinn +Trem Bao Uai +TremensInc Tremorx00 +Tremzy +Tren Culture +Tren Hex TrenbolonAce +Trench Ben Trendeon +Trendiness Trenl Trennel7 Treno Trensational +Trentovitch Trentt Trepa Trepador Treps Tresemmee Trev +Trev the dog +Trevenant Trevo Trevor +Trevor Died +Trevor M +Trewg +Trews Trey +Trey is Treygor +Treyvor +Trezler +Trgx2 +Tri Flamingo +Tri-P0LAR Tri9py_J TriBalanced +TriFlea Tribe +Tribe Leader +Tribe of 123 +Tribryd26 Trick +Trick Blue +Trick Statue Trick-demon TrickRoom Trickiac @@ -23636,11 +48821,15 @@ Trickster122 Tricomb Trictagon1 Trictagon2 +Tricx +Trid3nt Trieuce Triforce13 Trigamy +TriggaTriggs Triggadd Triggahappy +Trigger Me TriggeredMot Triggeredm3 Triggering @@ -23650,22 +48839,44 @@ TrikiRiki TrikyCutworm Trikzed Tril +Trilipe Trilligy +Trillogy Trillotani +Trilogies TrilogyXO Trim +Trim Jr +TrimmedGrimm Trimmedguy TrinitySauce Trinix Trio +Trio MF Trip +Trip Machine +Trip Masta +TripEatIRL +TripJaw +TripSquad Tripachu +Tripae Triple +Triple Deuce +Triple Dex +Triple U TripleBeans +TripleHyphen +TripleNeck Triplet +Tripod Neb TripodDog +Trippie Damo Trippinsac +TrippleMarty Trippy +Trippy Mind +Trippy Troll TrippyReefer TrippyScapee TrippyTony @@ -23673,78 +48884,155 @@ Trips TripssAcid TrisomyMumky Triss123456 +Trissee TristV1 Tristann +Trito +Triton Blue +TritonSaber Triumph Trivi Beast Trivit Trivium Trixcet Trizak +Trizepz Trldude7 TrocSan +Trocko4 TrodOnLego Troetelbeer Trogbite +Trojan Steed Trok +Trolerage +Troll Chad +Troll464 TrolleVV TrolletTruls +Trollevv +Trollface +Trollheimusk +Trolli TrollinPony TrollinTony +Trollinguy +Trollzzy Trololosaur Tromal +Trombalski +TronixxIM +Tronkshark Tronse +TroopIronman Trooperke Tropec TrophieTyler Tropical97 +Tropicaux +Tropidelics Tropsic Troskals Tross Trottero Trottington +Troulis180 Trounced TrousrMonstr +Trout Wallet +Trovam +Trovo +Troxicus +Troy Buckle +TroyPolamalu +Trreezz Trrrpfosdss +Tru3Iron +Trublians Truce TruckTruck +TruckYacht +TruckerLiam +TruckerTuck TruckersLife +Trucki +Truckstop0 True +True Flex +True Joker +True Knight +True Owl +True Repent +True Tones TrueBadApple TrueBank +TrueNorth95 +TrueSatan TrueTech TrueTeller77 +TrueYoshi Truegreed Trueplaya +Truers Trueth Trulieve Truly +Truly Lifted +Truly Loving TrulyForever +Trump TrumpCard TrumpSuxAss Trumpet +Trundholm Trunker Truno Trunsa +Trusejageren TrustIssues +TrustNoOne Trusted Trustifarian +Trustin +TrustyThrust +Truth Hurtts +Truth Seekir +Truxy One +TrveKvlt +Try Casual +Try Die Cry +Try Hard Jr Try2IronMan TryAltF4 +TryCBD TryHard +TryHard DBag TryHardi Tryactin +TrygveLegend Tryh4rder Tryhard +TryinNot2Die +Trym +TrymeTrick +Tryna Max +Tryna match +Tryndaflex77 Trynottodie2 Trypophobia Tryptamind Tryptopane Tryuumph +Trzaskowski +Ts Danne +Ts Me +TsMaxed Tsakahele Tsar +Tsar Douglas Tsarina Tschinelas +Tshotz Tsiquli Tsitika Tsjok @@ -23758,27 +49046,42 @@ Tsudo TsukasaS TsukiAkuma Tsukihi +TsukikoBaka Tsukiya Tsuku +Tsuku yomi Tsukuyomi Tsumikitty +Tsumoso +Tsurubebi Tsyphoid Ttffdd Ttoz TuNxZbs Tubbless +Tubbzzy +Tube Dood021 Tubmasta95 +Tubs Tubz Tuca +Tucker Jeb Tuckerajf +TudoLaDentro Tuerro Tuexo Tufan Tuffa Tufs +TugBoatWilly +TugMeTwice +TugMyCox +Tuga9 Tugboat Tugboats +Tuii Tuisku +Tuittu Tukeldaja Tukkairti Tulf @@ -23786,20 +49089,37 @@ Tulip Tulipssonmyd Tully03 Tulppu +Tumbdownlog TumbleDore +TumblingSand +Tumeken Tay +TumekenToday +Tumma Paahto +Tumms +Tumnus Tumppe Tuna +Tuna Juice +Tuna Shuffle Tunaking420 +Tunasafarii Tunda TunderBog Tundra +Tunez Tung +Tung Fu Rue Tungsten +TungstenGyro +Tunguska +Tunkky Tunnellord Tunppii Tunsberg Tuntun +Tuoppi1230 TupacShaakur +Tupackid Tupakki Tupeli Tuperrovski @@ -23807,97 +49127,188 @@ Tupla Olut Tuplaa Tupoopsa Tuppu +Tuppu hoitaa +Tuppuu +Turambarr TurangaNui +Turb0uu Turbanator Turbie +Turbin Turbo +Turbo IM +Turbo Junkie +Turbo Toes +Turbo Zero TurboMilf +TurboSoak +TurboTez TurboWet Turbokjepp +Turbotymer +TurdFlicker TurdFurgeson Tured Turha Turiak +Turjilin +Turk Monsta Turk3H +Turk3HH TurkBird +TurkeyPro +Turkije +Turkish One Turkish3agle Turkled Turkos06 Turks Turn +Turn It Left TurnMagic +Turnalar Turner Coach Turnii Turnt +Turqish +Turqy Turri Turrner Turrox Turskaa Turso +Turssuttaja +Turtelloo Turtle +Turtle Rak +Turtle s Turtle7 +TurtleCoddlr TurtleWurdle Turtlebutt +Turtledog Turtleliest +TurtlesClimb TurtlesRdank Turtleso3o +Turts +Turuii +Turvasana Tusc +Tushy Taker +Tusk Tusondude25 Tusseladd92 +Tustea Kossu +Tutorial Tutoroo +Tutta Tutter TuttiFruttii +Tuttimango Tuttimelon Tuuri +Tuuri haukka Tuvisitt +Tux Tuxy Tuya Tuzle +Tvanderlaan1 +Tvb Cx +Tw0Pack Tw1ZzT +Tw1nsPurr +Tw1nz +Tw1st3d_B0W Tw1stedBow TwTv Twald10 Twas +Twas Xmas +Twashua Twaste +Tweaky +Twee Barkie Tweeder Tweek +Tweekzor Tweetart Tweeznap +Tweezr TweezyShadow Twelvyy +Twenie Wan Twerk +Twerk 132 Twet Twice +Twice Flo TwickerTweet Twiddle +Twiddle Twix +Twidgets +Twiested +Twift Twigbert +Twigglet TwiggyC Twigler Twigster Twiisted Twilight2326 TwilightPony +Twilly Spree +Twillz Twin +Twin Fists +Twin Kinz +Twin Peaks Twinflip +Twinick Twink +Twink Ripper Twinkle +Twinkle Park +Twinklekat Twinr0va Twins +Twist2K Twist3d Twist3dData Twisted +Twisted Boog +Twisted Bung +Twisted Cook +Twisted Echo +Twisted Jam +Twisted Matt +Twisted Titt +Twisted cat +Twisted garg TwistedAegis +TwistedBeer +TwistedBerns +TwistedBowlz TwistedBr0 TwistedCybrg TwistedGuard TwistedHeart +TwistedLike TwistedOffer TwistedWally Twisted_Ry +Twisted_newf TwistedxAura +Twister Nips +Twister XIII Twistertjeee +Twistie TwistsedT Twitch +Twitch Fear +Twitch simp +Twitch507 TwitchFear TwitchSeljan Twitchen004 @@ -23905,220 +49316,491 @@ Twitchin TwixTM Twizler74 Twizzlers88 +Twnkles Twntythree23 +Two Elites +Two Fears +Two Ounces +Two2SixToo TwoBeerBuzz TwoDigitJish TwoDogs TwoInTheSink TwoLegedDog TwoShue +TwoTwentyTwo +Twoconch TwojaStara +Twoy Twpz Twstd Twum +Tx2 +Tx3 Poseidon +TxNock +Txbor Txfr Txga +Txh +Txlon +Txture +TxunaTuna Txyus +Ty +Ty God +Ty Sit Idiot +Ty bears Ty1er Ty4F +TyDyPooFingr +TySkidmore23 Tybear575 Tyberium +Tybones Tycen +Tycens Tydigidy Tydollatree TyeMeUp Tyelca Tyepo +Tyfr Tyfus +Tyfus Bende +Tyfus Mug Tyfuslija Tyga +Tygr +Tyhger Tyin Tyixx +Tyjes1 Tykaman +Tyl r Tyler +Tyler Razz +Tyler Stone Tyler051095 +Tyler4rs +TylerGBR +TylerMike Tylerknight3 Tylerton +TylerxBandit +Tylo54 Tylooor Tylz2 Tym8 +Tyney +Tyngre Tyom Tyontaja +TypOneg4tive Typhose Typical Typisch +Typto +Typtooka +Tyq +Tyr 24 +Tyr Ara Tyra Tyrael +Tyrael OG Tyran88bid +Tyraniana Tyranids TyrannicaI Tyrants Tyrep +Tyrex Tyro Tyrus Tysh Tyskie +Tyskie38 Tyskn Tysn +Tyson11 Tysonn Tyst +Tysterisk +Tytastic Tythle +Tytto Tywonia +Tz-Kek-Twang Tz-Ket-Kush TzCal TzCok +TzCok-Hard TzDeez +TzDeez-Nuts TzHaar +TzHaar Meej +TzHaar-Doug TzJal TzKal +TzKal Majora +TzKal-AszZuk +TzKal-Cumsok +TzKal-Gio +TzKal-Mike +TzKal-Thad +TzKal-Zuky TzKalFatkok TzKalSuk TzKarl +TzSuk-Dis2 TzTok +TzTok Chris TzTok-1gBud +TzTok-Fart +TzTok-Flame +TzTok-Izzy +TzTok-Jaffa +TzTok-Jahd TzTok-Jeffy TzTok-Joka +TzTok-Kekw +TzTok-KetKok TzTok-Ladz +TzTokTitties Tzek +Tzhaar Bower +TzhaarThicc +Tzhaar_PvP Tzharzh +Tziis Tzikit +Tzkal Edgar +Tzkal Tygo +Tzkal-Reborn +Tzok-GigaKok Tzoski +Tztok Shaz Tztok-Met-Al +Tzuyuwu +U A E +U A V Online U Ded Boi +U Mirin Brah U N X +U R Lame +U Tele Nub +U W8 +U n I f Y +U nknown +U0Q U0sunpeh +U3 +U4 +U71Q +UAWMAN UB02 +UBWare UBaKr UConn UENDELIG +UFOTurtle UFOs +UG Juppa UGLYMONKEY58 UGLYS UGam3zOS +UI GOKUU +UI UC +UIM BUTT3RS +UIM Brah +UIM Burni +UIM Chayula +UIM Illusive +UIM Liar +UIM Lobotomy +UIM Log +UIM Loki +UIM Nathanjb +UIM Ori +UIM Paperbag UIM Pepper +UIM Pidbull +UIM Shen +UIM Shrift +UIM Sorrows +UIM Spongie +UIM Stephan UIM Thor +UIM Vas +UIM Warriorh +UIM Wedey +UIM Yoga +UIM Zoldyck +UIM whozan +UIM7 +UIMBerg +UIMaqtpai +UIMatti +UIMpostor +UIPanda +UIdahoKush +UIspice +UKB0b449 UKnowItsB +UL7RA +ULF Tagger ULTMA ULTRA +UN-FAZED UNBIQUOUS UNC0RN UNCEL UNCLE +UNCLE LEET +UNCLESAMY +UNDEAD EXO +UNDERURBED4 UNEX1ST UNH0IY UNLOADED999 +UPDOGS +UPSdeliveree +UQV +UR 0 HP LMAO +URA Noob URAMESHl URSS +US Postal +USA Tyler +USA USA USA +USA is Dev1l USAF USAO USBthe2th USMARINEHYDE +USNavyOver70 USSpaceForce USTreasury +USirHaveLost USirHaveWon +UTT +UWCB +UWF +UWUSTELIJA +UZY VS JAD Ualt +Uamee Ubar Ubaru Uber Uber Logan +Uber Yeats Uberamazing +Ubersmind +Ubicorn +Ubu +Uccino Uchiwa +Uchr Udacity +Uderp Udhariol2 Udingus +Ufda +Uffe Persson UgliestIncel Ugly +Ugly Hipster +UglyFishArm Uglybeetle27 Uglyyo93 UgranDag +Ugursuz IT Uh-0h Uhbove UhhhBoneless +Uhhhh Wut +Uhm Uhscended +Uidi One +Uim Beyonce +Uim IRL also +Uim Zuko UimSian +Uimakoulu +Uk Bristol +Uki Kukkamaa +Uki Skillz Ukko +Ukko-Pekka +Ukkonenn +Uknow Yunho UknowPotter Ukonvasara +Ulappa +Ulibarri +Ulik madiq +Ulillillia Uliss Ulizius +Ullerton UltDrewes +UltRise Ultebor +Ulthane120 Ultima +Ultimat3ly Ultimate +Ultimate Low +UltimateH0bo UltimateSami +UltimateWare +UltimateZe Ultist Ultistic +Ultorman Ultra +Ultra Miami +Ultra Primal +Ultra Sloth +Ultra Space +Ultra Teuz +UltraGOOP UltraJack UltrasTomi +Ulvhilde Ulyanyx UmUUmuUmU +Umarra Umbr +Umbrah Umea Umek Umiland +Ummfufu +Ummz +Un Dutchable +Un M-U-T-3-D +Un puma +Un-Expected UnDutchable +UnGoof UnHoLyxMaTTy +UnOrderly +UnRuleD +UnTaMed X +Una999 Unacceptab1e +Unaclogger +Unaided Unass1sted Unassisted Unavailable Unbacked +Unbann me Unbiased +UnboundLeaf Unbreakable Unc1e +UncJo Uncaged1776 UncagedOne Uncandled Uncel +Uncel Ben +Unchunk Man Uncle +Uncle Exci +Uncle Julien +Uncle Rocho +Uncle Solo +Uncle Somnus +Uncle THC +Uncle Trippy +UncleBigBob1 +UncleCuckle UncleDaddiii +UncleGuy UncleSlappy1 +Unclear +Unclesam137 Uncode UncomfyPants Uncommon Uncooker +Uncool Gary +Uncr3at1ve Uncut Uncy Duncy Und3r0ath Undead UndeadElk333 +UndeadYenny Undeadd Undefeated +Undelivered Undeniable Under UnderExiled +Underaged Undercatt Underlogged Underoos +Underrs +Understars Understated Underverse Undine Undoubtful +Undra +UndrgrndSalt Undulaatti94 Unemati02 +Unemployed Unequalized Uneven +Uneven Mango +Unexposed Unfair Unfearful +Unfergetable +Unfi +Unfollowing Unfriended +Unfunno +Ung Ungolianty Unhappy +Unhapytuna Unhealthy UnhingedE Unho +Unholy Bains +Unholy Cult UnholyAbyss Unholybucket +Uni Mike +UniQ +Unicat Unicorn Unids Unii +Unik +Unimaginary +Unimander Unintended +Union Dixie +Uniqlorn Unique +Unique Am I Unit +Unit Tests United +UnitedLeeds Uniteds +Unity 3D Universe Unkh +UnkindPastry UnkindledTwo Unknown UnknownBeing @@ -24127,158 +49809,353 @@ UnknownValue Unknownchuck UnkoPlayer Unkoly +Unkownkiller +Unlash Unlds +UnlimitedHC +Unlit Sky +Unlock Death +Unluckerdile Unluckers Unlucky +Unlucky Jord +Unlucky lmp +UnluckyNGay +Unlugy +Unluigi Unmasked Unmaxed Unmerkable Unmoist Unnerving Unohdettu2 +Unomia +UnorthodoxGF Unorthodoxfo +Unown397 Unprofitable +Unread +UnrealGecko +Unrecord +Unreliab1e Unrot Unruliest Unsafest Unsainted +Unsavior Unscuff +Unscythed Unseen +Unshaven Cat +UnstopFork Unstrung +Unsubscribed Unsung Untameable +Unthinkable Until +Until Dawn +UntrimCraft Untrimmed +Unus Divinus +Unv +Unwiii Unzkiboi +Uoziz +Uozu +Up N Ur Mom +Up ya mom jr +UpBad +UpNorthCha UpRoaRs UpThaSaints Upeo +Upi Uploading Upluk +Upper Four +Uppercuts +Uppotukki Upriser Uprising Uproot Upsi +Upthe1rons Uptime +Ur Exp 2 Me +Ur Obsession +Ur a baish UrASalmon UrBabyzDaddy +UrBoyBilbo +UrDadsLov3r UrJustXpToMe UrMomLvedIt UrNansMan UrPureSucks UrScr3wed +UrSuchaShita +UrWifeLuvzMe +UrYe UrZoggy +Ura Juanker +Uragaan Dude Urakas Urakkapallo +Urallia +Uran ium Uranus UrbanMerza Urbdayy +Urbn Urdead Urea Urek +Urekzera +Urfe +Urheiluiatka Urheilujatka +UricOddball Urkchar +Urked Urkerhard Urock16 +Uross +Urotsuki +Urpokarhu +Urri +Urs +Ursa UrsaOmega +Urskog Urthron +Uru p +UsainBloat +Usb Doe Tin +Usb Flies +Use +Use Tongue +Use2bHC UseToBeGood Useable +Usecsythang UsedApplePie +UsedLube +UsedRubbers Useless +Useless Main User +User 27 UserApproved +Useranme Usos Ussin +UsualAntZ Usva +Utahime +Utahn Utareita Utca Utini Utis Utsuwu Utter +Utter Pleb Utvisa Uunijutsku Uunipelti +Uuo +Uus kaust Uuti3 +UwU Leo +UwU Noctis +UwU Otaku UxXwpasdiioa +Uzin Uzot +UzrielBoi Uzunar +V 3 +V 9 +V A K U +V A L O R +V A M 0 S +V A N D E R +V Bros +V E F +V E H +V G +V GK +V Gamemaniac +V L A D Y +V Lestat V +V NL +V Nichushkin +V OO D 00 +V R I L +V e c n a +V endetta +V ergetend +V ezi +V i 1 e +V r o l ij k +V the Victim +V-43 +V-EuSoto +V-SaTanjiro9 +V-Tek +V-olRagnarok V043 +V0F +V0WZ V0XA +V1BER V2int5 V3NQM +V3XY V3lnias V3n3natis +V3rtigo btw +V43 V4SKI V4sia +V5C 2 +VAIDUOKL1S +VALH0WLA +VALHA LL A VALK0 VALORANTJETT +VAMPYRlC +VANlLLA RUM +VB TINNS VB24PK +VBoss +VBsec +VDB Niffooo VDHG VEDA VEGANDIET +VEN0M13 +VENNY MOCKER +VERYBANANNA +VET DMaZ +VHS or DVD +VIAL1 +VIE T +VIII +VIIVII +VIKING0 +VILIONKKAA VLEERMUlS +VODKANATOR +VODs VOIVID VOREVERAIONV VORKl +VOlDWAKER +VP N1ck +VPSxSam VPixels VRScotty +VS0P VS367 VUNDA VVDance VVJuul +VVS1 VVStoner +VVade VVanderer VVarden +VVeems +VVhite0ut VViggle +VVilson +VVinni +VVintage VVona VVoods +VW Crafter Va1ynx Vaal Vaalbara9 Vaalberg Vaandah +Vaca Preta +Vacant V Vache +Vache Verte Vad3 Vader Vado Vaealin +Vaelleruen +Vaelte Peter Vafan +Vafthruthnir +VagAngler +Vagabond +Vagina Bad +Vahagis +Vahagn Vahidil Vahlyte +Vahn +Vaikuttava Vailokas Vain Vainis Vaishe +Vaisu VaitkiS Vaizki Vajengo +Vakstu +Val Rex +Val3ntlne +ValOnMyChest Vala Valadrak +Valarfax Valaron Valdevon Valdomiro B +Valdyra Valendale +Valentijn +ValentinaLuv Valete ValgeHunt09 ValheraUK Valhk +Valiant Nite +Validde Valiente +Valienton Valiiim Valiralith +Valirion Valivill Valknir +Valkore +ValkyraeS1MP +Valkyrie btw +Valkyrie xo ValkyrieNora Vall Valliance +Valliate +Vallies Vallk Valluu Valmar +Valmora Valo +Valo Ville Valo247 Valor ValorantJohn +Valorate Valorisatie Valorise Valorpoint @@ -24288,10 +50165,17 @@ Valverdi Valxn Valzar Valzor +Vam pire Vamo Vampeodia +Vampire Bob +Vampirehunt Vampiress Vampurr +Vampyire +Vampza +Van Cold +Van Hellsing VanDarkhome VanHeisma Vanaic @@ -24300,79 +50184,154 @@ Vandahl Vandaine Vandalize Vandalized +Vanderhek +Vanderstorm +Vandery Vandetto Vandmand Vandorann Vanek +Vanek-26 Vang Vanh0 VanhaKettu Vanhal000 +Vanilla Best +VanillaBum VanillaDonut +VanillaFlow VanillaSwirl +Vanillawaifu Vanity +Vanity Fair +VanityNugett +VanityRS +Vanityyh Vanja +Vanja M +Vanki +Vannara +Vanskid Vanss Vantiron Vanupimphi Vape99 VapeMonster +VapeNGapeLLC Vapeape1 Vaperan +Vapid H VapinTiger +Vaping Cloud +Vaporion Vaporized +Vapsjeeee +Var Laslore +Varamyr +Vardorfister +VardorvisSux +Vardovish +Varduka +Varenagan +Vargen96 +Vargo +Vargrmoon Variabulls Varixed +Varlanazz +Varlot4 Varm +Varm Kaffe Varnilla VarockVirgin +Varonom +Varpu +Varradero +Varro Varrock +Varrok Obama Varroq +VarrrokObama Varsa Varsii +Varthon Varulven Varxas Varz +Vas R Vasar23 Vasd Vasdeffernce Vaskapotti Vaskekort Vasquez +Vassaa +Vassago0111 +Vassal +Vastrakal +Vastuuvapaus Vasuki Vasyliev +Vatenkeist Vatix Vauderus Vaull +Vault Hunter +VaultTecs +Vautumn +Vaux +Vava471 Vaveti +VawnHeuf Vaxx +Vaxxil +Vaxyr VayQ Vayda Vaynon98 Vaz0r +Vazier Vazoo +Vb Panther Vbiqve +VeKnow +VeZuu Veas Vector +Vedam Veddunreal Vedroulian +Veecal Veeena +Veekkuu +Veerpalu Veersnof Veetu76 Vefsn +Vegabond Vegakargdon Vegan +VeganFemboy VeganVibes Veganstho Vegard Vegas +Vegas Gunman +Vegas Mike +Vege-Mauri Vegeetta Vegeta +Vegeta MF Vegetah +Vegetas Veng Vegetunks +Veggie Mate Veghan +Vegitation Vegito +Vegito Meta Vegolse +Vehicle Tech Vehms Vehru Vehtamin @@ -24382,205 +50341,416 @@ Veinin VeitiKKa Vekie Vekuuu +Velaynx Velbain +Veld Velegro Velek Velgreed +Velhote Veli +Veli Iron +Velikan Veliki +Velite12 +Velkennar Velkija Velli Velmir +Velociraptor +Veloxrapt0r Velreth +Veltsi +Velvetgunner +Velvsy +Velzun +Vemba Venado Vendall2 +Vender Venderik Vendet27 +Vendum +Venemies Venenatis +Venerate Venereology Venetsia +Venfour Veng +Veng BTW +Veng Me Not +Veng Waster VengDeezNutz Venganza +VengeMeDaddy Vengeance013 VengeanceTR Vengeancen Vengeful +Venizar +Venkeltje +Vennythizer Vennyv99 Venom +Venom Vegeta Venom00 VenomTears +Venomousbite +Venomxkillz +Venous Cobra +Venpu +Ventia Ventile +Ventril0qist +Venus Nyan +Venzdroid Venze +Venzy +Veo s Veos +Verac Obama +Veracs Veracthus +Veraen Veratyr +Verbac Verbal +Verbal Kint +VerbalIrony +Verbia Verbo Verche Verdantys +Verdoemd Verdux Vereco Verelya +Vereoris +Vergi Drakan +Veri Eze +Vericity +Verify Verin +Verissimum Veritasium Verity +Verix Verjj Verkyz +Verliax +Vermachelen +Vermeill +Vermithrax91 +Vermont Iron +Vermyapyre +Vern29 +VernalTDevil +Vernon +Vernossiel +Vernyxitas +Vernz1337 Verokostaja +Veromnis +Verrario Verrtus +Verruckt VersGrind +Versacce VersaceGuap +VersaceSofa Versalix Versatio Versily +Vertigo 2 +Vertsu1 +Vervyyy Verweel VerxaRS Very +Very AFK +Very Typical VeryAvgRNG VeryGoodRNG +VeryLarry VeryLilRng Veryloo Verysharp988 +Verywarm2246 +Veryx +Verzicky Verzik +Verzik BTW +VerzikDaCuck +Verzika Verzy +Verzy Werzy Vesal Vesaris Vesipiisami Vesku Vesley +Vespina Vespulia Vesqu Vesryn +Vessim Vest +Vesta 1000 Veste Vestergaard +Vestorius Vesture +Vesunna +Vetala +Vetem VeteranGamer +Vetilation +Vetinari37 +Vetionarian +Vetr Skaoi +VettePolle +Vex Viper +Vex Virus Vex8 Vexare +Vexed Viper +Vexeed +Vexer07 Vexero Vexers +Vexflame Vexing Vexinity Vexrip +Vexstrom Veylantz Veyron Veysel +VezTa Vezka +Vezon +VgbndUnicorn ViIlageIdiot +ViaCarter Vial +Viallinen Viat +Vib3Ch3ck3r Vib8 Vibby Vibe +VibeCentral +Vibeke Gar +Vibeology +Vibes Check VibesTooWavy +Vicardi +Viccuri Vicente1111 +Vicenza 173 Vices +Vicious Dest +ViciousPawg Vickies Vicky VictheStud +Victimised Victor +Victor Dogg +Victor Lim VictorHo +Victorize Victorp75 Victoryw Victreebel +Victur Vida Vidacks +Viddii +Video Gamic +Videogam3r +Vidlmao Vidy Vidz Viech +Viema Vienas Viera22 +Viesker Viesty Vietnamees View +View Bot View0 ViezNegertje +Vieze Jongen Viggi +Vigi V Vigilamus +Vigly Viguro Vii23 +ViiPV ViiViiVii Viiduus Viiiral +Viikonloppu Viiksi-Vallu ViinaGoblin Viinakramppi ViisYsiKuus +Vijand Vijay +VikSC Vikat VikeSkol Vikerne666 +VikiLord Viking +Viking Dad +Viking768 +VikingKnees Vikingfe +VikkiVance +Viklok Vikram Viktor +Viktor Wins VilainLutin Vilbeee Vile +Vile Arcane +Vile Cabbage +Vile Squid Vileblood Vilemaw +Viliant Vilke +Villagers +Villain Dude +VillainLife Villanovaguy Villanovan Ville Ville921 +VilleGallle Villix Villllu +Villosa +Villrix Vilnis Vilty Vilunki Vimpsen Vims +Vin 08 +Vin B +Vin Vista +Vinaegre +Vinbum43 +VinceBennett +VinceOfMince Vincen Vincent +Vincent D2 VincentDaMan +Vincentimetr +Vinceut Vinchops +Vindi IM +Vindruen +Vindruva +Vinh y +Vinish Vinkmaster1 Vinland +Vinloxx +Vinn28 +VinnFrazz Vinneh Vinnie +Vinnie Dabs +Vinnie Pazz Vinnie526 Vinny +Vinny NZ +Vinny Speedy +Vinny Verac +Vinny-G +Vinnyaldo Vinoloog Vinopenkki Vinostondis Vinous VinsanityGG Vintage +Vintages Vintner +Vinxe +Vinxion x Violas Violent +ViolentPudd +ViolentToxin ViolentWaves Violetti +Violon +VipStar Viper +Viper Aurora +Viper G40 VirZuk Viral +Virbatum Virbliud +Virelith +Virgin Creep VirginGirl +VirginHunteh +VirginUwU +Virginism +Viriato VirtRemnants Virtaheepo Virtuaalnuss +Virtual +VirtualAhri Virtuart Virtuous Virunypel Virus +Virus LSSZ +Virus Soup +Viruss ViruzTehNub +Virzik VisagePlease +Visarin +Viscera Viscx Visdom Vishno +Vishnu Visibly Visigothic Visine Vision +Viskan +VismaBlet +Vister Vistopherson VisuallyMatt Viswiel Vita VitaLemonTea VitaMineralz +Vital Dude +Vital Hope +Vitality +Vitamin See +VitaminCnote +Vithark Vito Vitor Vitreous @@ -24588,260 +50758,533 @@ Vitrified Vitruvio2 Vitryssen Viturbio +Viturscy Viva +Viva La Vida +Viva Mehico VivaLaWeegee Vivalask8r Vivalla Vivants +Vivascape VividAzura VividDreamss +Vivido +Vivij +Vivk +VivziePop +Vixca Viyrew Vize Senpai +Vizima +Viziyo +Vjee +Vk VlBZ +VlGGAN VlNTER +VlRAL +VlVID VlaamsePlank Vlad +VladTheBwana +VladThePaler Vlada Vladek284 Vladi Vladibjoern Vladictorian +Vlaendren Vlambare Vlast1n +Vlncent Vloxx +VnG Lynds +VnG Zenyte +Vnce VngH +VnilaGorilla +Vo Amice VoHiYo_Nami Vobia Vocaloida +Vodbi Vodec Vodka +Vodka ice VodkaBarrage +VodkaBreath VodkaPlz Vodke Voekus Voetbalkous +Vogefur Vogues +Vogven Void +Void Fanatic +Void XVII +Void-Cho VoidMySoul +VoidOnyx22 VoidWraith Voidberg Voidnight Voidpaw +Voidrow Voidseeker +Voidwaker op Voittosumma Vokon +VolProMan Volai Volantis Volary +Volblaffen +Volc Volcan +Volcance Volcanos +Volco Volcwinder Voldesad Volgos Volkert +Volkie Volkrah Volkzy Volmortt Volrod Volrum +Volt +Volt OSRS +Volt268 +Voltimolt Voltz Tzkek Volucris +Volunteer Volux +Volzo Vomiting +Vomiting Cat +Vompiainen Vomuao +Vomure +Von Beck +Von Dylan 2 +Von Locke +Von Reibnitz VonThaine Vonbony Vonderhaar +Vondoom Voneirus +Vonhinten Vono +VonoV +Vonschatten +Vonsv Vonty VooLis VoodooCells Voodookie Voorheees Vopi +Vor The Ape VorGole Vorare +Vorarlberg +Vorcan +Vorikar Vork +Vork Planker VorkathsMate Vorki VorkiAlt Vorkscaping +Voroth Vorpal Vorpeo +Vorsamu Vorschlag Vorso Vortob4 +VosOc +Voss V2 Vossen +Vosty Voted4Kanye +Vovi +Vox Whoppa +VoxMachina Voxna Vozion Vpdz +Vrauri Vrayl Vreaper Vref +Vrekked Vriendschap Vriix +Vrijer +Vrillionaire +Vroeg VroomMasheen Vrzn +Vsian Vsmoke +Vsnn Vt Flavourss +Vt99 Vuallis +Vubbe +Vud Vueko Vukodlak +Vuku Doll Vulcan Vulcant +VulcunLogik Vule Vuleka +VulfRS +Vulia +Vulklet +Vulm +Vulo Lives Vulp Vulpes +Vulpes Audax +Vuohi Vurx +Vurzik +Vus Vusa +Vuto +Vutox +Vuuln Vuur Vuuututututu +VvM Otter +Vxmm +Vxus Vyagruhh +Vyaraeaen Vyaza Vyby +Vycarious Vycos +Vyluxian Vymera Vynlx +Vyrelady Em Vyrza Vysaraine Vyseri +Vytauts +Vyukris +Vzb Vzla +Vzr +W 0 R D +W A G M I +W A G U S +W A V V E S +W E K A +W I L L 777 +W I N 3 D +W J M V +W L F +W O W S K I +W Rizz +W a r s +W ak +W amo +W anted +W e r +W elfare +W i i +W i l l y +W i r e tap +W ifi +W iggly +W illy +W ilmer +W l S E +W ll Z A R D +W olf +W orx +W-2 Form +W-A-M-M-E-R W00D +W00DINTUNA +W00X W0N DMM W0MB +W0RY W0SS W0fle W0nderwall +W0t Rng +W141 Legends W1ETzakje +W1F +W1G +W1Z3 W1ldman W1nch +W1ngedDragon +W2P_III W330 +W349 W370 +W3SL3T7 W3ST0RZ -W4R3 W420 +W489 +W4R3 +W4T3RM3L0N +W4Wumbo +W56 W5O7 W7uQs7s1uKyS W7uQsTu1KsyS +W8 letme pot +W88SSKILLER +W8ST UF TIME +W8ing4Name +W91 forever +WA2 WAGINGWARS +WAKANDA JEFF WAKEUPSWEATN +WAP Munchlax WAQQQ WARLOCKTIN WAZABl +WAxsTAche +WBA Scott +WBMA WE0DEND +WE3N +WEEDY Woody WEGOINGCRAZY WEGSIR +WFH Gains WFTWP +WG Affect +WGWGWGW6W6W6 WH1TECHAP3L +WHITE E92 WHITEEEEEEEY +WIMThighs WINNINGrng +WIRE PULLING +WISEB0LDMAN WIZRD6 +WLJ +WM94 +WMAF +WMATA WO0DSIE WOMYNAREDUMB WONT +WOOGLlN +WPNsuper +WS Hubris +WS Kyzza +WS Phora WSOP +WTB GF 1 GP +WTF No Luck +WTF S7VEN +WUDS +WV Boi +WW I +WW2 Champs WYBD +WYD STEP M0M WYDStpSis +WZ95 Wa Wa Master +Wa t WaIk WaVy +Waaaan WaaduuuHek +Waafty Waager +Waai Do +Waassssaaap +Wabanaki Son Wabbert +Wabo +Wack Sparrow +Wackabie +Wacko Swaami Wacoltx Wadbot Waddlez +Wadee Wadeo369 Waderik +Waem Wafcfreak +Wafe +Waffle Cone +Waffle Jr Waffleboy +Waffleici Wafflekin Waffles700 +WafflesYo Wagada +Wagblump Waggit WaggsTheDog Waggz Wagit Wagn1984 WagnBurner +Wagyu Wahb Wahido11 +Wahpahp Wahpan Waifuism Waifus WaikatoChris +Waikit8 +Waine Wait +Wait Quick +Waitforit14 Waitin Wajiiro Wake +Wake Boarder WakeAndDrake +WakeUpF1lthy +WakeUpGirl +Wakey Wines Wakisaka +Walborg Waldrin Waldron530 +Wales164 Walker Walkin +Walkofshane WalksOG Walktellfox +Wall-enberg Wallabies +Wallabillah +Wallace D S WallaceTusk +Wallah Krise +Wallah Lag +Wallahper Walleen Wallerz Wallex Walli +Wallstboi69 +Wallsunny WallyGator Walnutt +Walo CZ +Walpie6 +Walsamer Walshy Walshy00 Walshyo +WaltJnr Walter WaltersPub +Waltt Waltzz Waluigi +Walzu Wampire +Wan E WanPanMan Wandel +WanderTheSee Wandereer +Wanem WangSohLong +Wanhe +Wanistan Wanna WannaBeE-tje WannaGetABag +Wannebet Want Want2beIron Want2mess2 +WantTacos Wantsome909 Waonnman Wapf +WapitiSmackr +Wapol Wapsi +War Dwr +War Force War12Ready WarFawk +WarHawKVJ WarOnOurMind WarSoc +War_x Warbler Warchee +Warcloud Warclown +WarcraftOSRS Ward988 Warden +WardensFe Wardle101 +Wardless 1 +Wardy791 +Ware Adelaar Warfeh +Warforged Warg Wargames11 Wargowitto Warhammer70 WarheadZ91 +Warking 5099 +Warlolz Warlord +Warlord Kek +Warlord Oli +Warlord Papi +Warlord Sage +Warlord Tyth Warlordjinx Warm +Warm Alfredo +Warm Beer +Warm Donuts +Warm Pasta +Warm Pillows WarmLoaf WarmManBlast Warmantus Warmly +Warmongoloid Warmouth Warnac +Warney Warnings +WarpedDeath WarpedMatrix Warph +WarrgMG Warrior Warrior09rs WarriorHome @@ -24853,41 +51296,66 @@ WartoysCandy Wartt Warwick 1080 WasHcimLoL +Wasabeh Wasbeertjes WashMachine +Washed CJ Washyleopard Waspoeder Waspraa Wasserohne Wassillie +Wasstyr WasteOfBond Wasted +Wasted Toxic +Wasted Xj +WastedSpecs +Wastedgr1ny WastingTicks Wastinmylyfe Wastoid Wasup725 +WasupMyBwana Watafara Watamei Watamelun Watanuki +Watardid Water +Water Skink +Water-T Waterbender Waterbury +Watercress +Waterdrop WatermelonTV +Waterpijp +WaterrBoy +WatersHorse Watertodt +Waterwraith Watr Watschi Watson92 Wattledaub WattsyMain +Wattua Waugh Waulez Wauzemaus +Wave 10 +Wave 69 WaveBtw WaveSkill WavesOnMars Wavezz Wavy +Wax Dabs +Wax i +Waxby +WaxbyDonkey +Waxing Sun Waxtap Waxy WayOfKings @@ -24898,113 +51366,240 @@ Wayabove Wayde Waydens Wayert +Wayfarers +Waylor Wayne +Wayne1149 WayneBretzky +WayneMain WayneStated Wayney WayofWonder +Waypanaator +Waypastfear +Wayt Wayward +Wayward Soul +Waza131 Wazp +Wazup31 Wazupfighter Wazzlewop +Wbd +Wcrocks Wcs139 +Wct +Wdfamidoing +Wdges +We B Trollin +We Feed +We Grinded +We Guard +We Love Dogs +We Tad +We The Team +We sley +We0921 WeAllGucci WeAreDoomed WeAreGroot WeAreMoksi WeChat +WeDaBstMusic +WeLoveToB WeRageAsTwo +WeTheCha WeTsHaDoW +WeWanking +Wea Boo WeaIth +Weak Iaugh +Weak Mindset +Weak Terror +Weak Wrists WeakLesss +WeakSpot Weakcob Weaker +Weaki Weaky +Wealth herbs Wealthy +Wealthy Pro +WeaponNovice WeardBeird Wearwolf +Weasel07 Weasel09 WeaselToast +WeaselTuco Weaselious +Weatherwatch +Weatherzx Weav +Web 2 Webb +Webbe +Webben Webdow Webs Webstar +Webtastic +Weby Elite Wecanmakeit Weddn Weder WedhusGembel +Wee Wee Seapy WeeDRekT +WeeMissSlays +WeeWab Weebcrusher Weebmurderer +Weed +Weed B0Y +Weed Barrage +Weed Farm +Weed OG +Weed PhD +Weed Strains +Weed VIII +WeedWizzard +Weedbucks +Weedle +WeeeWoooo +WeekndWorior +Weel Weelechts WeenieHut Weeperz +Wehby3K Wehsing +Weichey Weight Weighting +Weightless Weighty WeirdChimp Weirhere +Weis578 +Weistalief Weki WelbyBree +Welcome +Welcome Beck Weld +Weld Arc Weldar +Welfare PvM +Well Done +Well-ChromeD +Wellar21 Wellbutrin Welld Wellfence18 Wellpower10 +Wellrun1076 +Wellschit WellyWonka +Weloy +Welp Welsh +WelshNProud +Welshfuryy Welshhy +Welshy 07 +Welshy94 WelshyRhys +Wemh Wench +Wendy Page Wendyy Weng Wenja Wenkey +Wenzhou Were2341 +WereWaffles +WereWolf II Werebanana +Werk +Werknemer +Wermin +Werrett Werrtus +Weru Wery Wesh Weshzz Weslee Wesley +Wesper Wessen +Wesss West +West Mids +West Shiv +West Tigers +West Varrock WestFlag WestTxBoyz +Westardythot Western +Western PA WesternBlot Westleafer Westly Westwich Weszie +Wet Boxes +Wet Garbage +Wet Land +Wet Ottr +Wet P +Wet Sneeze +Wet Thot +Wet and oily WetDreamMeme WetForPet WetRnG Wetex Wetone2880p +Wetta +WetterPussy +Wevile Wexom +Wexs +Wexxorz Weyerbacher Wezl Wh1teSox WhaIe +Whaddup +Whag Whai Whale WhaleeWatch +Whaletorsk Whalkatraz +Whamburgers +Wharebadjer Wharncliffe +What Da Hell +What if WhatASpoon WhatAThot +WhatAreDrops WhatItDoBoo WhatSheZed WhatTheDaze Whatapure101 Whats +Whats Canada +Whats Good +Whats Reddit +Whats Trade WhatsHonour WhatsRsSober WhatsThisRNG @@ -25015,262 +51610,501 @@ Whavenlad Whaxt Wheatleyprop Wheel +Wheelchair +Wheelied Wheelies152 +Whees +Wheesnaw WhenPigsFly WhenRuneLife WhenYouCute Whensfull +Where is GE WhereAreWe WhereIsPeace WhereTheCats +Whereisme7 Wheremeballs +WheresMyPets +WheresMyPurp +WheresMyRNG WheresPurple WhersMyPet Whesh Whey +Whey God Whiff +WhiityTosser WhilyWhip Whimsicat Whina Whinnie +Whipppy WhippyMong Whipsaw Whiskerfish Whiskey +WhiskeyWhip WhiskyVault Whiskywayne Whisp3r +Whisper_2 Whitah White +White Beauty +White Mage +White Mantis +White Owl +White Rnger +White Shark +White Soul +White Wolf WhiteBTW +WhiteBoySam +WhiteChuky +WhiteCricket +WhiteDeathh1 WhiteMagnet +WhiteMaleHre WhitePilled WhiteProdigy WhiteWolf216 WhiteZephyr +WhiteZetsu Whiteboy016 +Whitecoast +Whitecrow Whitefire68 Whiteflashh Whitemambz +Whitetoes +WhizsuJr +Who Add +Who Nose +Who8mypaint +WhoDatDJ WhoDoICatch +WhoHaxdMe WhoLikesIron Whoa +Whoa Gaming WhoaKemosabe Whole +Wholelottabk Whomp923 Whomst +Whomst MD Whoratile +Whorrid Whos +Whos Jo3 +WhosUrDabby +Whosjason Whosyourmac Whothehell +Whruum +WhtKndofCake +WhteLilySeed Whuo Whurse +Whurse Meat +Why 8ank +Why Play +Why SkaR +Why Try Guy +Why are u ge +Why u N0ob WhyBank WhyCantIPick WhyIsRumGone +WhyNevaLucky +WhyRyan WhySleeping +WhyTryAtOsrs +Whyase Whydoubother +Whymcie +WhyteGoodman +Whyto +Wibbity +Wibbix Wibbleforce Wicea +Wichel +Wick3d Bet Wickaboag WickedKlowns +Wict Widdly Wide +Wide Client +Wide Vibe +WideBoyy +WideDommy Widmee +Widows Kiss +WiebMasterly Wiebah Wiebere Wiebren Wiebstar003 Wiegedood +Wielebny WienerWipe +Wierie +Wiesel Wife +Wife or RS Wifi +Wifi Beater +Wig Lops WigWacker Wigan WiganRS +Wiggety Wiggie WiggleMcTuff Wiggly +Wiggly Woo Wiggoth Wigins +Wihbane +Wihwy +Wiigg Wiiillllsonn Wiiize +Wiji Wijji Wijsheid +Wikas1337 +Wiki Flipper WikiLiex WikiWorm +Wikinger Wikingpedia +Wikked +WikuliK +Wilby Wild +Wild Bill 71 +Wild Clicks +Wild Cowboys +Wild Fury +Wild Orange +Wild Pump +Wild Raven Wild Rivers +Wild Spirit +Wild Squidi +Wild Stylez +Wild Whim +Wild chickie WildAbandon +WildGothGirl WildSF WildSnorlax +WildTokes Wilda83as7 Wildapple +Wildbasher Wildboy181 +Wildcard +Wildcatface +Wilde Bizon Wildfire Wildlands Wildly Wildmon +Wildy Back Wilk Will +Will Compton +Will Smif +Will T +Will i b +Will man +WillCosby69 WillG WillNight +Willasaurus WillfulNomad WillfulTiger +Willi William +William Way William2133 +WilliamChris Williamsburg Williamwrc +Williamwurld +Willianderma Williard Willicous Willie WillieP +Willlowsap Willo +Willoweeper2 Willowisp +Willsy_828 +Willy WillyMonka +WillySneeze WillyTickles WillyVanilly +Willyams Willymule WilmaCokfit Wilnafe +Wilpu Wilro +Wilso Wilson +WilsonBro WilsousGoods Wilters Wiltings +Wilwork4stuf Wilza Wilzy Wimm +Wimpy Hulk +Wimpy Worm +Wimpy127 Winanda Wind +Wind River +Wind the ham Windal +Winded +WindexWipes Windi +WindmillBoy Windowpie Windows10 Windrun +Winds Tormnt Windwaker Wine Wineapple Winedolphin WinexBlaze +Wing Daddy +Wing Reaper +WingToe Winged +Wingedlemur Wingednebula Wingknutts Wingless +Wingman Skre Wingmanfire +Wingmastah Wingnut Wingnut277v2 Wingoficarus WingsXIcarus Wingz Wink +Winner Chris Winner1Class +Winning Life Wintage +Wintaj Winter +Winter Slays +Winter Woede +Winter mage Winterpropht +Wintersaurus +Wintertarwe Wintertoad +Wintis WintonOS Winze Wipe WipeRZ +Wippy Spuds Wipzed +Wirbi Wirusas14 +Wis +WisCheez Wisdem Wise +Wise Andy +Wise Bloke +Wise New Man +Wise OlMan +Wise Old Guy +Wise Old Roy +Wise Pug +Wise Up +Wise9884 +WiseBlackMan WiseOIdMan WiseOld +WiseOldCam WiseOldNeef +WiseOldNut WiseOldSimp +WiseOldWench +WiseYoungOne +Wish +Wishen Wishidie +Wishies +Wishwandewe +Wishy Walshy +Wispa WispyWolf Wissfx1 +Wisundaz Witch +Witch Aileen +Witch Elf +Witchkraft +Witchprick +Witchz +Witeout LLC +With Skills Witha +WithoutAGe +Witicism Witkus WitlessFox Witness +Witte WitteLijnen Witteri +Wittu Wittytoad Wixsie Wixxa +Wiz master WizKaleeba WizKawifa Wizard +Wizard Weird +Wizard of Oz Wizard012345 +WizardFish11 WizardIRL WizardKing WizardMascot WizardSleeve +Wizardmatt6 Wizardspike Wizfujin Wizidross Wizreefer +Wizyweirdo +Wizz Z Wizzie Wizzti Wizzy Wizzypoop Wizzzard +Wkd Br0 +Wkedjester +Wkndr WlLDERSGEERT WlLL +WlLL1am WlLSO +Wlatt Wlsperingeye +WnB WnnB +Woadblu Woah +WoahDudeNice Wobbery WobbleyPOP +Woblin Wobos Wobs Wobufett +Wocka Wocky Wodka +Wodka Orange +Woe Woe Woedipoe Woemance +Woeppa Woes Wofford +Wofford2 Wohdii Wohrx Woikaz +WojoWins Wojtas WokeUp Wokkel +Wokki Wolf +Wolf Berserk +Wolf66 WolfApple WolfLucifer Wolf_Hunter Wolfazal Wolfboi70 Wolfboy1209 +Wolfden95 Wolfeena Wolferno +WolfgarrX +Wolfgarth Wolfhearth Wolfie +Wolfie Daddy Wolfiezzz Wolfinger +Wolfique Wolfjob Wolfman +Wolfman00777 Wolfmans WolfnBane WolframOxide Wolfshade Wolfshook +Wolfspeed Wolfy3777 Wolfz Wolles +Wolq poW +Wolverine V8 Wolvesy Wolwa WomanScorn +Womaz WombatLife +Wombats Wombayaga +Won Alll Day Wonderful +Wondo +Wonka44 WonkyShlonky +Wonn Wonnawonka +WonterJodt +Woo Hee +WooGGi Wood Wood Choppin +Wood Scimmy +Wood Style +Wood VI Wood4all WoodJablowm3 Woodcrest +WoodcutterQw +WoodenSword Woodland Woodsboro Woodson @@ -25279,31 +52113,57 @@ WoodsySmells Woody Woody540 Woody8 +WoodyBussy69 Woodys Woodz90 Woof +Woof Woof Jr Woofaire +Woofi Wooh +WookieBread +Wool Socks +Wool Tar +Wooli +WoollffMain Woolly +Wooo Blod +Wooody125 +Woooglets +Wooogy Wooooo91 +Woopie Doop Woopsx10 Woopuh Woord +Woorm +Woos Woosa Woot Woowoh Woox +WooxFromWlSH Wooz Woozie400 +Wophel Iron Word +Word Bird Word2urmum +WordCheck Work +WorkUkko Workahaulix Workath Workin +Working Man +Working Poor Workouts Worland World +World 46 +World 526 +World 61 +World Of Rat World345 WorldEndero WorldWarTwo @@ -25313,23 +52173,39 @@ WormInHeaven Wormeater66 Worms Worning +Worning Mood +Worst Herp +Worzo Worzord +Wosby Woshy +Woste Wostyn WotCee +Wotnel +Woudie Woul Wounded +Wounds Wourlow WouterMarni +WouterPils Woutertje +Woutertje 93 WowAUnicorn WowDerek +WowoW Woww Wowzer1482 +Woz X +Wozi +Wozol Wozzah +Wozzy Wqlq Wrackbar WraithSx +Wramn Wrap Wrap5 Wrath @@ -25337,11 +52213,17 @@ Wrath0fMath Wrathchildxd Wrathinsea Wrav +WreXham AFC +Wreck These +WreckAndRoll Wreckage Wreckanism +Wrecked Wreckfull Wreckin4Days Wreckon +Wreckonize +Wrecky Wreckzu Wrekdum Wrektem @@ -25349,139 +52231,283 @@ WrektumRalph Wrenny Wrigzer Wrijo +Wrinkle Meat Wripzi +Writing +Written +WrmFzy +Wroggi Wrong +Wrong Focus Wrot Wruumze Wryd +Wrynn Wsupden +Wtf Burgers +Wtf Bwana +Wtf Is Elmo +Wtf Michael +Wtf happen WtfJad Wtf_Stake +Wtfisabook Wtfxcreepy1 +WuLuZ +WuTangDan WuTangRs WuTangflame WubbaRs Wubj +WuceBrayne +WuckFeeaboos Wucky Wudkip +Wueu Wuhan Wulfeh Wulkanaz Wullets +Wulong Rush +Wumbolii +Wumox Wundy Wungz +Wunk +Wuntch Meat Wur1 Wurgon Wurj +Wurrior Wurstfest Wurtziite Wuteng Wutlife Wutru +Wutta Beast Wuuluu +Wuz H Wuzn Wuzzi99 Wwalrus Wwarlock Wxll Wxyz +Wy 1853 Wyan Wyard +Wyatte +Wybb Wybo Wyborowa +Wyd +Wydie +Wyel +Wyiphi Wyldar WyldeKirito Wylie Wyliecoyote2 Wylyne Wynand +Wynmao123 WyoFletch WyrdStoned +Wyrlor WyvernBreath +WyvernMage WyvernSlayer +Wz Karmish Wzurd +X X V +X 0H +X Axis +X Bullet X +X Dsmith X +X E L E X +X E R 0 +X Ecuted +X I L E +X Ice Break +X Japan +X King Jehu +X Landie X +X Mars +X Mathiew X +X OUT OF RS +X Robert X +X Rorschach +X SUR X13 +X Seabridge +X WAVE 70 X +X Y P O +X e x i m +X pelz +X-Jabs +X-Man +X-SVNTH +X0N3X X1xfa11enx1x +X65 +X9Y XAAXAA +XANSEB XARlQUE XATHD XAyYxlMaOxX XCShark XCortezX +XD XDDD XD XD8D +XDQ XDamage XERTNARG +XESPIS XEback XFitVapeVegn +XHCD +XI J +XI5 +XIBT +XIX Zeta XIX +XIXIXIXVXIVI XIXXI +XJT XKappaX +XL Peen +XL Succ +XL itikka +XMR XNovaCainX XOBLIN XORB +XP All Night +XP Hobo +XP Jake +XP Thieving +XP for gains +XPOQ +XRP Glandorf +XRV +XRay Mike +XS3X XSandwich18 XSapocalypse XTCarlo XTIF XUJ0RKI XV73J +XXGrimorgXX +XXTENTACI0N +XXaan XXera +XZoTicTB +X_Ouchies_X +X_Streetz +Xa1e Xaaan +Xaberphel +Xadia +Xaeram Xafirox +Xahp +Xaint +Xalastar +Xalcvs Xalrir +Xam Renz Xambitz +Xamphion +Xan Gogh +XanaxXR +Xandahr +Xandayn +Xanefeo Xanfan Xann +XanomaliuX Xanq Xanthophylle +XanthousKing Xantiasto +Xar Xarigue Xarious +Xarkus Xarnathos Xarov +Xarpus Decay +Xarqn +Xartes253 Xaryn Xasdaxs XaskiM +Xasthur Xatar Xaud Xaussiemaulx Xav777 +XavieerL Xavieerr Xayrus Xazz12 Xbalan Xbogaerts Xbox +Xbox Account Xbox kid 99 Xboxkid33 +XcL ady kila XcalenX Xcalumet Xcelorin Xcuuuse XeNeaxaxa +Xebstrika Xecki +Xedoria Xeem +Xeet +Xefi +Xefn Xelas Xelcab Xeldin Xelian Xelzathar +Xemnax +Xems Xen0phyte XenaDior Xenastry Xendel +Xenece Xenethos Xenfire +Xeniat +XenithStar +Xenlon +Xennofobia +Xeno X Human Xenofiel Xenofile Xenoforms +Xenorith XenoviaZhao +Xenria Xenses Xentric +Xentric I Xenzah XeoX Xeqo Xeretus Xeric Xerics +Xerics Exile +Xerics Solo +Xerile +Xerkom Xerloz Xero XeroBlitzAce @@ -25491,14 +52517,25 @@ Xerona Xeroscape Xerosenkio Xeroso +Xerphias Xertrius +Xerxe Xestox +Xetarillos +Xewne +Xeyler Xfebruari23X Xflowerz1 Xgen2004 Xghostbx XgodofironX +Xhaloz +Xhq +Xi Bogan iX +Xianerth Xiang +Xiang Ying +Xiao Wei Xick XicoDoAnzoL Xidos @@ -25506,19 +52543,37 @@ Xielt Xiff XigZig Xiglaan +Xijaxer Xilamz Xillious Xilphy XinXani +Xinbonddon Xinck Xiom +Xiphoz +Xipi +Xipo +Xirenia +Xists +Xityx +Xiuol Xizor +Xizxuka Xizz +Xj Driver +Xl Pat lX +Xl Tango lX +Xlarss +Xlogmore +Xmas Santa +Xmasvibes Xmerl Xnam Xname4 Xniklaz XoXdr34mzXoX +Xofal Xoir Xojix Xolca @@ -25530,319 +52585,739 @@ Xoobs Xorphas Xorx XoutofRunes +XpTitan +Xpect2die Xpelz Xperiencer Xplay2slayX +Xplicits +XploitClamps +Xpm +Xpreme +Xqcksilverx Xqkiller Xquick +XrRipple Xsk1l3rX Xskillz XslayerkingX +Xsy +Xtan +Xterioz +Xternal VZ +Xteven +Xth +Xtian Xtopheris +Xtreme Kill +Xu +Xu3 +XuRuP1Ta Xufo Xuhe +Xulaa Xulreh Xupafion +Xuro Xutera +Xuxe Xuxy97 XvalQ +XvalentiX XvegetaX Xvim +Xwb Xwoprl +Xx A ll y xX XxBABY +XxBriDGExX XxCoponerxX XxJIMBUSKID XxKaakkimusx +XxMOPExX XxPoliSwagxX XxRXZ60xX Xxhel +Xxpyroxx20 XxrigourXx +Xxsagexx30 +Xyagrius +Xylarium Xyler Xylr +Xylym_pilot Xymox Xynamic Xyrath Xyresic Xyryu Xyzcanon +Xz8 Xzavier Xzil +Xzpect +Y DynHaearn +Y Fx +Y O D A +Y O K A I +Y arok +Y ellow +Y em +Y ogo +Y oshi Y0N3 Y0l0mees Y0usless +Y2K38 +Y2k Survivor Y3RBA +Y3w +Y4P +YBank_Mak 69 YCTH +YCantPigsFly YChewyYOS +YEEEZY YERTII +YExTI +YGBigTank +YKW +YM +YMJFL +YNW Kushy YOKiki +YONGWOLRANG +YOOOH JOEE +YORJ YOTJ YOUR +YOURMOMSMAN +YS3 +YSL +YSL for Life +YSinpo +YTPO YTrySoHard +YUSEF +YWM +YYST YYose +Ya Boi Suff +Ya Boy Lachy +Ya Boy Ryan +Ya9 +YaBoiCrisps YaBoiSlip YaBoiWestie +YaBoiiQuan YaBoyCosmo +YaDoons YaLilMupp1t YaOldHeffer +YaSillyRAT +Yabai +Yabbary +Yabbie Pump Yaboiskee Yaboitrek Yaboku Yabui Yachi Yachiri +Yackill +Yackity Yak +Yackley C Yagyu +YahRamen Yahe +Yahtz3 Yahtz3e Yahya10100 Yaik +Yaimzz +Yak Elves +Yak of Iron YakYak +YakimaValey +Yakka Stacka Yakosu +Yakushima +Yakuza +YakuzaDragon +Yalazar +Yall Raycist Yalloune Yalomi +YamR6 +Yama XCII Yamagata Yamakato Yamata Yamda Yami +Yami Bakura +Yammed Yampay +Yampay II Yamsaretasty YanKeDooDle +Yand0 Yang Yangtze Yangus456 Yani +Yanilla +Yanilla Kush +Yank on This +Yankee Run C +Yann78 Yannick177 +YannickH Yannis +Yao Yo Xin +Yaossynx +Yaprakdal +Yardi +Yarfn Yaribel Yarne Yarny +Yaseki +Yasen 105 Yasuos +Yasuuo Yato1God +Yaukai Yauz Yavrum Yawan Yawgg YawningPanda +Yawp +Yaxfe YayItzTyler +Yaysuo +YazanBates Yaziro Yazo Yazuki Yberi Ycinho +Ydmyk Ydorog Ydrasil +Ye Magekilla +Ye Mate +Ye Olde Ace +Ye Olde Ned +Ye Olde Oak +Ye ti YeBankWicked YeBoi +Yea UrBanned YeaAiiiiite +YeahIMineIM +Year YearUp YeastPocket YeastyPussey +Yeblehs +Yechs Yeda YeebusGeebus +Yeeeeehaww Yeeetist Yeeetscape +Yeern 101 Yeeska +Yeet Dan +Yeet Thyself YeetMemes +Yeeted One +Yeetu +Yeezy YefTalks Yefim Yehtii Yeiw +Yek Yekhsad Yekouri +Yeland YeldariIII Yeli +Yelling YelllowFlash Yellow +YellowForest +Yellowfox21 Yellowhoody +Yem o +Yemly +Yemrisnen +Yenie +Yenil +Yenofthunder Yenom Yentelke1998 Yeoubi Yeoz +Yep Cup +Yerbal Tea Yerd +Yeren Yerico Tsu Yerkinoff +Yerm da worm Yeroen YerrBanned +Yerradu Yerrrrey +Yes Click Me +Yes No Maybe YesOk +YesYesYall +YeshuaShalom +Yeso Pro Yessir Yesze Yetagaindied Yeteri Yeti +Yetiburger +Yetlon +Yetsu Yettiez +Yetzne +Yevop +Yevral +Yew 2 +Yew Burn +Yew Root +Yew Tree +Yew Wu +Yew a sloot +YewEssBee +YewGnomeSayn Yewcutter Yewise Yewna Yewp +Yews pnas Yewsanity Yewse YexaC Yezzi +Yfer +Yffud Gnik +Yggdrasverre +Ygh +Ygritte8686 +Yharnam Soul +Yhul Yiatse +Yid +Yidy +YikesScooby +Yilver Yimo +Yinlin Simp +Yippe +Yippiyak +Yisabela +Yja +Yke Ykeykey YlFF Ylikivaa +Yllattyneet Yllig Ylmn +Ylpistynyt Ylulawo +YmanThe1 Ymbyydi +Ynastra +Yne +Yng Xehanort Ynka +Ynun +Ynza +Yo Caspian +Yo Griff +Yo Its Devo +Yo Kev +Yo L +Yo MyUSD +Yo Soy Dios +Yo lm Lee +Yo uu +Yo wyd Yo2021 +YoCerberus +YoGurttt YoHighRoller YoHimiiTsu YoIronManBtw +YoKristaps +YoMomsFavBF YoSinNow +Yobew Yocan +Yoco Yoda +Yoda Adf +Yoda Corona +Yoda NSZ YodaEvans +YodaPen +Yodamainn YodasNo1Fan YodasYoda +Yodasquad Yodati +Yoder +Yoerias Yoeshua Yofang Yoghurtis Yogi +Yogi DMT +Yogi Surfer Yogololo +Yogusun Yohny Yoink +YoinkYoink Yojak3 Yokie Yolkysky YoloSwagHope +Yolp +Yolvert +Yomaku YomamaPro +Yomashu Yomdo Yondu +Yondu Poppin +Yonemid +YongZhong +YongZonnegod +Yonkers +Yonko Buggy +YooDuragon Yoodish +Yoooord Yoorah +Yor Yorga Yorick Yorick095 YorickMorty +Yoriichan Yorinky +York Rite +Yorkson Yoru Yosep Yoshi +Yoshi Man17 +Yoshi Suyumi Yoshi6380 +YoshiThick YoshisStory +Yoshiwaptor +Yoshizilla +Yotaak +Yoteii +Yotsuya Miko +Yottie +You Are Zach +You Be Love +You Die71 +You Ok Fam +You R D3d +You rc 2 +YouGotRoll3d YouGotSeabed YouNeverKnow YouOverThink +YouSuck YouWontScare YouareGE Youbartonz +Youme +Youncies Young +Young Bucket +Young G4 +Young Guthix +Young Krazed +Young Logic +Young Mooch +Young Mullet Young Tango +Young li +YoungCatFish +YoungNoot +YoungScuba YoungThugga +Youngdaddyg Younge +Younglleff +Youngn Youngsters Youngvet Your Your Amity +Your Future +Your Idol +Your Misery +Your Mom67 +Your Mothers +Your Toilet YourDadIsMe YourFrenRen YourObsessed YourPaperm8 YourSolution +Youre Joshin YoureAllTalk YoureIgnored YoureMySam +YoureSoCool Youssef +Youthful +Youtube Luck Youwillcower Youxi37 Yowarrior40 +Yowch Yowzer Yoxz Yoyaaaaaaaaa Yoyo Yoyo502 +Yoyoma007 +Yrasa +Yrdna +Yre Yrjo +Yrok +Yrrabo +YsL Dom Ysdragos +Yshtola +Ysr Yster +Yster Bunny +Ysuke +Yu Seolha Yu Stinkipu2 +Yu Zi Jiang Yubs +Yubz +Yucan Tucan Yuck +Yuck Aroma YuckFou YuckMouth +YuckNoYums Yudi Yuengllng +Yug Cipe +YugiMoto666 Yugioh +Yuhai Yuigahama +Yuiii Yuiku Yuipster +Yuka Takaya Yukaiaiaiai +Yuki Kitsume Yukika Yukionna YuliusCaesar Yulong +YumYumSauce +Yuma az +Yumaad Yumbo +Yumhumgao Yumiko Yummy Yumped Yundastan +Yundruh +Yuneekh Yunery Yung +Yung Belial +Yung Birdie +Yung Deaner +Yung Nice +Yung Swoosh +Yung Zach +YungDuski +YungIron YungMoistGod YungPredator +YungSlick YungThimothy YungTungsten YungWhiteBoy Yungsik +Yungsingteng +Yungyonder YunnT Yuno +Yuno Yuno Yunozen +Yunq Yunthers +Yuoni YupImMadBro Yupal +Yuqi Dab +YuqiShuhua Yurimo Yurix +Yuriy Yusaris Yusko Yutorgborm +Yutzz Yuudachi YuugeJohnson Yuuki Yuuma +Yuuuuurd me Yuuzu Yuyevon2003 +Yuyu Shirai +Yuzumii Yveaux Yvno +Yvoa100 Yvon +Yvuar +YxY Yxskaft +Yzanagi +Yzap Yzyszn8 +Z 0 D I A C +Z 84 +Z A D O +Z A R G O T +Z A V Y +Z Barrows +Z E R0 +Z I K O +Z Jay +Z M P +Z O R 0 +Z O V K O +Z O ZO +Z Rowz +Z a a K i R +Z aeBae +Z e e e f +Z e x +Z ebak +Z edd +Z erkie +Z ev +Z i g g e h +Z igZag +Z ion +Z y g y +Z ygis Z-TheReaper +Z00STER +Z0K0 Z0MBI3 +Z0MBIFIED +Z0NK3D +Z0RB0 Z0bbey +Z0deac Z0ops Z1pn Z1pn_xD +Z26 Man +Z3 +Z3FRAN +Z3R0 CO0L Z3ds +Z3ymour1 Z4phy +Z4ppie +Z6L Z7Z7Z777ZZ +Z900 +ZACCU +ZADDYGANG ZALCANOPET ZALGlRlS +ZAQWRY ZB84 +ZBLOCKA ZEIVI ZEKEDAFREAK ZELDRIS0 +ZER0 EHP +ZER0Z +ZGJ +ZHG ZIARED ZILLER +ZJ +ZL1 Devin +ZLA +ZMB Scary ZMithrilMan +ZNDX +ZOEY 101 FAN ZPWUZZLED122 +ZRegi +ZSYD230207 ZUCK +ZUK EXPERT ZUwUBI ZWUNK +ZWlFT +ZX +ZY +ZZ +Z_Z ZaPhiRoxD +ZaadTeef Zaane Zaanstad +Zaatar Zabe +Zabey Zabini +Zabky Zaboxi ZacAynsley +ZacBallsHard +ZacFx +Zacariah D +Zaccchhh +Zaccy Zacflame Zach +Zach 6464 +Zach Patino +Zach est13 +Zach q p +Zach07 Zach314 +Zach4211 Zachagawea Zachatank Zachawy @@ -25852,38 +53327,86 @@ Zachs ZachsAccount Zachulous Zack0ry +Zack504 +ZackAsch ZackSparrow ZackWasTaken +Zackary +Zackle Berry Zackly Zackman Zackology +Zackree +Zacky P Zacoron +Zacxion +Zaddy Bully +Zaddy Zo +ZaddyCool +Zadek Zadior Zadok +Zae +Zae The Bae +Zaenil +Zaeres +Zaf Zafaron Zaff +Zafrot +Zaga911 Zaggly +Zagustin +Zagz +Zahard Army ZahellGlarus Zahellina +Zahiirr Zahnae +Zahrani +Zaion Zairin Zairx Zaitsev Zaixii +Zaixyyuu +Zakhary +Zakje Pep +Zaku Rs Zakz +Zala +Zalaberto Zalar +Zalat Zaleander Zalen Zalerae +Zalotus Zalphyrus +Zalse +ZaltyPretzel Zalux +Zam ZamPeZu +Zaman Zamanr Zameul +Zami Zamianx +Zamicxus +Zamirok +Zammiy Slay Zammy ZammyHasjta +ZammyJesus +Zammys Flame Zamorak +Zamorak 61 +Zamorak Book +Zamorak Tome +Zamorak808 +ZamorakBrews +Zamorakz Zamorangue Zamorizzle Zamowrecked @@ -25897,225 +53420,461 @@ Zandous Zane Zanfew Zanfis +ZangKeera Zangola Zaniels +Zanimoto Zanithic Zanity +ZannyBatsbak Zanryu +Zans Zansus Zantaril Zanwk +Zanzu +Zaom Zaon ZapWasTakn +Zapah +Zapatos +ZaphiasTM Zaphyan +Zaphyrim +Zapii Zapio Zapky Zapleno Zapletics +Zappaforever Zappman123 Zapppy +ZappyLand +ZappyWabbit +Zapsticle +Zaque +Zara Mobile Zaraffa Zararod Zarasth Zarathos +Zarchonias Zardee Zardua +Zarf +Zarfa +Zargole +Zariah +Zariky +Zariser +Zarke +Zarkh +Zarkino Zarkoz +Zarley Zarliona +Zarmos Zaro +Zaro M +Zaroki Zaros +Zaros2k +ZarosCorrupt +ZarosRex Zarosadomin +Zarosian Rat +Zaroux Zarov Zarpedon +Zarrix +Zarude +Zarvern Zary +ZaryteKnight Zasi +Zasilus +Zastava Ak47 +Zastavo +Zatailex Zatch175 Zathul Zatom +Zattix Zauberbiest +Zausbaus Zav555 Zavaren +Zavikk Zavilia Zavinor Zavorak +Zavvia +ZavylonCG +Zawro +Zawts Zaxbys Zaxcord Zaxm1 Zaxxxsoldier Zaza9119 Zazian +ZbraCakez Zbychu +Zch +Zcj +Zcu +Zdawg +Ze Golo +Ze Own +Ze Punheteir +Ze Ubernoob ZeOblitz +ZeProx +ZeQuYaa +ZeZienMaar +Ze_balla Zea1ous Zeal +Zealandra Zealea Zealicious Zealoe +Zealous Love +Zeals Max Zeather +Zeb Slays +Zebak +Zebak Acid +Zebaks Jugs +Zebedank +Zebede Zebest605 Zebras +Zebs main +Zebs scuffed Zebu Zebuck +Zecca Zechuchith Zect +Zed7 +Zed_11 Zedanko Zedar Zedd +Zedd UwU Zedd180 Zedek Zedirex Zeds +Zedz ZeeAyyBee ZeeEL +ZeeZeeZee Zeebers +Zeec Zeedith +Zeehox +Zeeke Zeekheart Zeelmaekers +Zeemoee +Zeeny +Zeeon +Zeep +Zeepra Zeerkel +Zeeshan Zeeshan01 +Zeeuun Zeeuws +Zeeuws Tuig Zeeve Zeeyk Zeezki Zeffe +Zefrank +ZefyX3 Zegetable +Zeh Zimah ZehThijs Zehbu +Zehf +Zehiret Zehv +Zeilex Zeinovyah +Zeious +Zeitgaist Zeithex Zeken +ZekimusPrime Zekje Zekkels +Zekley Zeko01 +Zekrom ZelaooReturn Zelatrix +Zelcano Zelcode Zelda +ZeldaHaxor42 +Zeldamen Zeldaza +Zelle Me GP Zelnite53 +Zelroy2 +Zelten +Zelzoy +Zemiak +Zemie Zemix Zemmy Zemoko Zemps +Zemyrrah +Zen Moments +ZenBtw +ZenRaidz +Zena96 +Zenathrius +Zenci Zenearys +Zenemz +Zenez Zenfor +Zeni Master Zenithina +Zenitsu +Zenium Zenki +Zenki RS +Zennyte Zeno +Zeno Pho Bia +Zenoce Zenpep +Zenqii +Zenqs +Zenrrrr +Zensai +Zentae Zentra Zenytum Zenzulo +Zeon Clone +Zeorun +Zeos Zeoth +Zeou Zeoxr Zeph Zeph0s Zepher138 +Zepherahs +Zephere16 Zephrinne +Zephxa Zephylius Zephyren +Zephyrhills +Zephyric Zephyrot Zeplin1 +Zeppelin IV Zer0Requiem Zer0Tw0 Zer0mancer ZerUmh +Zeratul259 +Zerbeh +Zerberous +Zeref Zerendipity +Zergonaut +Zeri0n ZerkByDay ZerkInDaYard +ZerkMeOffPlz +Zerkeee Zerker +Zerker fe Zerkism +Zerkom Zernag Zero +Zero Cals +Zero DeNiros +Zero Saber +Zero Scope +Zero Suit +Zero Talent +Zero Tol +Zero Zeros Zero92922 ZeroAltruism +ZeroBodies +ZeroCake ZeroDignity +ZeroFox8576 ZeroGravity3 ZeroHour +ZeroHpAgain +ZeroTheKing +ZeroValor ZeroXJD ZeroZero Zerobeat Zerodareborn Zeroeagle +Zeroen +Zerololz Zeroly2 Zeroswift Zerq Zerrilis Zerro +Zersers +ZertUwU +Zerx +Zesima Zeskater Zesty +Zesty Bvrnsy +Zesty Senpai +Zesu +Zet_RS Zetani Zetardo Zetore Zetreker Zetrus +ZetsuboSekai Zetsubou Zetta Zettty Zeug Zeus +Zeus Jr +Zeus07 Zeus09 Zeusvdl +Zeven Zeveria +Zevlim Zevosh Zevvo Zewx +Zexma +Zexra +Zexual +Zeyora Zeyzima +Zezaroth Zezergz +Zezima Simp +Zezima W q p +Zezimaislife Zezimas Zezime +Zezus +Zezynx +Zfg Fan Girl Zfsalt +ZgeL Zgrite +Zgzi Zhacarn Zhaoyl Zhava Zhinky Zhiqth +Zhonny +Zhops +Zhotaro Zhqith +Zhuxiong Zhuzh Zhykiel ZhyloFlex +Zi P +Zi1y +ZiNikor Ziauze +Zick Licker +Ziclone Zidi Ziega +Zierikzee +Zigfrid +Ziggey Ziggurattus Ziggydog7 +Ziglar +Zigory Zigzagoonfmt Ziicatela +Ziidz Ziinc Ziincor +Ziisus69 +Zijwiel Iron Zikry +Zil o Zilandraa Zilanthra Zilex +Zilexion777 Zilly ZillyLovesMe Zillya Zilpha Zilvia Zilyana +Zilyana Gr +Zilyana Jr +Zilyanas Dad +Zilyarma +Zim Zim8 ZimFlare0003 +Zimak +Zimaterasu +Ziminiar +ZimnyZielony +Zimpathizer Zinc Zinct Zing Zingg Zinixon Ziniy +Ziniyy +Zinnialexis Zinogre Zinoto +Zinryia +Zinshaw +Zinsmaster +Zinsmeistro Zioh Zion +Zion Fire Zioo Zip Lynx +Zipacna Zipit +Zipm Zipo259 +Zipp0Fluid Zippeeee +ZipperTrout Zippy909090 Zipsap Ziqs Zireal +Zireb ZireneV2 Zirkisi Zirn @@ -26123,74 +53882,143 @@ Ziron Zirrub Zirvzaa Zisam +Zitaya +Ziti Sauce +Zitri Zittte +Zivile Zixcon +Zixon Zixxen +Zixxty Ziyai +ZizZazZuz Zizarius Zizou Zizzle +Zji +Zjoelini +Zkilrr +Zkyui ZlGGEY ZlNQK +ZlZl Zlap Zlatan +Zleek +Zleepeey +Zlig +Zlomble Zlote +Zlug Zmancool Zmanonthego +Zmazek ZmaziWasHere ZmbieShepard Znked Znorox +Zo e y +Zo m B +Zo nk Zo7al Zoak Zoanthids Zoaxyl Zobbe +Zobny Zoca +Zoca BD +Zodden ZodiacIsTed Zoeh Zoet Zoey Zofad +Zofu +Zogggii +Zoggy Marley +Zogloid Zogurk +Zohi +Zoik Zoil +Zojun +Zok +Zoka Zolarf +Zolaris Zolcome +Zoli +Zolkaria Zollo Zolon Zolrisma Zolruh +Zolt09 +Zoltan Uk Zoltanious +ZolwoZ Zombah +Zombi Zack Zombie +Zombie Cody +Zombie Zack Zombiezparty +Zomboide +Zombrons Zomi Zomimi +Zomp +Zone Red ZonichGG Zonir +ZonlyAlex +Zonnedael +ZonoxRS Zonse Zonum_Knight +Zoo Orleans +Zoo scape +Zoobloo7 +Zookly +Zool +Zoolander Zoolander011 +Zoom Zooming Zoommaster97 +Zoonix +Zooted Zoppy Zorb49 Zorblet +Zorcar Zoret Zorg Zorh +Zorie Zorin +Zorkath +Zorkz ZornDurag ZoroRoronoa Zorolith +Zoros son Zorrac Zorrita Zorros Zoryov +Zos +Zosc +Zossssssssss Zostok Zoteize Zotetz Zoudrex +Zoumok +Zouns +Zown Zowski Zozma Zozo1232 @@ -26198,54 +54026,116 @@ Zpizz Zqw6 ZrankerF Zrax +Zriv +Zrr Zsedcx +Ztneff +Ztxch9 +Zubaritis Zubora +Zubsolv Zuburus Zucchini3 +Zuchini +ZuckZyZock Zucu +Zuel +Zuened Zuggster +Zugmah Zugs Zuibbi +Zuiox Zuipe Zuipen Zuipvlek +Zuk +Zuk Bot +Zuk Cucker +Zuk Meh Off +Zuk My Toa +Zuk Sucks +Zuk a Duck +Zuk a Zik +Zuk at 1 Kc +Zuk my Tzok +Zuk was here +ZukDisLilZik ZukMadic +ZukMyAss ZukOrBust +Zukala Zukmos +ZukoTheMcoon +Zul-Bot Farm +Zul-tul +Zulandra Zulax Zulex Zullander Zullrah Zullu +Zulrah Goat ZulrahSlave Zultora Zulu ZuluLippen +Zum Zumaz +Zumaz Her +Zumb ass +Zumwalt Zundaddy Zundix Zunkrah +Zup Rap1 +Zurad +Zuramaru Zurcal +Zure Kut Zuremate Zuriel Zuriel321 Zurius Zurkzes +Zurlofix +Zurn +Zurper Zurqos +Zurthur +Zurvan +Zurxas Zuubi Zuuqe +Zuurkast +Zuv Arik +Zuviel +Zuwy Zuxar +Zuxf +Zuxi Zuzad Zuzas23 +Zvg Zvirbulis +Zvotne Zw3d Zw4rtjoekel +Zwabba +ZwangerePapa Zwanneke +Zwartbeast Zwartbest +Zwarte Iron +Zwarte dief +ZwarteAapMan +Zwartehand Zwef ZweiBeer Zwei_02 Zwerky +Zwette Draak +Zwieber Vos Zwiers Zwift13 Zwijg @@ -26254,65 +54144,152 @@ Zwimps Zwinter Zwlr Zwwwnbeast +Zx J3SS3 xZ +ZxFe +ZxbeeRs +Zxeon Zxirl Zyad Zybes +Zyck o Zydecolarry Zyer Zyev Zygalo +Zygameux Zygy Zykaite Zykonic +Zyl Zylco Zyleta +Zyliana +Zyllami +ZynGardener Zynerith +Zynnocent Zynthe Zyntixero Zyper89 +Zyrem +Zyrinth Zyrok +Zyrona Zyrpex ZyruviasDied +Zyunkko Zyxla Zyxuz Zyyra +Zyz Zyzziima +Zyzzy +Zyzzz brahh +ZzJ0SH Zzanoss Zzayo +Zzuma6 Zzyzzx Zzzax Zzzd ZzzzG +[#OA0VWICQ8] +[#SG1JGUXTW] +_Untrimmah +_gria +a Cairn +a Dang +a Mikey +a Miko +a Venenatis +a Venny +a Weeman +a bean +a black cod +a casul +a cooky +a cool bug +a eu +a f o +a gentle sir +a little sad +a ndo +a p p l e +a pathetic +a pb +a sad kraken +a sad waffle +a sk y +a the sniper +a tnQ +a trash cat +a zo +a-x51 +a07 +a1liez +aDome +aDuNaz aGamerGaming +aGamingDad +aGlasgowGrin +aGoober aIIfather +aKSU nPC aKash20i3 +aMiniDude aMiniGorilla +aMiniHitMark +aNERDYsloth +aNStarFury aPinkBunny +aPinkKitten +aShavedLlama aSnowTiger aSunnyPotato aSwiftyBoi aThoms aTinyChimp +aVolk aWildSeal a_SaladKing +a_duncan +aa noob +aaah aaahChu aalucard +aanmaken +aanwaz1g +aaron_diaz aaronparkerr +aatudoz aaty ab0u +aballer09 abbruzi +abbruzie abcz abdi abdimajiid abdulllah abis +abk144 abni +about blank +abqve abra238 +abrakadabraZ +abray +abu hassani acceleratism +ace375 acecoffee2 acerkush achillies +achillies zy +achinadav +achterkamer acidshit +actionbob actlater actofvalor24 acuile @@ -26320,41 +54297,78 @@ adPEXtwinDnG addaaam adem6792 adizzle444 +adogg0323 adopt adrian adsdadasdgtd +adsh55 +adue adul +adul t +advia +advies +advit +aeej +aeggefar aejfd aenpaa aezthetic1 +afatslug aferraro +afh +afk 2 2277 +afk a bunch +afk n doc +afkayscape afkdontattac afkingRS afkvsehp afkwarriorzz +aflk afraid2boss afraid2boss2 african aftrthxght +afzi agent_of_fox +agentdd_4 agfdbzIM +aggain agic +agieee agoraphob1a +agrovation agsmanpro11 +agytagtyewaq +ah oh uh ahahah ahippi3 ahokusa ahrlhyrslylh +ai eye q ai3i42Iaaskl +aiden m8 aidibohx +air strikes +airborn frog aito +aitoBeruna +aiwodas +ajiffniff ak47afghan1 +ak47ags akaExploit akaNorman akae akbennyboy +akeep +akidnamdjrmy akipf +akirahokuto +akkha kum akleb +akq +akspew aksta aku aku1212 al0x @@ -26362,82 +54376,139 @@ alabasta1 alabthemoola alans alaric +alaxam +albersson albiguerra albioon alchetraz alders0n +aldi warrior aldrichmax +aldrichs alecbeats aledank +alexjberroc +alexlangman alexs99s alfafa20 alfhershey algotrader +alias ilias alic3 alimpweenus +alipandh alittlepig alkaizerx alkkis +alkkis pk +all en +all love man +all to 200m +all4four20 +allcaps +allebylund +allenbb3 allez allluminati +allomax3 allora76 allowitplz allzeras +almoggar +alpacathund1 +alpacka toke alpalmchal alpha alphabosss already also alsobosspros +alt f4 gn +alt maxed +alt rite alt0n +alt2kil +altairanezio altehnub altforusa altiarblade +alvexn ltu alvinhic +always win alwayscurius alwrighty +am sam +am so sleepy amagna amay +amfoine +amheeh +amikiri ampharos61 amputated anasacez21 ancapistan anchor +anchor seb +ancientskye andhetakes andhim +andmcadams andreable andriuttt +andtony +andynew2007 anelebar +angel995 angeline1711 angrydump +aniki chan anime +anime member animeF3tish animegirl73 anizan +anklez ankou4smokin annie +annie r u ok +annni annull anoldfatdude +anon1606 +anotha 0ne +another gay anti antibully +antituuri antivaxer antombomb anttimage3 anxiousbeef +any1 anygirls +anyma +ao aocha +aod retired ap1ska +ap3xOo apacifist789 +apcays apeman8731 apenzoon +aperts aphr0 +apikeppa apina apiph3ny apou appelkneuz applee +aqp frog aqqqqqqqqqqq aquafx +araenel13 aratsanus arcane archyiop @@ -26445,342 +54516,692 @@ arcvnaxiii arcwriter ard lad 06 ardazz +ardy guardy arengs +arevles arexmeister arfih argilah +ari abdul +ari shaffir ariman22 +arkoudaphile +armadyyyyldo armyofkids +arnr +arocardo arookie +arouze arreydn arrowbob2 +arrows2ashes +art possible +artaax artan arteefact +arth urr +arthadeos arthurdebart +artist_60 +artizia +artogoes arvothepure arzier ascipulus ascott1 +asdafsdafsd asdasdasdf1 asdsdafsa asedviss asfand ashster25 asian +asianbunnyx asibioass +asidb +asm asmoooo +ason jones aspiraring1 asrdftgffdsh +ass chance +ass jiggles assaultvests +assbergerler +assdrag +asseaterbtw assoffire +astgferallah asuhcuh +at0 +atob7 atoma619 attaaM attack2much auditore28 audrey +audrey horne auma +aus j osh +aussieyobbo +aut AT5 aut1st1c autism +autisticboiz autumnbound +av av av8bgo +avantoeftish avewy +avg Jake +avg gov ee +avg idiot +avikntos avmech31 avocabo awple +aww fk +axeleebob +axeli +axetoons axoblaster axperson808 ay96 aydrian +ayeetbix +ayhank aynull +ayos ayo +ayrball +ayshinx ayte ayvz ayyreynolds +az3r bulbul +azerke azilim +aziz8mohd +azj azura +b a g +b a l r a j +b b o x x +b eeg +b enjy +b ezos +b i g s t +b kuz +b l u rr +b oe +b on ass +b oo n +b ooth +b u l +b ulba b-ray29 b00ty +b00tyw1zard b0btehcool +b0dybilder +b0gadu +b0nelesstofu b0rn2grill +b0urb0n_kid b1ackcoxdown b1apoody +b2bpurple b2bs +b33 rabbit +b39 b3cc b3kiy +b3rgo b4Mb00B0NGG0 +b4iforget b4nyluckypvm b5 s4 0000 bIack bIrkaoff bLeatzker +bMat95 bSteeezy bVibin bZabii +ba1tti +baIIs3 +baami +babewatch babstah babugo baby +baby peb +baby peba babybuffalo babygirl +bacbacbacbac +baccybaxter backseatrs bacodie +bacroonX +bad bee +bad boy602 +bad british +bad data badalts +badass1337 badat3tick badcold611 +badderjari +baddspella +badger fan 7 badsadmac +badtechnique +bag milk +bagans baglokale bahumat baile +baile y baitmem8 +baj69 +bajadam bajj +bak3d bean5 bakareru bakesome bakkerbtw +bakplaat11 balding +balisongg +balkare ballenbak +ballerbebbo +balsson +bam bam-BA-lamb +bambera2 bamfhitman bamsi banana bantrok +baraho barakozle +barcrestboy bard006 bardj +baritone888 +bark bark +bark f0r 0ff +barkirion rs barkmeat +baron nash +barou barry +barrybacon +barrysdad barryslet bartelbarel based +based af +bash the rat bashong basic basically basiel +basispiloot6 bassdrum bassfortexx +basspro76 bastukid +bat flack di batchela batdog183 bates batje vier batseflats +batterym1es +battlebus33 +battleman36 battried +baumannii bawky bawsi +bawz zaa +baywest +bazjunior +bbALL +bbb bbest bblood bbones bboyalec bbtarget +bbully +bc22 bcguppy +bck2kickass bcollier94 +bdb +bdw reborn +be one +bean flick3r beanbag173 beanieton beanskunk bear +bear66881 +beard3djesus beardZy +bearia +bearitimus bearjack +bearplusiron beatthebot +beaver 5 +beaver 9 +beaver win beaverboy47 +beavitte bec0me +becarius +becca boooo beckles96 +bedabin247 bedburn bedtime beech beeelake beenus42 +beer sweats beggar +behaardezak belanin belgibeer beliver96 +belizianos bellatarius +bello0 +belub bemw bendy +bengnomonkey +benisbutts69 benjabii +benjimin benjiswaggod +benlovesyo +benrj91 +benroxo bent benyatta1 berd007 berkut87 berrytrials +berseke1 +berserkbear +berserkku bertucci2575 berzerks +besouley +best bojji +betleejuice betonimuna +betty wu +beverlly beverwijk bevh +bevsteve +bff +bfxrturbo +bg s +bgs ownez +bhicks bhuffs3434 +bibilush +biccc bicycle666 +bidls bidof bieltanman +biffsy bifket +big bad jon big bojangle +big gay ig +big gmbino +big head +big man shaq +big rart +big snood big tree 63 +bigbadheskey +bigbig horse bigbigbone bigblade28 bigbluntbrnr bigbologna31 +bigboybarlow +bigboybrips +bigboymansir +bigbud bigchoocher +bigcuff bigdbandioto bigdoggtrock +bigdoinks42 +bigg bud biggest +biggest fan +biggiefries7 biggledoinkz biggreenbush biggs +bigjuicybutt bigl +biglenz +bigmoney jim bignipnik bigonevs +bigotslayer +bigpkz bigpompom +bigreddogV2 bigschlong33 bigsee bigshrub45 +bigsnail +bigspick +bigsugoi bigtuner bigz4p bike +bike trail +bilbsay bilet92 bilfey +bill one +billbosaurus +billsta46 billy +billy g0at +billy mayne billy5454 +billyj0e billyjoewo +bilo xd +bimblebunk +binaev12 binch bincho420 bindi bingels binkie +biolemonhaze biozahard +bipiee bipoc +biq pp gamer +bir d birbeon +birdieputt birkki +bisp +bisse bitten by bitter +bitter fruit bj0rne bjassen bjpc bjuti +bkguytd6 +bl00d twinz bl00dShaman bl0wMyPlpe +bl0wdakushh +bl4ckdelt4 black +black coffee +black cum24 +blackbelt blackburrito +blackedmarko +blacksshad0w +blackstyl579 blackzranger blade2k9 +bladee blaktraksoot +blame war blankownz blarbydoo blastmaster6 +blawblaw +blazar58 blaze59 blazed blazekin blazertrail4 +bleenkie +blessn bleu +bleu kayn +bleubeard bliksem269 bliksuiker blind +blind idiot +blink 1 8 2 blinkforlife +bliss blky bloQQe blobaman +blockteleing blonkie45 bloo37 blood bloodhound96 bloodrain202 +bloodredd bloodtheatre blothbather +blowmebuddy blubbystr699 blue +blue in vain +blue max6 +blueTofu blueWagonMan bluebean2596 +blueberry624 +blueberrydev bluebop blueergon059 +bluetrane bluewahfull +blunt tank +blurite boy4 blutorch blvckstvrr blynaas +bman5 +bmeow bnff +bnndt +bnqy +bo bby +bo nk bo2Lawrence bo3rke bo4r +bob bob bob +bobby ross bobby45153 +bobbyb727 bobbyitsme bobbyjoe +bobbytronx +bober vvittu +bobfish66 +bobness +bobondowski bobsushi6396 boer bofflepopper bogie297 +boglad4ket boident +boinkerton +boke smowls +boksepoeper1 bollocksed +boltwitdick +boltzy bombadinski bombycrahan +bon4ri +bonSwole bond bondalorian +bonderoeven +bonelessrice +bonfire bongohonkers bonkbonk bonna1994 boo0ty +boob boob +boob nut boodje1993 boofablebass +book of ra boom boomboom booogieoogie +boooosh +boorito boosbear +bootn98 bootylips +bootyters boratas13 bored +boring hobby born +borpxatu borsi boss +boss hogs +bossboy420 bosscat56 bossdemon88 +bossdog99 +bossedit123 bossy momma +bostonbb2g +bosway bota2 +botchx +botilabaca +botleFluff bottleo +bottn bottomfeed bottypedpsw +bounsn bouquetboy bouwjaar1990 +bouzouki +bowfa bob +bowfaaddict bowl +bowl loaded +bownd boxofbears +boxtrapgod boycie420 +boydi +boydt +boyuniverse +boz pwr boze +bozo +bp9 br0wnardRS +braap poster +bradrian bragegutten brain +brain rotted brainbusterr +branderx gim +brandom lol +bratnt brawling +brb cigy bread breakingood brecht181 bree breeze +brejch +brekitutta brett +brett 69 bretthomas3 brettiz +brettjournal brettmanx7 brettrae +brew bar brewi brexit +brian285 +brian289 brianknight7 briareus brics bridder bridgeport brika +bring ya ass brisingr vin briskyhot +brixs22 brizzle +brky +bro its hamz +brock soup broetie broker +bronson99 +bronzelvl bronzenohkie brooskii +brotha in Ra brotherkjell brothervoid7 brown brownell brownjesus brtsbrg +bruh +brushy1 brutals bryike +bsavs bsct +bskiller10 +btc btd6king +btw Im Nakey +btway +bu bla buIberpikmin bubbakush +bubbith +buckethead12 bucketnipple buckul budabaii @@ -26789,47 +55210,108 @@ budge1 budhato buds buff +buff T O N Y +buff boobies +buff outlaw +bug salesman +bugeye freak bugsijs +buhm buldog89 +bulk up +bulpster +bumbler bumpyD +bumpywalnut8 +bunchface0 +bundun bungaku +buornos +burakaflocka burlyman +burnedpotato burnindank burnsalinas +burntfish55 +burntjar burt buryafriend bushkada +bussi eater bussmandrew +busta bunny butlesha +butt boobies +butt chug +buttercord +buttonbags buup buurman111 buurtvader2 buwatt +buying ai gf +buying girls +buying sloth +buzzin +bwaby +bwana69man bxhxdir +bxmbi little +bxther +by Juddy byEmilsson +byll byrny bzerk +c a b l a y +c bro +c greyson +c h u c kles +c hainz +c j t +c m l +c o 1 a +c onorr +c rompt +c ubic +c xx zz c c-ross93 +c00lbeer c0vid c11ntz +c3h8 seller +c95 c9hype cBold cDive cFraze cMehuu +cMoney62 +cRunX +cT Kura +ca mel caaaazaaa cache cad5112 +cadeano +caesarsantin cafedenbas +cagasaurio cage cagesitter caiomhinnn cajzbi +cakemusclez cakepillows +cala mity +calamity meg calgore10 +calisme call +call me Q callbackc4ll calliott14 +callmedaddie callmeqel callmeson callum23394 @@ -26839,148 +55321,291 @@ calvo camberland cameindamail cameliorate +camellia +camognome camrbidge +can o fish +can smoker canadian canalope cancer +cancer ruin canman794 +cannot pvp cantgetdrops cantsoloraid +canyon crab +cap byakuya cap3r +cape kraken capinkiller1 cappin captn_dabbin car oussel +carbonclock carefree +carltonking1 carlwalter +carmito999 +caronita carrotepic carrus65 +carti stan +carx casadri cash pls +cash19400 +cashcache +cashflowgwap +caspar O8 casperium +cass cassa +cassidyz +cast iron 99 +cat goose +cat the rat +cat yo quack catJAMgif catdog183 +catdog184 caterpie +catgirl41 catlice catlover68 +catmummy18 cats +cats go meow catsandogs catsarepeopl catsntatts +cattierjam cattsts causey +cave zizil5 +cawn man caykk +caza +cb0ndy cbbr +cbf maxing +ccc kyle ccc kyle BTW +cccccc +cce ccoinstar ccvtw +cdryz +ceef ceerial ceh9 +celery dog +celestial177 celliott94 certifythat +cestlez ceus +cgmirin +ch oi ch00s3n chach47 +chadduker +chadmaro chadsmurfin chaffedlips chakra +chamby +champagnedon champinjon champions champrocks chamskillz +changa nndmt changemyrng +chao keng +chaossarim2 +chaoswizzard +chaps on chargnar +charliety charlyzard charred chat chatandinan +chats 0ff +chavito_mobi +chazsti +cheapscape +cheddaphile cheekraider +cheenos cheese +cheese nuts +cheese tots cheesed cheesesmoka +cheesesnake +cheesie odst cheesy05 cheetboyx90 +cheetodust cheffffffa chemistmike chemistryphd +chenswok chent +chenzoh +cherenkov +cherrygrove chessboxing chewbacca814 chewybeaver +chi huahua chickenarise chickenbyrd +chickennug74 chicknsoup3 +chicknugets chicom +chicom shill chidavantlez chie +chie na wei +chien belge +chigas +chilli chillimayo chillscape99 chillummen +chimney15 chimonas +chinchinchin chinkbox chinorondon1 +chipndale chirspls +chisssa +chlodotexe +chnged +chobby bong +chochise +chodell13 chogey chokemepleas chokemysword choobocka5 chook1e choppers +chopsbwana +chorkin +chr0nic k0 chris chriscrossz3 chrisdude +chriskr9 chriskys christimgood christinet +chronicwax +chuI2ch +chubbybeagle chubysack +chum god +chumboyee chunkydaddy +chvi123 chxpo +ciggen3 +cigonusargas +cimmins cimsoK +cindur +cinekmiszcz cinim circa445 cityless +civo cjim +cjrr3 cjskillet cjuul clabby clac clancy272 +clangy544 +clara ravens +clardiiii claryzz class1k clayylmao cleanhell +cleann +cleanscape clevesbch2 click +click boss +clickin boss +clickrtraind +clienting cliff clifsideGang +clig fish +clini +clippng +clodoaldo23 +clogs please closeline194 cloudroamer clouds +clownViking +clownsrus2 +clownzeta +clrjones964 clubsammich cluemaster7 +cmer cmiite +cmiuehye cml852 cmm6364 coatria +coats cobrafrost cobraslyer coco +coco coconut +cocoa codga123 +cody curls +coffeechuno coffeemug91 +coin btw +cojestkuwa colafanboy +colb 45 coldumber coleeeeee colekay +colemak +collect butt collessin colon colt +coltsfan1287 +coma afk come +come in bum commandrsnow +compact cat +concert conig connie connor420sit +connorkwl +connorosrs containment +content days +continental contra145 conww cookiedunker @@ -26988,59 +55613,118 @@ cookiekill cookieman cookys cooldude2845 +cooleodotty coolgasje +coolish funt +coop ananas +coozin_killa copy166 +cor tapijt cordnog core63 corgi +corgi fan73 +corgsterr corn +corn8holio7 +cornstarchII coronel coronieverus corps corpse +corpslave18 +correctmymis cosec cosineeee cosmic cosmicphetus +coszzyy +council pops +count beck +countjupiter covid covidconvict covidsurvivo +cow abandon +cow cede +cow20 +cowpigj cowpker4life cowpoo99 +cowpuncher19 +cows +cox finisher +cox for cash coxchambers +coxfcksme +coxnass +cp5 cpenn +cpt-cujo +cr ai g +crZbY crab +crad le guy cradleguys +crag slayer +craigbr-1994 craigobaker +craigs cool craj +crajan crannerz crash +crayfish1 crazecanuck crazycow913 +crazyloLer14 +crcsofkrks +creamiboi crenux1st crep +crevebach crew-z +criddd +crimsonlily +cringis khan +crinkes cripsystrips +cris7ronaldo +crisVao +crisp damage criticism critiode cross crownchyfled +crppironman +crueship cruisingmap +crumble +crunchyfrog6 +crunchyrolll crushsquid crustymcfk cruuton crybcdry +cryme wave crypto crystalbluu crzybrady cskt csramsus +cstk1Ng ctmv +ctq ctraltdelet +ctsRasta +cu ck cub1c +cubbear cubezor99 cucked +cumstrosity cunnys +cupma cupofpeepee cups cursed_angeI @@ -27048,43 +55732,94 @@ curt cus345 cuscusrevers cute +cute lil elf +cutekitten7 cutemuppit +cutepenguin9 cutetoeluvr +cutie cat24 +cutie frog cuvae +cvbj +cvl +cwazi +cxir cyanicide cyberdunk cyberyux +cyi +cynth ia cyxxa czaroiemao czechit +d arb +d e v o u t +d io r +d urrin +d y lan d00she +d0g eat d0g +d0gz +d0nnie-d0rk0 +d0rq d0ugjudy d1sh +d216 +d2n d3mot10n d4rkk +dDillyDilly dEAd0dhz dEdjamaL dXLeamXb da jiin +da ph da6god daMteG daPeanut +dab 710 +dab face +dab marino +dabaig +dabbtheslab +dabilitation daboiz daboo420 +dabs n smoke dabtchel +dad bad +dad tree +dadcoma +daddds +daddy sharky daddyfred daddys daddywaluigi +dadfcker69 +dads bulge +dadsbelt dadsilou +dadson23 daedbent +daft plonker +dagens mand dagg3 +daggry daghostwoman +dagond0rk1 +dahhyunnee dahlinho +dahlukeh dainiux2014 daisyfletchy dallas +dallee +dalunk +dalvik +damage222 damo332 dan73 +dan_hua dance dancol00 dandy man @@ -27092,51 +55827,89 @@ danielccm danielfanacc dank dankburgers +dankin606 +danklingt0n danliciouso +danny4490 dannytjuhhh danthebankid danzing +dapipelaya daprincess21 +daredevildog +daretodair darigondeath darius_v_2 dark +dark binding dark hays dark0hawk dark5pac3r darkandrew7 +darkanimal86 darkclues +darkcyco darkgirl79 darkhex0 darkjustin54 +darklordc +darkmagicdad darkness darkstagx darkxaotik darkyChao +darranegobli +darranekarhu +darranekives +darth gainz darthbuddatv darthv102 +darvan +dascarytaco dasor012 dataenz datakrash +datalogi datboi2456 +datstonerlal datweekaz74 davadof daveb123 +david442p +davidpain dawaj dawningofwar +dawnsend4 +dawocar +day of dog dayoh +daysack daystar +daystar 0-0 +daz 11 +dballl dbau +dbopp dbow4pking dbstf94 dc22000 +dc22000_1509 dcPain dcfgs4 +dcing always +dcross9999 ddSyndrome dddvlot +ddr ddsfornubs +de Fe Dad +de em tee +de metro de00 deZoet +de_rono dead +dead tee dead2Mfarmer deadazztec deadcentred @@ -27148,69 +55921,157 @@ deadmeadow deadskiller7 deadwildyXD dear +dear sleeper +dearlola1 death +death to wdr death0183 deathax10 deathchecks deathe +deathlifiron debbie +deci m8 deciphered +declaw3d +decoy110 +ded R N G +ded pixels +dedarec +dedcell +dedfin +dee2801 +deeezey deep +deepbowlz deeptechouse deesnertz deetuu +deez ntz +defblacklawl +defender3355 defenderCX degie degraded degryser dehula deivvn +dekane deketamingo deku delboy1964 delete +delete from demaguz +demerstrand +demon ssss +den n y dennyispro densenuggett denver +denver nugs denzarr +departusa deperni Jr +derdepoging derrybarry +des9re +deserved pet +desksitter despotroast dessverre desteezdubs +detnia f +detrater mi +detzy detzy +deuce +deuzzz +dev rat devils +devilz ashes +devious man devonjt1 dewsh dexaur +dexless 4eva +dfkjgkjfdgj +dfordumm1ed dftba +dg eco +dgndfgjnmfdh dgro dgwiD dharokjonsin +dhe +dhl +di Trevi +diK +diabolicdth diamanda +dibdabber33 dibdibdibdib +dickchair +dickenbals +dickfield +dickin +didak +diddy420 +didnt rwt dids didugetrekt +dieHosen +dies at zuk +dietc0ke +difjnuee +difluenz +digigrind +digimonOtis digthat diguper dikke +dikke vogel dikorbut +dilaudid dad +dilbertt dill +dill picklez +dinklebrah +dinwy dioshka +dirt box dirty +dirty rat420 +dirtyman +dirtyydan +disc o +disco sminny disdudsauf disease disrespected distracktion diti +diu nay lomo dive divibee +dixon butts +dizma +dizzee l0l +dj en sander +dj poolboi +dj roblox +dj1111 dj_khaaaled +djawns djerfen +djfistingodx djhonnyc22 +djk1168 +djm 0813 djschaum dkb15 dkirk +dlaldus +dmersaregay dmgx dmh3464 dmmeguy @@ -27218,170 +56079,340 @@ dmmskuhled dmolishall dmorgzz dmxbutwhite +dnb demon +dnd5 +do o d +dobiz +doctorbeefus doctorkrysis doctorstig +doeby1 doesnt +dog dog baby +dog rs +dog yum dog22 dogGoesMeow +dogluvr42 dogofrivers +dogongod +doing time +dokus dom1nation97 dominicpm008 +domiuxas52 dommegekke1 +don paro +don3tsc3m donaldsocool +dong bone +dongiebong +donkeykong2 donmaners donnyr2hcim +donohuey dont +dont eatass +dont relax dontiane dontpickme24 +dontsmokemid donzy doobie8 +doogleweed dookie +dooknukem3d doom +doomcat67 doominizer +doomsiclepop doorbel doors +doot scooter +dop dopa +dopey smurfy dopeyaf +doris negra dorkSine +dormanth +dorschbag10 +doteslintrrc double99 +doublecross +doublegulps +dox +doyc15 dp23wnnabe +dpi +dps7 +dr crabman +dr evil +dr smurf dr3wst3rk dr4ll1m drag drag0n dragneel132 +drago_jr555 dragonizer11 dragtom draind drakh drakonic +dratini213 draxyboo drazil7 drdrinkwater +dreads iron +dreadthefate dreamworld +dreiph +drewsky drickvatten drillbit_10 +drink toilet dripcuck drogodon +droidfarmer +droopsnoot drotRS drouzeee drphil10203 +druedainx drug_yew +drugandbass drugs drugsrbad drunk +drunk f00l drunkwpants drwilly92 drxfluffeeee dssctn +dstortion +dstroyd dsvgs +dt duby dtfmslogan duMonster +dubba z dubdubbronco +dubies4days +duckwax +dudash dude duder +dudrid BTW dudylson +duedeman duel duets +duette duff skill duffman1992 duhpho +duked +dulitrai +dull needle +dulle00 dumb +dumbass hick +dumbweeb22 +dumple +dumpy rat +dun2kaz +duncan c +dunerat +dung_eater31 dunnman +dunt +duo virgin +durche93 durgs duriol +durkology +dusp dusq +duve melker +dvnny +dwarFcaNnOn4 dwayne +dwvb +dylaaan6 +dyldied +dylodide +dymo dynastyzero +dyrachyo +dyskletiker dyssection +dyzi dzhy +dzmomolungma +e LFa s +e acc +e c e e R +e c stasy +e ji +e med e pinke +e rui +e031420e e1ght +e50 e500 +e621net eKaleb +eL Lavish eLSD +eLas eLeeT eLqTLN +eM Be +eMiSk AU eNCH ePicnicEMan +eSquence eStimatic +eXtr3Mer btw eacy eaekk eagl393 +eagle shed +easily thero easterparty easyMEDIA +eat a udon +eat my bewty eatcox +eathelwulf eatmyfries +eatmypie +eatsdonut49 eazybreazy eazygps eazyws ebbe ebijah +eboy gamer57 ecce +echo cooks +eckla ecofine +eddimunstr +eddyb edgarsjm edible +edilot +edmu edunit +eegor +eek monkey +een pint aub eenzeven eerx +eesau eetbordleeg eetuliiniBTW +efcherry +efci effectiiveRS +effing sheet +efog efren189 egcept +eggo death +eggu eggzotic egirl qt314 +egirl tile egirl73 egyptasaurus egypton egzoff ehdion ehoov92 +eiaraieaieai +eid ola +eiflA eigh +eilhart +ein Bier +einu miegot ejobs ekcivtec +ekhoplex +ekm +el Laneo +el is +el peppo +el tubo elDiablo666 elGoblino elbo +eldanari +elden lawd elder +elder jam +elder poul elderimpking eldestlance +eldrich ball elefantsrul elfje185 elitharion +elkcarc elkcark +elletwo elli +ellias elliott1650 +ellipsism ello ellran elm43 elmeroguero elon eloquent +elsieh +eltomatero12 elyaxo email12345 emaq emaru emaw emiiru +emilviperHIM emilyqt666 emiracle +emm +emokid93 emopapi emptyhead emptysoul88 emuulzzz emvelienenko +en Au encoa endless endlessgrnd +eneco enemy2mad269 +enen energymango +eneslannn +engrave +enjoiskate enlmatek enlot enneUni enormousguy +enservices +entiesman envetoids eocri +eow btw epcr epic epickayle @@ -27390,62 +56421,123 @@ epocsorekiM eptul er2002 eraie +eric verdonc erik020 +erikj20 +erilthil +erk is cute +erlendolstad ermer +ermer fudd ernestoch ernieK erniethecat +erpponen +errikkold5 error +error nope +error occurd errorwithnam +ersatzquatch +eruze ervin +erzin +esc eseeg +esportspker espress +esssaa +estra jen +eteelS eternatus etha +ether-or +etsii naista eujamaispkei euonym +euphoria btw +eureka 4 euxy +ev tesla evanthenewb evidencez evil +evil drudge +evils ault evirgin evoL evol evonaabi evoshiva +ew its paul +ewechoose ewenn ewgility +ewmu +ewvn ex0dus ex_shadow +excalipoodle excitedz exila exile exodiass exolyte +exp waste 07 extesyturtle extinct extra +extra big pp extrastark extratrippy +eyes fire2 +eygs +eyniss ezAce +ezzychu ezzymc +f a r r r +f ainted +f c gee +f d b +f ern +f q +f r o st y +f reS +f0r 20 f0rbes f0rev3r +f0rzca f1elder +f1ll2 +f1oh f1sh1ngcrazy f2pkiller420 f3n1kz +f41r unknown +f4az +f4fight +f8 fEmshi fJack fa1lure fa2kil +fa43ws5gdrxn fabsku +faceeee +facehunt fadc2 failbloug +fairies ring +faiyaz911 +faka jackson fake +fakeironman +falcon30040 fallen fallenbouse fallengodxx +falneek falsehope familypp22 famousbutnot @@ -27453,61 +56545,123 @@ famousdavies famwell fan3to fancybunny84 +fanof +fanook kill +fansh +fapital one +fapyqt +farmerman111 +fart taker farth4lyf +fartypants64 farva5001 fastfoodguy fastsalmon34 +fat bish0p +fat miso +fat n ugly fatalzgs fatalzick92 +fatblimp +fatcactus99 fatdabz fatdemon +fatfish44 fatiimma fatpapi fatrat095 fattig fatty +fatty_ironmn fattymcthick fawaka fawkin fawnt +fayeuk +fayfey fazIlioilol fbah2 fcemee +fdegierr fdsd +fe ar none +fe fi fo ben +fe fleton +fe hessu +fe shredder +fe unclefro +fe-ma-le +feaker fearma +fearnooaths +fearsome +fech +fed the rat +fedposting +feed water +feet r neat +feet shui +feet tickle fegorus feinkostbob fellman250 felsic +femaledhide +femboy fever femiketyson +femra fems +femtanyl fenimore133 fenty +ferbies +ferderb fergina ferkyy fernezi fernibosh +ferric thane +ferrotopamin +ferrousnub fettnerd +ffa btw +ffakin roids +ffs cmon ffun15 +fghtmeirl +fhb ruby fhisher9 +fi1LMma8Ke7R fiddy +fieryflame55 fifiz +figey figgiolly +fighter8888 fighttme fighu figit fiiks +fiishcat +fijurgt fiko +fikset fill2 +filma kraken filnrozdor +filthiefrank +fin hupu final dip finalkid finally +finance king +findmydog4 finerunes7 finfinnegan fingerd finn fire +fire skull99 firebrotha2 firebwan fireflyman3 @@ -27515,67 +56669,145 @@ firemadara firewood149 firework19 first +fish cook +fish slut34 +fishbomb83 +fisher ilhan +fishfiinger fishnforfun fist +fist n twist fistaah fistofzeuz +fitjamal +fixedmanose +fixx ur face fizoo +fjuc +fk bud +fkMushrooms +fkWiiz fkn seale fl0ppy +fl0rals fl0xen flabb flaccid +flacidzillaa flaggeding flaminstu flapdrol2000 flatbroke +flatjack78 flatpancakes +flawskee flax somker +flenis +fleqk +flexmaniac flexxygreen +fligh4 +flimzzy +flink1145 flint +flip555 flipdoggydog flipouu +flipperkid69 +flke +floch floie floopily +florda v2 +florida1992 flow +flow states flowerbunz +flowers +flowerworks +flowing past +flpi fluffy +flunkerr +flwc flyingfather flyingpigs +flymouse +flywoodhead fmPalm fo77y +fo_of +focusor foldoutchair +folklore +fondledeez fonytergus0n food +foom +foookz +foot fe tish footbag +footgobble9 +forbiddengol forcestealer forevercc +forfun_ED +forgeleader4 forkheals formazion +formerly act fornitesweat forrestriley forss1 +fortnitecuum forty7 fortyfour44 fortyfours fotjonxd +found RS2019 fourecks +fowrt +foxMcCl0udd +foxair foxdude909 +foxi melissa +foxmr2 foxological +foxspirit foxxit +fp fp4bank +fpsbowser +fr0stys fr0zen46 +fractalion +frail +franklinzule frantam +frawzti +fredz1 free +free rations +free willy1 freeheadbutt freekek freekface99 freepknub337 freeze4peeps +fremenik +freshaf +freshdougie fressi +friccSailing +friday x +friedz friendlyduck +frierenfan69 +frodobaggens +frog37 frogggggggg7 frogmeme420x +frogposting froock frootl00p233 froppy @@ -27583,147 +56815,269 @@ frosteazz frostfire089 frostkatss frothsy +froxey frozen +frqke fruitdeeps fryguy20 frzen +fskencha219 +fsnack fsteve fsxd ftSlimShady +ftmg fubar fudkingname +fuhrari fukduelarena fuktig +full service +fullrune383 +fun e name +fund issues +funk +funk it funky +furi xD +fusarium5 +future days +fuwamoco fan fuzzlumpkin fuzzydenuts +fuzzypapi +fuzzypupz +fwapdokopjai fwft09 +fwip fxck fxck versace +fxdb fyfaen +fymcgee +fyr irony fyromaniac +g arre g o o w +g u L z g00dz +g0_ober g0d slayer19 g0dofgames +g0dz target g0ld +g0rgelzak g1g1tyg0o0 g1n00tj3 +g1o +g4rug gIassy gOWObs +ga zr gaaaaleth gabba-jabba gabbe314 gadnukB0W gaffel +gagifidi gaht +gaht dangit +gainsaid gainz +gainz no gainztrain9 +gallidogs galx37 game +gamedbroski gamelsbad gamer gamer63738 gamerb0y +games sheet gamesalright +gamin hard gang +gang gastino ganger34u +gangstersfly ganjah lord ganoze +gapin ass gaping +gargalonmyd +garn woolies +garra +garymunzen +gas watah gasang +gatekeepr gatlin +gatorbait61 gatorclue +gaumcat14 gavin +gay avenger +gay corn +gb +gd5 ge1uk gecs gege4646 +gegebee geitz4 general_a3 generalneos genghys +geniuswinner gentle geof +georgemonger gerdlol gestrikt +get pregnant +getcance +geten30 getpixelz getsnipez getting geusjj +geve en neme gewoonhendri gezzle +gfink +gg Goombas gggochu ggremlin ggroeffus +ggrr ggwpezgame +gherkins +ghliz ghost +ghost of CVS +ghostlyjon ghostmahi +ghrimdrakan +ghxstboy gianni025 +giannnnni giant giantsbane10 +gibsons dog +giffnamepls giga +giga zooted +gigglybear gijsro gilgir +gim Bam +gim ajuin +gim so bad +gimeurgpm8 +gimhunter02 +gimmey bear +gimpeta gimpinator14 +gimtmbj gingasnapz +gingerr ginjembre gino2315 gintoki +gioh girl girlbossed girthing +git gud kekw give +give in +give me 1 gp giveortake givmemonyplz giza gizmywizz +gkfdhsjbgpas +gl barnie +gl gf i win +gl lmfao gl0s2n gladwin97 glazura glgl glica glingster +glitch1128 +glooboowhoo glotis420 glowmastree glumburger +gmac33 gmtn +gnak +gnariska gnarrrkilll +gnobo +gnome pegger goGETTER87 +goal freak goat goated goatflocker goblinsyler +gochugaru +godblaster69 godfreeB godmiljaar godmysavior godofvoid +godsdankweed godss godver +going2maxnow +gokhanakan goku9172 +gokublk409 golaguard +goldenN0B0DY +goldest cat2 goldiepawper gomikasu +gon dor gonarusinat +gone numb +gonewild gonsoLE +gonz o good +good duck 4 +goodboi525 goodlife +goonette goontuna gooootsby +goos fah bah goose goosegoose22 gor7 goranfr +goreshitfan +gorgewkush goroka +got u m8 +goth mime gothic gothorian gotmadtree gotoschool gottaRash gotzeeben +goy street gp294 gpawshaft02 gpf93 gr0ve +grace life graftosh gramss gran chorizo @@ -27731,310 +57085,648 @@ grandp4 grandpa grandpashome grandslamhit +graphist II grashuis +grass hopper gratis gravetheif +gray ass +greasy bacon greasyguy19 great +great bazza +great blazer +great keith +great pkay greeaf green greenbuds1 greenfleet1 greenie14 greenm4444 +greeny4 +greenzyyy greg +greg btw grey +grilecheese +grillmagnum grindin2bond grinschen grizzy77 grlobe +grogybog12 gronoc +groogns +grossedinde6 gruelsipper grumpyy +gt i gtrpower3 +guardy gucci guirkle gularies gulibleidiot +gullefjun2 +gulp my knob +gumlord54 +gunbladelh gungaman3 +gunnmoses gunnybear gunzip +gurz guttsberserk +guuvin +guy123452345 +guyfranklin guyhasaname +guyladriel +guzzlinbrews gvfsa +gwaph gwaphics +gwapo gwapo +gwb +gwen-artemis +gwiffdakid +gwogoudain +gwug gypzys +gyxl +h ertog +h re +h ugo h00cares h0rseZ +h2j h3hz +h4h4h h4ndshake +h8browns +h8dip +h9g hEAdGLiTcH hOsujaRS +haaksrikko +haam habitus hacchi hackening hadibaam hagerlund haha +haha lul +haha nice xd hahaLMAOlol hahaa +hahaa-ukko hahaha +hahaha LOL +haiiG hairahcaz hairy hairyraccoon hairytaent haistavittu9 +hakuikoyori +hakumaata halal +haldfhaklfa2 half halfcrimp +halfrightfox +halftimegod halling1 halo +halo 238 +halo is scum +haloumbs hamdrip hamers +hamhand hamilton +hamilton fan hammade hammershark hammu666 hamptonboys hamthenoob hamzullah +han sohee hanakarjala +handi 0_0 handi9900 +hangry_bird hanh +happi hippo +happyprophet +har tig hard3x hardcoresque +hardstuck gp +hareby harelmatlaw1 +haringbata hark harleybegum +harmony +harmony w harrpp harryderoest harts0295 harziol +hasansahl hasbulla hash hassbulla +hat foe +haterz havfherter +haw yee hawkesbay +hayati enta +hayden787 +hazel nut +hc pilszen hc_karadeniz hcgoldslaye +hcim gud btw hclirongang hcmemekiller hdhd +he a 1O but +he box jonge +he r b +he4 +heGee hear +heartvessels +heast oida +heatassnugs +heatwave305 +heavygim +heavyiron94 +hebrewmytea heca +heckn frick hedonismbot +hee haw 255 heegeer heel heelgoed heeming heeyhallozeg +heftZEUS hehe +hehe heheh hehehehe hei954 +heimy22 +heizenberg11 helgrimm +helicopta12 hellobob488 hellofpures hellohello +hellohelloom +hellper hellreaper25 help +helpa +helpusobi1 +hembree +hemmingsson +hemmy +hemran +hemstad henkka89 henkleingeld +hennnin henson23 henzer heppytako +her mager herb +herb btw +herb l0rd +herb l0rd jr +herbdean0981 herbi herbibear here herezacsko herkimer heros +herrasmies68 +hesedona +hesi pullup hestakuken heuj speulen hexergeralt +hexxers +hexzie +hey axel hey im ben +hey its zul +hey_imgrump +hey_rayray heywoodya +hh r hhdrgu +hi im miku +hidde xddd hiddeboven +hidesonkush hidlandboys high +high bonsai +highIMcamila highelolux +higher man +highfly94 highprice +highright highsassy hightoo99 highventure +hih hiiggiinss_5 hiirihaukka hikipastori +himokarpaasi himself99 +hiphopdied hipocracy +hippofart27 hippyjump3 hippytrippin hirai +hirai momo his7 +hit trees hitchclimber +hitsumabushi hitto hitz hiunknown +hiya jase +hizli maymun +hlen +hlua hlucky hm08 +hn k +hnge +hnsky hoangbach456 +hobbit head hobosloveme +hodl link hoffnungslos +hol my got holdadoor holden21 holdenrulz6 +holidayRus +hollowking holonomy holy +holy chad +holyfizz holypalo +home2get homestank homie jaquan +hompkerbenis honda honeywheat honourpig48 +honscy hooah89D hooliganism +hoonyboony hoosier4life +hootis4 hopOFFbish +hopeakettu25 hopeless0ne horkkaaja18 horror horsedik7 +hos hoswoo +hot otter hotdogmum99 hotpants +hotyogapants +how 2 use ge +howliett +hows it garn howyadurrr +howyodo hrby +hrsn +hs +hs3 huang9296 hub154 +huealldaym8 huge +huge cog +huge man big +huge ovaries hugh +hugh_who +hugheberto hughjazznut hugjam02 +hulikopteeri hulikopteri hulken532 hulrikon94 +human6000 humble +humjiboi +hummerspeck humpmedumpty hunden +hungrypit hungwonglow hunter +hunter01132 +hunter123216 +huntin_pets +huor4hansu +huoranpenska hurt +hurtswhenip +husbandowo hush huskyheaven +hut dugs huutonaurua hwow +hxdd +hxzy +hyasf +hycoda hydra hydraboss hymke hypez hyphynx +hypofelix10 hyprmax hyung +hyvintoimii hzpascal i 0nly skill +i Bmx +i C D +i Kelly +i Kyle +i Shin Chan +i Spartan i Stugbert i +i URNn +i Val +i am hua ren +i am iron xd +i am nickle +i am rocky +i am soo dry +i bets i +i ch i +i dandy +i dcd 4 sets +i disabled +i done +i eat noods +i forte +i gag +i gor +i got dust +i grug +i hit 420z +i i i i +i john 96 +i look great +i lose gp +i need top +i need you +i ok can win +i poop alone i praise mvp +i preferhead i r muffin +i r4piid i +i ronman +i vexterr i-i-istutter i0 strength i0am0the0one +i126 i2eally i2legit i2me +i3nd Legends i420u +i50 +i8 2 l8 +i9 iAIex +iAM Pleb iAUSSIE iAdriaan iAlch +iAlchedNieve +iAmNotSharky +iAmaWiseAss +iAmen +iAttributes +iB Lifted +iBal iBallr +iBeDorky iBeanie93 +iBeast It Up iBeatNavy +iBeleti +iBelg +iBlack Zeus iBlake +iBloodsicle iBlurks iBosstastic iBoughtpizza +iBrandon iBukowski iBunZoot +iBurkie +iBurn Dro iBustedaNUT +iCakoRS iCarna iCbarr93 iCh0sen +iChangeling iCheezedOff iCheze +iChugBleach +iCiga +iClickYellow iCmurda +iCoconut +iCrank a lot iCrash +iCreeme iCyantist +iD Dazza +iDH +iDabbedOut iDan iDanny13oy +iDark Jesus iDashio iDashwood iDeathlok iDerpo +iDez +iDo RageQuit iDoNot iDontWinSad iDrankCOFFEE iDrebin +iDrexler +iDrops +iDuiveltje +iElfy +iElysian iEmery iEpa iEprod iEuph iEuroVamp iEvergarden +iFailAgainnn iFatalFoei iFerrumMan +iFeud +iFightClouds +iFightGiants iFire +iFoRGe +iFrads +iFradz +iFrogs +iFry +iFucter iFukFatChix +iFurb +iGab +iGarns +iGlaceon +iGlitched iGlowGreen iGohan iGotDds +iGotDibs iGotem iGreig +iGuDMaFF iGuessUrNew +iHazelnut iHenrie iHenry +iHiyori iHockey +iHolydude +iHuntie iHydroxity +iHydroxityv2 +iIimesiahiIi +iJ0HN +iJ4CK +iJCLEE X iJake iJamPancake iJesslag +iJezuss iJfr iJohn +iJomm iJwu iKHole iKILLN +iKantu iKarl1s iKerry iKitch iKitz +iKonijn iKoning +iKozak iKristov iKurko iKushUp +iLEFTmyGF4RS +iLL Sushi iLeftHer4XP +iLegacyX20 +iLetaker +iLeveled +iLikeTacos +iLikeTheStok iLikeuAlatte iLoner iLove iLoveYou3OOO iLuckout +iLuv Pandas iLuvMyMilf +iLuvSubs +iM3RKEDu iMADbro iMahjarrat iManiac +iMark 1 +iMarkl iMartin11 iMatey +iMeeger iMellek iMelli iMementoMori iMeo iMichaelN +iMikail +iMikey +iMogUCope +iMotown +iMushh +iMuste +iMx +iN3K0 +iNamaste iNeedBeaver iNeverMor3 +iNewbcake +iNewton +iNibble Bats +iNz +iOPeveryday +iOhmz +iOsmumten iOwl iOwnU4ss +iP1 iPIMP iPKedEpstein +iPacmanSam iPaki +iPalumor iPatrickN iPegAsians iPerfectoX @@ -28044,6 +57736,7 @@ iPink iPlugg iPod iPop +iPray_Guthix iPresident iPunchCones iPure @@ -28056,9 +57749,14 @@ iQuittedCiao iRNGizzed iRekt iRepToronto +iReue +iRev Man iRezlo +iRoN cUj0 iRoNmAnSdUmB +iRonAllot iRunTh3World +iRunzo iRycoda iSaran iScape @@ -28068,115 +57766,255 @@ iScream03 iScrewedUp iShibby iSkane +iSkript +iSlay Girls iSlayCookies iSlayGoat +iSlenderMann +iSmashUrGF iSniffCows +iSnowmobile iSoulReap +iSpare iStayLowKey iStealSex iSteele +iStick2Corp +iStonee iStream +iStreetfight +iSuhdle +iSwarly +iSweat +iSweatyYeti iT0m +iTan +iTaz +iTed2cold +iTheDarkKing +iTheodore iThiellie iTisk iTmetzo +iToxic +iTrin iTunder +iTw1sted iTyler +iTz Command +iTz Frosty +iTzBoo420 iTzGoinInDry iTzKATalyzt iTzSnypah +iTzTurtlexD iTzTyLeRXD +iTzWho iTzZ +iTzxLiMiiTz iTzzVanquish iUberz +iUsed2Corp +iUub +iWilkel +iWillz +iWithdrawal +iWonderWhy iWyatt iYahwehi +iYellowClick iYunis +iZ4 iZorru +iZuny +i_murder_bh iafx iain19 +iamAFK iamCanadian iamMcLovin iamfish +iamfried247 +iamfuss0100 iamgreatrng iamlucas19 iamonfiyaaaa iamperkins +iamvery cool iamvoldemort iamzed +iandrehehexD iateyourpie ibbenbueren +ibn Mukhtar +iboomedyou +iboyfly ibr4him iburythebone +ibushmani ic3d +ic3d c0ffee icannotboss +icanread321 icantspelle +ice beam +ice juice +ice-nine9 +icearrow28 icebolt19987 iceburg189 icecoldbreez iced +iced marbles iceman000 icewall0w +ichau icjbi +icky sticky icutL0g5 +icy ded ppl icyT icydilldos +icypolarbear +id c +idc idcy +idfap +ididnthither idiedonmyhc +idiom idiot +idiot game +idiothead +idk chill idkgoogleit +idkh0wtoplay +idkwhatdo idle +idle1 idpoen idrater +iduggz10 +iekaajer iekgaa +ienai +ifantomas6 +ifarted42000 ifootfondle +ight igiddeni +iglo16 igotdaice igotnolifee igotnoolife +igotwingz igotyour99s +igrimmerz +igugh ih8urkind ihan ihaveanxiety ihavitunopee +iheartBBLs +ihopeurope +ii Sahir ii +ii am teaser +ii bad guy +ii forte ii +ii love cats +iiBink iiDivine iiDrackidii iiGallardoo iiHydra +iiLuckyVibes +iiTz Nothing +iiZEEii +iiZno +ii_TrYHaRd iiaannaa +iiiRood +iijelloo +iikasoyi +iimperious +iinsin iioktb iirc +iitsjarod +iitz deebz +iitzz Ryan +iivy11 iizoneout +ijoinedthis ijust ijustgotreal +ijzer ali +ijzer vreter ijzeren ijzerenman1 +ik itachi ik ikea ikeep1r0lled ikil ikillstuff +ikiroz ikoyouboy +ikp0wnsz +ikpakjou ikrr iksalion iksd iksdeee +il malocchio ila161 ilapaR ileax ileft ilegalTruble ileppmot +ilfi ilike2gamble ililliiilli +iljang +ill Dottore +ill-Money illadelph illenials +illisible +illmaister +illmatic +illmindhop5 illotex illumea illuminavi illyreia +illysia +ilookcat +ilovecitywok +iloveinsulin ilswisa +iluvducks +ily stepmom ilyakchuk +im 1v9 +im Jaacob +im Noah +im Z a n e +im a learner +im a pur8 +im at cox +im bad tbh +im batu kham +im cats +im dandy +im huge +im in charge +im nlf +im pogging +im ruben im solo rose +im tr4vis +im ttZ im4everxerox imAcidic imAhri @@ -28187,123 +58025,302 @@ imJT imNEWY imPapu imStef +imWebby +im_pro_jones +ima big boy +ima survivor imafatscaper +imago loop imaybegod imbaconyum +imbueddog212 imbutz imbuyingf +imcahos imcaprise +imdrunkashit imdud +imfi imflavio imho imhuge iminarager +imjeremy +immachin +immaturely immef +immirgant +immmersion immortalz +imnotdani impaired impartial +impek +imteddybear +imthenalls +imtogepi +imusualyhigh +imzahikell +in africa +inSec inTheSlum +inb4elysian +inc incant +incci +inclibe includingtea +ind +indebara +indian inescate +inf nick infamousO775 +infamousjew +infare +infernalwhen +infessian infragant +initiator iniu inject +injinourme inked inldgwetrust innSink +inner child insaned17 +instagation +intja intwystis +invictecum +invirtua +invisybl +invynsable inwervs inwnucleus inxx +ioe iojerfwpjiof ioliteKnight iolm +ioncolliderz ionlypickadc +ionman iorcsrox +iownw69 +ipfreely939 +ipwnkthxbai ir0nschlong +irak93 +ireq +irhunter +iriee NZ iron +iron Dreven +iron Fapkin +iron Nido +iron bewts +iron carly65 +iron chur g +iron colb iron cuzibro +iron d +iron dafanek +iron dumle +iron evoo +iron gariks +iron grogu +iron hobbs +iron i jad i +iron imp 89 +iron kobe +iron kydrol +iron mazie +iron nakno +iron nkellen +iron sfgiant +iron snak3s +iron snurd +iron t2 +iron te_un +iron to main +iron tylerr1 +iron veil902 +iron veyydot +iron vow iron xarcher iron0 +iron0_o ironBellukka iron_day54 ironandwhine +ironarrow ironbandiit ironbass +ironclimber1 irond ironderp +irondude686 ironerextion ironerrosann ironeye +ironfara +ironfather8 +ironfyi irongaga +ironguxiz +ironhuuu +ironic it is ironikcronik ironinfinite ironjssnoob ironjustice +ironjutku ironkendall +ironkevkev ironlizrdfuk +ironlog215 ironlooks +ironly fans ironmortel85 +ironoujust ironpower29 ironpuni ironskunkki ironspig irontsuki +ironvesku ironwortel ironwoss irradiated +irregularly +iruste +is an option is skimpin isCatrileo +isayswegyolo +isleepwith3s islugo +isoPROpain istealyoloot isuwu +it do be +it ends now it0b it0keup itachi9113 itbch +itirof +itisdre +itmeautim +itroy v2 +its Bread +its DeFib +its Hoffman +its Knetter +its Mewtwo +its Polle +its a ginger +its aight +its an 8th +its leviosaa +its not mine +its the game +its20after4 +itsAden +itsErnie itsGLD itsJayy itsNoki +itsSt1cky itsWum +itsa itsa_feature itsaart +itsalic +itsbenny itsbill +itsdanlol +itself +itsfwhobar itsmewarreng +itspajamaday itsthedirtyJ +itwasme ityttmom +itz Ozie +itz Tastey itzjaycie +iua iusedtosleep ivao ivibondivi ivlr +iw iwearIRONirl iwinulosety +ix7 +ixGOONIExi ixJake ixoniron iyyghg izmibence j e company +j o h n z +j o l s +j sta1in +j uddr +j wet j0rd +j0rdb98 j0shNZ +j0shwah +j1nx +j311yb311y97 +j3ffmaill3 +j3rvi5 +jDaledge +j_mes jaakqoo +jaatzy +jackBingus jackLonghorn jackancoke7 jackjester +jacksonlol +jacola +jae Bee jaguarundi +jagweed +jagweedle jahan +jahmelo jahnjo jahrezeiten +jaitt075 jajademonrat +jajajad jake92 +jake9549 +jakeyvil jakkaru +jakste r +jaksterlite +jakuusa24 +jallon jalucox jamaz8 james1234269 james68889 +james9f +jamesishere +jamesw jamflex +jamgyo +jamie g 456 +jamjarrrs +jamm janguy jani jankywanky @@ -28312,50 +58329,104 @@ jaq0 jargonship jarjoevis jarngrimre +jarno561 jarnrisi +jarnwoodchck +jarsko jaseDemon +jaseGrumpy +jauu +jaxta +jay 6ird +jay oh kay jayst1n +jayveedee jaza +jaza maxwell +jbirrd +jd345 +jdockett jdore jdsgsxrthou jeREEEEEmy jedi +jeeeeee jeep jeezuschrxst jef skhiii jeff jeffswifty jegerklog +jehhjr jekkujaba +jellyfish49 +jellyjam20 +jem is cool jerome +jerrys ags +jerrys venny jerzieboy18 +jesjesjo +jesus bone +jesus vape jesus4gives jesusiswrong +jesust +jetalexnder +jettyrr +jewellski jewjoking jfan +jfc +jfrank127 +jfy +jfyulopaef jheezuz +jhinnessy jhonlee48 +jhoog +ji mbo jibmask +jicc +jigx +jihal2020 +jikrak jiksee +jim jones it jimbob1 jimbobeda jimdeut06 jimmy +jinjji jippey +jjammerweer +jjerrbo +jjingx jjpanther95 +jkfizzy jkre jkthekilla jman +jmjmjt01 jmusilli11 jmw1031 +jndi +jnjo +jnlffs +jnyjny jobljobl123 jochieboy6 jodilynne +jodo wollos +joe the pop4 +joepie +joestrider2 joey0343 joeyisstoned johhny2hatz johndalton95 johnnyandtam +johnsmain johnstaLoL joje9 joji @@ -28363,7 +58434,10 @@ jojojo357 jokaranpampu jokemyster jokerpoker +jokkefar jokr +jolle rmm +jon ko jonehehe jones jonk33n @@ -28371,56 +58445,106 @@ jonko jonnetuinen1 jonnywormy99 jonppeli +jonwillbert +jonyants jonzii90 joohhhnnn joop59 jordaaaan jordlar jords +jordy8878 jordymans jorfee +jorge w +jorma heat jortdebonobo +josheroni joshuab98 joshy872 +joshykun uwu jossejoks123 +jossiee9 joster jouv +jovic joygi +jozn +jp s +jpjpj +jpmonkeyboy +jpruee jqzz jre257 +jrwheelyy +jslashk +jsoaksdawg jstrot jta1992 ju1ce +juaco torta juan09gon jubbediah juggernaught +jugiwow juice juicy jones juicyj03 +juicyjoystic juju +juke +juketsauli13 juks +julia uwu jullbrew +jumpe jumpshot7 +junami14 jungle jupi234 +jupilersjuk jupl234 jusiuke just +just living just2own justJust justLush +just_willie justamemerr +justaname20 +justapethunt +justarabbit +justin5454 justinttu +justluxy +justsomenoob justsomewood justwin4head +justwitching jutku22 +jutmeister juwgrehg8w30 +jwalty jwheaties900 +jwles jwov +jxdoo +jye2014 jynzziii jyripetteri jyyhnas +jzhua jzm0 +k a p s +k anao +k e y e r +k ep +k ian +k oga +k u h +k um man +k-rock94 k0ed y0oh k0mpact k0nch @@ -28428,73 +58552,145 @@ k0nna k0rrup7i0n k1dnam3dcud1 k1lla +k1lla cam +k1ngzinho k3yblade +k6k3 k80may k9k9k9k9k9k +kFlipsta kMikey kUwUmiko +ka r el +ka vi +ka wa +kaaf kaali +kaalwo +kaaskrok3t +kab000m123 kabal1995 +kacy +kaffetime kahleparta kahvi kahzaohimark +kaii tangata +kaimann kaiokenz +kaizen1 +kajyboyyy +kak_kis kakes kako666 +kako666 ii kaksaking +kalacaodan kalev +kalijaveikko kaljunaama kaloopsia +kalusto123 +kalxb kamekazi +kamerucito kamika kammoooooon +kanchazi +kandids +kanga roe kangaroo kannv +kanyefan22 kapot +kappachino +kappaross420 +karambamb karelzzzz karibola karil +karilol +karma dies kaspery0 kasperyo1 kasrug +kassi kastekann007 +katelate +katiegore katinnekke +kavachi kavinskie +kawasakki kawi kawkky +kawnoz kaynori kayxiv kbest777 kbuns +kc3 +kc3477 kcaaJ kcmeatlover +kdani +kdawg710 +kdog420 kdw27 +ke-bun keatonboss keegan789 keekluulz keep +keep going33 +keepitdedpls keesie7 keezuth kehd keilaaa +keiniks keittokinkku keittoo +keiwa kejo kekipua +kekw9001 kela +kela fan kelan +kelan miehii +kellapea +kemabi kembot +kemosabi kempster8 +kenchuuuu +kendawwwg kennynoodles +kenya help kepijuku keppuli +kepwontmax +kerekewere +kerm jump kerwin +keskorian567 +ket boof +ketaccino ketawuss ketchupfles kevin +kevinator41 +kevinnnggg kevpurp +kevvaGG +keyggre +kferd +khaki cuffs khxn +kiba420 kibeleza +kibsy kica7 kickback kiddoseta @@ -28502,98 +58698,166 @@ kids kidsteve18 kidz kiefcheef +kiiiiiiiiid kiix +kil lu a kill kill3r killah +killakristy +killanoob93 killconey84 +killcrab killd0zer666 killedual0t killerline +killnack killthatree +killwi5e killy kilpi +kimachevich kimbo kimpsa +kinako4 kind +kinda soft kindaanxious kindocool king +king lee166 +king stuff1 +king-tiddus +king420smokn kingblackops kingcuzh +kingdaddyIM kingdale26 kingerr +kinghrvatska kingknightf3 kingkong1211 kingofmanse +kingprince kingrizzla2 kingsardine9 kingsje kingswood kingvoid1083 +kinky fish kinobi kinzyyy kipitril kirby421blzt kire7693 +kireeh kiri2kun kirkaye +kirky 127 kisipicka kisses kissmyassetz kitashan +kitkats GIM kittymeow556 +kivipaska kiwidson kiwie +kiwiibear +kjekken kjellingeee kjeltringen kjems +kk lol kkDV kkangaroo +kkarl kkjamin +kkman45 kl00g +klaaore klacen klampo +klankerclean +klassiskt klef +kleshkebem kleu klexosfox +kleyver22 +kliefhead kll4mee9 kloh510 klojo103 klojo105 klopt +kluizen klycko +kms fast lol +kn0ws beers knani +kneel2me kneeslapperr +knickname +knifemanha knight +knightnate8 knobb knobby knokro +knotts knox kodakid98 +kofelad +kojak1211 kokimon kokinaattori kolb komari_k +konar simp +konb konch99 +koning broer +kontiainen +kony +koo de gras +kooks only +kooltrickz +koronaaaa kosiq koudekroket kounga koyhalaulaa kozel +kozina +kozzuu +kpt +krZ +krab meat krad +krakenwsn +krakim krakkakkak krakodile krat +krazyfaken +krb 16 +kreepingdeth kreeq +kreesie +krewl krikenator krillzscape krioyo kripu krisaaferfi +krnjellytv +krobi kronicganj kronopes kroodjebaass +krp +kruizin kruuuuben krxW kryptocookie @@ -28604,157 +58868,344 @@ ksubbi ktsmo kudryavtseva kugelencas +kujan2 kukerino +kukko soosi kukrishikari kulers +kulers bsk kulju kulso kulwreck +kumiko okada +kurasaki21 kurdikana kuro 275 +kuromi irl +kursa sucks kurtebener kush +kush tacos kushmas +kusib kusimursu24 kuvaiti +kuwait333 kveemanne kwak +kwak eend +kwall +kwarkje kwdn kwinus +kwuantadyme +kxde +kxlle +kxzu kyaa +kyanochaites kybl kyfu +kyle of pvm kylehwog kyles kylop kyssysmeua kyurem_vrah kyykanhenki +l Am Mathew +l Athena l +l BTW Envy l +l Buzzsaw l +l Click l +l Darken l +l EARN MAN +l Elija +l Fam l +l Feather l +l Floss Fish +l Flynn +l Freya le +l Hav Ligma +l Kelpie l +l Killua l +l Lena +l Love You +l Macca l +l Misfit l +l Mister l +l Nz l +l RSK l +l RWT l +l Snus l +l Steph l +l Succubus l +l Sw0rdm3n l +l Viz l +l am RON +l am cute +l cup +l failex +l lemon +l u g i a +l unchbo x +l-LEVY-l +l-Relinquish l-l-L_l-lL_l l0H3aV3nLy0l l0ne0ne l0rellai +l21 +l23 +l33tsuperh4x l3LACK l3W0FPI +l3en l3enjie +l3ezzerk l3ishop +l4n +l5h l7ivine l8tenite l995 +lA R R O Wl +lAlexAnderl lAnomaIy lBaecob +lBakin lBrent lCEBERGSLIM +lCONlC +lD an +lDFC lDalel lDanilo lDark +lDark ice lDerby lDezzy lDokkum +lE N VY lGuess lHawke +lHong Kongl +lI pv M l +lIHlIIlHIllI lIIIlIlIIII +lIIlllllIlll lJWl lJoynerl +lKanel +lKeith +lKenna lKenny +lKlas +lKyle +lLY Harambe lLewis +lLupo +lM Nathan lMarkl +lMercyl +lMr Zaros +lNSF +lNTOXlCATlNG lNerdRage lNolan +lPaleHorsel +lParticle lPeriphery +lPoe +lR0NM4N lREKEEN lReece +lRossy lRyan +lSaiyanl +lSellFeetPix +lSkinny +lSlayer +lTS ON SIGHT lTedl lTextbookl lTlTITlTlTIT +lVIaGiK +lVictorl lVitor lVlango lYungPlaguel l_Thunder_l +l_wyverns_l +la flare +lacefield07 lactosebad +ladsquiron lady-yoshi78 ladyspartin +lafreniere13 lagamuffin +laggium lakde99 +lakey peak +lakeypooh laks +lala u death lamJason +lambar lambreturns lame lamepun3than +lamironben lamshnarf +lamyourdeath +lanch +lanthe +lapyflapy laqsative lardosio large +large moist +large nob large pox +largewillow9 larinen larl larsbeuk99 larsnjun larvacorium lash209 +lasseboi last +last katana lastdcplz lasyy +later gater +latinamx +laughingbisc laura +laura froggy lawkingkong +lawo1 +laxasia lazarus +lazy aiz +lazydj2 lazyhitman lazzabazza11 +lcefiend lckle +ldy +le iromax leafsevens +leak organs +learncox123 +least toxic leather74 +lebanon d0n lebusoft +ledy0710 leech +leech iron +leech keeper leechyGP +leehi +leesha locks leetjojo leevi22 leewhiffy leewi leggie +legioen +legionbgbear leglizeRanch +legn-dary legohuis99 leipo leivonnainen lejhobs +lejhonni +lekkergras +leld +leliwuz1837 lellikedraak lemeborrowgp +lemm y lemon +lemon 25 +lemon cookie lenda +lengf +leo vzla +leos main +leoshnoire lepetitpois +lepicklenick lepo +lerpledore +lesel +letos111 lettam +lettername level-103 +level-125 level-596 levendi levon lewcifer8118 +lewdogg lexi +lexi bell3 lexicon7 lguana +lhommerun liamde +libad5343 libertador liberteeeee +licdik21 lick +lick my chad +life is shit lifesalaugh lifter light +light year lightfader96 lightningess ligma ligma2 ligmadich lihaamm +lihavadino69 +liisa liisankissa +lijkenpikker +like cooking +lil Mamacita +lil b +lil bumpp +lil chris 15 +lil ducky69 +lil gay cat +lil jev +lil mage013 +lil zeze +lil zuck lilBula +lilJacklil lilNoob2341 lilbitlifted lilchiken +lilcjay11 lilcuff lilgreasy +lilkcough +lill misfit lillelar92 lilliilillil lilmasterOG +lilmuscles lilseveron lilsquiddy liltunechi @@ -28763,195 +59214,385 @@ lima limona5 lindyman line +linebacker linkhg100 linlithgow lintydeer linusforsman lionking-PVM +lip length +liquidchese +lirska lisher100 +listentonano +litger litheum +litranmaito +littering an +little boat +little man 9 littlebumble +littleman699 littlemc14 liubei4444 livdumb livil liz_mar70 ljjjt +ljzerenmes lkalgo lkaoz +lkeaurhteakl lkigai lkjhsdfglkjh +lkkle +ll Grey ll +ll Zeke ll +ll jacob ll +llBear llIIIlIIIlII +llIIllIIll llKaren +llKris +llNephilim +llRevenantll llStevell llab +llaurune llerb +lletya sugma lleygo llhan +lliigmanuts +llitl +lllIlIlIll lllPeppalll lllnifflll lllogical +lllustrious +llo yd +lloytronn lluH +lm Drunk69 +lm H o T +lm Jard +lm Scoob +lm Stark +lm Washed +lm batman +lm scrub lm2fas4u lmAddicted lmBarryAllen +lmTrash lmao +lmaonation +lmfao ffs lmgur +lmmorral +lmmortall +lmpart +lmpatiences lmperishable +lmplication lmplode +lmpostar lmposter +lnSpectre lnYourDreams +lnc +lncendie +lncest Steve +lncestralTop lncline +lncredibilis lndain lndecisive lndika lnfa lnfernal +lnfiltrate lnfinitesoul lnformed lnitial +lnitialed lnkd lnquisitor lnsanewolfy +lnsec lnsertname lnspect lnspiration +lnv lnvictxs lnya +lo0o0lo0o0l loadedhuggie loadingman loasted lobi +lobssss +lobster pot4 +lobswordie local +lockluster +lococonut92 lococsgo +locustchrist +lofi cow +log item logMs logger2222 +loggiee logic +login down loginxtor +loisakurvi +lokdead +lolaskiller lolbert +loldatfunny +lolekx6969x +lolerrofl loli loliconflict loliron2main +loller63 lollydeepthr +lolnicebank loloharqia lolol +lolw +lolwhoplays1 lolxdmeme lolzzii lone lonely +lonely rider +lonelybutter lonewolf200s +lonewolf99s long +long hcaeb longbodd +longlabia lonko look1nAzz look2thepast look4clues +looking ass loopyloos loose +loota-criss lootshark loox lopiwer lopldopl loraxkiller lord +lord bimby +lord boozer +lordlazzy lordrandomZE lordrunekeys lordsamzju lordzyzzbrah lore2 lory +losbandito losee1 losing lost +lost to time lostchuck +lostingame lostpanda21 +lostwithiel +lotion on my loucks loueyyy +louisa loumit louw love +love bees +love haaze loveNfungus loveT0spooge loveablepand +lovebeastx +lovebite lovegoroe loveh8hero +loves a beug +loves moms +loveyoub1tc8 lovezz2pwn +low lQ gamer +lower caste +lowlyworm +lowrandom +lowstat lowwpower lpman +lreful lrin lron +lron Bladder +lron Fill +lron Kev +lron Mar +lron Mennis +lron Paladin +lron PvM +lron Taint +lron Tom +lron patriot lronBud lronConquer lronman +lronmanBtw lronmanCraig +lronnan ls32o0 lsdx lssabella ltachi +ltachi_01 ltaychi ltsJor +ltsJustified ltsMiller ltsYaBoi ltsYourBoi ltsuki +lu is +lu1gi00 +luc1d dream +lucaniste lucid +lucid olm lucifer290 +luck wheelie +luckeG +luckey7744 +lucknesshcim lucky lucky female +lucky never luckyweeb13 +luckyy vii lucuh lucyramon ludaftpitbul +lufteohl +luierick luis lukas +lukas2518 +luke the npc lukehm8o lukek22 +lukem0n lukewarmrod lukey +lukey pookey lukis159 +lukutty +lulllopiet +lulu +lummby fam lummywk17 lunamelina +lunar frost lunch roll lunchbox lung luolapeikko luthas luut +luv da grind luwl +luxyy +lv ie lvan lvarLothbrok +lvl 1 sleep lvl3 +lvon +lwesche lweyffaM lxli lymitz +lynx zan +lynxix13 lysander640 lyzolda lzrdlvr1 +m 62 +m e e p y +m i d s +m i n i m +m i t s u +m inimum +m miq +m nice guy +m x e m-moi +m00fen +m00fin +m00nrock +m0ker m0mentum +m0saic +m0stert m1ssing m1xos +m3g4m4n +m3nd3nhall m3rkzz m3tku m4ge4life4 m4gi +m4n m4ttay +m5q +m6ngel112 m8tio m8zi +mBucket +mGu +ma shnibbla +ma61187 +ma7shee +maadar sag maahhtt maawee mabeltwinkle mac_moneyy macflag +macgleeznorg machurrohard +macjonge mackbhamRS macke064 +maclean93 +mad bor +mad dogs son +mad hjorn +mad4cashh madara666 +madeustilde +madgamer45 madhat86 +madironman45 madman456789 +madmat38 madnijz madpaul1 madwebbie +mady I green +madzey maeonia mafiaz mafiz @@ -28960,16 +59601,25 @@ magerageftw7 magesticx maggpagg magic +magic me92 +magicarp420 +magick pp magicmike117 +magiskt het magnacarta +magnum0008 magnumdong94 magyarok3 +mah nickel +mahamoho1 maiden mainCallum mainyMCmain +maiy makarena makemon makenator +makkan69 makosoup maksavelat malfoy @@ -28978,57 +59628,103 @@ malmstrom malte313 mamadou11 mamatriceps +man spreader +manaakitanga +manameisjeff mangkj mango +mangocry +mangoszn manmeowmagic +mansbridge mantequille +manwhofish +manxster manyfac3god +mao maon maori maplegamer6 +mapletits maqr marbelo +marchdog marcinrulz marcmaralou marcwins123 marioflame marioswe7 +mark uk marketmoney +markobae markypoo +marmO0n +marmalarm +marr66 marrab marrciee +marrrcoman marshyymarsh marth2king +martickle marvypoo +mas koff +masdebator +masonkillem +masta132 mastafarmer master master9782 +master_box masterloveme +mastermisch masterpi314 masterseppi masteryi01 +matata23 +matiks matis6080 matiteusz mats +mats643 matsxe matt182xx +matteuce W matthew6500 matthoot88 +mattrabbit mattv matzRRR matzkia1 mauberries +maulnak maupz +mauriveitaas mausre +mav daddy mavrooo +max acc btw +max all max +max pet hunt +max yet jake maxcapealt7 maxed +maxed nelis +maxedtheaxe +maxgt96 +maxiicano maxiwiz +maxiyogi +maxplayer maxrevenue +may him +may lay +may thai maybe maybejarrod mayhemrs mazzahS +mb mcbig12 mcbreeeeee mcdonald @@ -29036,231 +59732,502 @@ mcgigity mcmadpac mcnuggetcons mcrane1202 +mcsoftee mdawg +me disabled +me espresso +me handicap +me ineffable +me no bueno +meOwNYXx +meat jun +meatball47 +mebigbob mechmillz +medicmain +medictbh +medium cloos +medium unit +meds bad meekmook +meemimestari meepify meerks meermaijer meetoihi22 mega +megabass megajoeck megatricks megoodpvmer megret +megxolotl mehloncoly +mehmuss mehunder +mei meinen +melangina melborn44 +meldrahn meleonlyslay mellaa98 +mellagro mellonman +mellow jack +melncholy melog +melog dog +melvin quit memephis +menaceirl +menarehot69 +mendier btw +mentasltu +meow for gp +meow for raf +meowthc +meowtism merryrice meskil +metblo meth0d +methcathione +method888 +mettleman149 meurtpo +mewby mezins +mf Catleesi +mf Giggle +mf neeko +mf yappin mfHank +mfHank Hill +mferJones +mg mhe00 miTzy +mia celtic7 +miaka yuki +mianbaoroll +miceworkteam +michaelma4 micheal michixranged +microham 69 microwave62 +mid clicker +midget man +midzy mie19 +mielas +migboincan +migidi migilicuty mihalys mikbea +mike 6 mike2290 mikefizzled mikeohtran mikh +mikko2112 mikkoyy miko mikomiko miksuwu +miku qwq milahreigne mild farm +mildMuscaria milfnmybed +milkpatty milkthegoat milkuwu milkybestdog +million sof miltryguy248 mims2dank4me +minato minatokill +mind goblin +mindislost +mini booty +mini r00d +mini rocklee +miningas +mininimum +minit +minky +minmax +minni mile +minor flex +minorhazzard +minsy minty1981 +mintyale mintyclintyy minus +minus Left minyhitsk0 miokaen mippim miqli +miramyra +miregal1 mirhagk +miriti +mis +misery2018 missingIink +missuy mister +mitchelle1 mitchrocks mitchvvs +mixed snacky +mk6 +mkden2 mkl782 mks200 +mksu +mkvo +mlars300 mlbg mlgb mlgkittycat mlkia09 mlong06 +mmaxie mmigo +mmmkay02 mmmmmmmmhmm mmmmmmnmmnm mmmuurrddaaa +mndo mniml +mno +mnt +mo an mobile +moer +mogwire mohak45 mohrs0 moist +moist P00P +moistSwan43 +moistcltoras +moithab mokkakulli44 moksi +mol 99 moldsack mole moleflair molkyrion mologgi +molten ass mombasaa +mombasaa D mondklapje +monero gay moneybandz moneypants +mongelman11 monkaS +monkasusdog +monkegrip monkey +monkeybisz +monkeymatt monkeywilly monkieturd monnan56 +monstaa +monsterje11 montaxus monteurtje +moo vo4life mooblesyrup +mooch86 moocowfish +moogz mooiboy +mookixx moomoocrab moonlighterr +moonona +moonpapa +moonrat2 +moonwyrms mooofy moor morPL8morD8S +morgan renee morgf morsotiikeri morty mortymoo +mos f +moscuz moska most +mostalpha +mothaload motmyfanny +motorbichael mountcaedo mpathetic +mpel +mpxd +mpz00ne mqaccat +mr atheist +mr boobrie +mr buying gf +mr mage t +mr pink1 +mr rob iron mr shroom +mr triggerd mr10inches mr12345 mrDragon2009 +mr_adore mrb97 mrbreadst1ck +mrdickbals +mrfox2 +mrgeck mrkaramazov +mrpurpdrank mrvortex3 mrwoffy2 msHyde +msb2595 msimmo93 +mss mstfu +mstr nay nay mtash96 +mthic +muchderanged mucserup mudbitedlite mufassa muffing muggfac mugii +muh +muh sheen muhName muhnamezjeff +muhnkydluffy +muin101 mulletman360 +multi genius +mum ranger +munalutkutin +mungero +mungkee munney munoz316 muovaz murders murphy +murphy XD musashi2109 musei +mushpinator +musnew +musta_matto mustaa +mustardsurma +musterdsauce +musty04 mustypill0w muta mutanen mutsCateer muufaanchu +muy bien +mv3 +mvgatron +mx mxgali41 +mxpurp +mxq +my fruit myballskin mychaelven +mycrazy life +mydmallsick myexdidntrs +mygf mykohchoo +mymoonkeyz +myname Borat mynamesDog +mypp +myrtlecat +mys_try mystic myturngranny mzsc +n a g a +n k h +n o m i s +n oge +n os +n00b tax n00btube +n00dIe n0DaT +n0n Believer n0ns3nse n0rthmemphis +n1ch0las n1ghtmares n3cromans3r +n4ts +n8m +n8n +nSubordinate nVox +nYer +n_koo +na cba naamarihomo +naapurintati +nabritches +nachoss +nae drops nagezz +nagoog +nah cba tbh nahbo nahhhh nahka +nahkasaurus1 nahkasohva nakneemo naksuu89 +naldy nalon34 +nalyD yrraB nambourian +name is damo namelessRS +nami skin namnori00 namtar elite +nancyy naner +naniichan naomi +naoshika napkins r us nappera +narbsta +nas xy +nashmvpx2 naskend +nassikka nasty natalya nathank498 +nattte krant +natty nest natur3za naturesque +natuurhuisje +naughty ruz naunas naven +navi my dude +nawilsi +naxe nayo123jo +nbyo ndrs +ne cro +ne hi +nebegyd1k nebula3 +nechs minute +neck bungee +neckals +nedpvm +nee ceri +neebzor need +need drops +need panoche +needs tips +neeeefe +neeloy neenisneen +neeshmow +negative neggibo neil +neil v neiti +neitsytkulli +nekemaribo nelrb nemofishtits neocritter +neoneu +neophyte8 +nerdneck irl nerf nerpkin netsh neuber +neukbare neutekind neuz +never lucker +never s0ber +never subtle +neverblume nevercash +neverenought +neviilz +new pfp newaccbtch newallmaster +news +newt merch next +next 99 nexus +ney spook +nezumileo +nfandango +nh0x nhy0x +ni ox niaya +nibbla nice +nice to game +nicelah niceslime nick +nick at nite nickdv nickel nickfx +nicky +nicnad nico nicoxpico +nieve nooooo +nightmareram nigriV nikhil nikler @@ -29272,20 +60239,53 @@ nimlif nioem nipsunaapuri nishkid64 +nisq nitro nitsuj315 nivk420 nizmoNL +njitram +nk spy +nko +nl Airo +nmb nmhbu +nmzcow nnick999 +nnko nnmf +no birds +no engraving +no flek zone +no gag +no gay ok +no l00t +no purp bug +no use +no1evrnos69 noDDD +noTheOwNeR noThumbz +no_odles noahcous nobankpin +nobjockey400 +nochoc +nodeLT +nodropman noek1 +noeyi +noice garrry +noiteerIW +noki keppi noldaddy +nomiS +nominMaxCape +nomlaS norI nomorelies22 +nona nona +nonamechange +nondedjuu nont0xic nonuboko noob @@ -29295,21 +60295,41 @@ noodle noong nopies noplanhere +nor so osrs +norI Ryan +nora cat nori +norm HARDY normal normie nornavsoc norrisi +nos nosemar nosepack noskilljoe nosnhojgib +nosoberday nostalgiaeng noswaL +not Duncan +not chop +not cumingbk +not gods +not heppi +not herbo +not him dude +not shaken +not tiv +not tk +not today m9 +not ual not1stepbak notEdited notPape notRoyal +notanjiro +notazerk notbennie notdead91 notefficient @@ -29317,54 +60337,119 @@ notepad0164 notepad14 notlikedis notsoB +notsosmart11 nottrade +notwack noutonme novali1 +novike +novikid nrakneS +nrdz +nt combos ntarallucci nthing +ntrstng +nucnad nufnufaz nuggeets nugs +nullbeing nulluserid +numb3r go up number +number 11 +numbly numnut +nuoli tulta nuopisa nurbaya nurriez nusta +nusta but +nut low +nut5ack nutes +nutpeanut +nuubbaa +nuubii +nvcu +nvrpurplight +nwate nyareet +nyc ramme nyet +nymue nysyGG nzskater +o Buffy o +o Galaxy +o Jay o +o NEK o +o Pug o +o SiLeNce o +o Steven o +o c c u l t +o chem +o n e i n v +o tp +o tu +o0 Rang0r 0o o00dan00o o0Ganktank0o o0mni +o3d +o9 oAQu1LeSs oAlsen +oAmber oBugz +oBuster +oChezzeRo oClairebearo oClay +oColeeey +oDemko +oDriew +oDrizzyyy oFelipe +oGMRKay oGreene +oGun Smokeo +oHEXo oHoriizon oHxD +oIce Teak oKsirf oMDmA +oMalevolence oMoJo oOGeorgeOo oORagnarOo oOoITITIoOo +oRonde +oSanta +oSea oSpecialx +oTARNAo +oWags +o_o SEMA o_o +oaenii oaflion oaisjgljlak +oaj +oakypinkre oatenz obama +obamas ass +obbE x obees +obej +obese_man61 obican obitokun obosk +obvi_no_gf ocbslim ocian ocruT @@ -29372,100 +60457,222 @@ octazookaa94 octopussi11 od1np1ck odafan +odd woof oddfinn +oddniffler odenthas +odinsjourney odio odlolien +odty odyssey oerinn +of a china +of booze +off balance +offends offshore +og kasi +ogag +ogbrittney +ogeesus ogg25the2nd ogned ogogog ogteleblock +oh no fuse +ohSmelly +ohai ohai oheesnose ohgoshyjoshy ohh_man200 +ohhh nooooo ohhnnnoooo ohia +ohio is for ohioisonfire ohiostate347 +ohly +ohmyrod ohtukurva +ohyep +oi ranga oids +oigia +oily rod +oilysurprise +oixi +ok baba okannah +oke oksen32 +ol Twizted1 +ol kq +ol pleb +ol_l olatrekuk +old Soul rs +old kind 911 +old man agst +old man zedd +old meat +old mem older +older fruit oldsports oleNeilyBob +olen lahe olindaelostz oljon112 ollie +olliedamage olliethekat olllllllo +olllllllo TJ olmec olmmmmm +olms beach +olovi kolome olsyboi +olvia omavi omegaOnepump +omff +omgbabestop omgimacarrot +ompahelppoo omrip96 +omwtotob +omyefge +on 9 +on the fella onalite +onbak1992 oncenterlink +one 69 +one1one1one oneblade onelifehaze onespringday oneticktony onex +ongelmanuori +onizuka onle onlinetares only only4pvm +onnetar +ons va +onthebook +ontspan maat ontv1992 onyo +onyx no oo7jordan oobent ooblued +oof mikael +oofbored +ooi +ook Thunder +ookbye ooli +ooo Papi oooRush99ooo +ooooby oooopsiee +op +op P openyoarmpit +opiumwet ii opneemvot opticsnail opzu +orangeluke orangetree34 orb in bag +orb knob ordy orebac +oreo lil oreru +orexinergic orez66 +org asms +orgasmdonor +orielor orig +orir +oritx orkans +orkut +ormz +orophyr +orra orrichimaru +os SlayScape osJuhiss osbhuda ose420 +osmati +osn +ososrswhen +osquiver +osrs Apathy +osrs MCFS +osrsbilly ossaciM +osu +osynlig otallone +otdog +oteb otherguy3668 otoboR +ottledread ottx +ouic +oum ouououuoouuu outohere2k +outsmart3d outsourced ouwe +ovas bis +overact +oversize rat ovox +owen4boro owenwilson ownsome1 +ownt by flan owo0 +ox +oxifaze oxoxoxoxox +oxtale +oxyy +oysni tu ozos +ozztrevor +p hd +p n g +p x v x m +p000r +p0ge +p0tat0_baked p0w3r p0werSinn +p0werliftin p2pell +pAj4ri pHqiXfQb5rpO pRandgris pRiesty +p_tane +paatttxxi +pacack pacbackpack paccerz pack @@ -29477,18 +60684,29 @@ padq pagakoning pahe painter2020 +pajiaobin pakgg +pakkohoito pakoonjuokse +pakwatch palacePier paladylan panda pandahands +pandas flail pandascapes +panel v2 +panelupgrade +papa jjinx papaisthatu papatec paper +paperbutter parB para1911 +parsakeito +party-joiker +partyinferno partymonkey partypooyan partypossum @@ -29496,6 +60714,8 @@ pashol pasismi paskapylly6 pastry +pat summitt +patbeerpants patches4623 patnazNkryme patriciogmz @@ -29503,9 +60723,18 @@ patrol paul94nl paulimvitor paulmacawk +paw fetish +pay peru payout pazmar +pb tiramisu +pbagel +pbj eater pbjt +pcce +pd3 +pdi +peace love h peaceofbread peaceoverwar peacsenur @@ -29513,151 +60742,280 @@ peajy peakyberry pebbles256 pecemker99 +pecker neck pecko517 pedagoog peeje peenwa +peepeepeepe peepichu peepoGamer +peepoParker peerks pegfemboys +pegge jr peksi pelaan peliken2 pellemaailma +pelmot +pemmex +pen gee23 penakonda penally +penile pain +penny 4 thot penteroinen +peoples0123 +pepe max +perc ceo +perc5 perckey +perigor22 perlecta perm +pernieuw +pernix +persepullo persesreign +persisted person personajay22 personal +pesto pasta +pet melon +pet my mole +petc0 +peternguin petesmcskeet petlucksucks +pettyrogue pewbs +pezzler pfiati phatpunch +phatsocallum phattymaster phen0mXD phenotype pheras phetagoras +pheyyw phinex +phlayme phonon phoop phorme photolstamp +pi n g pibbi +pickle llama pieater_314 pierke pietu pietun pieww +pigeonkisser pigeontoeman +piggybosspen pigusvaistai +pihseurc +piia potka +piie pikir +pikknu +pikkukala +pikkupeppi pillman +pilludemoni +pimmscup +pineapples56 +pink soup +pink spoon7 +pink4 pinkdragon76 pinna67 piomon +pipiopi +pippelisurma +pippy 429 pipratoos pir0tekniq +piraat bwana +piratedog7 +pisk naxui pixelpeat +pixiedrank +pizano pizzaforce33 pizzaloksi pizzalord321 pizzerr pj137137 +pjmonkey03 pk3rsh34v3ns +pk_all_pk1 pk_by_me +pkdrwho2 pkdude116 pker +pker ice pkerdude559 pkew pkpk +pkshitomario +pkwy +pl33k_supa pl3d plaatshouder planetflat +plank r +plankforsure platygirl play player198792 +plea pleadingface pleadtha5th please pleasebuyckb +pleb Remains pleb166 +pleben plebminister pletsjer ploomert plopko plszulpet +plum lee +pluma plumb +plumb bum420 +plumit +plumpy nut +plz dont kry plzl +plzvenmome +pm 2 spy +pm4 boost +pmax pmmefeetpics +pneck +pnn +po0z +poachpenguin +pocar +podginator +podolskee poesiewoesi poesiwoesie poffdragon1 +pogarmyy +pogdoor poggersgif poggie pogglewogger pohaku +pohwe pointn +pointright +poire +pok758758 pokas pokemonsunim +polentusmax politieman +polo gee poly ponderer pontlarge +ponyika +poo from bum poobutton pooga poohwell poolbadger +poon fisher +poon nanny poop81 poopeepeeman poopsm0ke +poorlyhung pop-tato pope popstantot popwig porkchop-kun +porkchop87 +poro600500 +porpleRanger poseidon0928 post +post nut sad potato +potato pleb +potatogod62 +potatolove20 potatoplayer potholderz potionsell3r power +power helmie +powercheck6 +powerpluging powerslide +pp 73 +ppb +ppdandelions ppengu ppfighter +ppidd pr0jectcarry +pr0kkeh pr1est +prQmethazine practice +praskiepas +prayfx preachably pregnant pretty prillage +princesstktk pripps0 prkr prncss pro90 problitz1 +progmog +project eggs prom +prostate proud2bbalin prtck prut257 +ps1 jrpg +pshot25 +psp 11O6 pssssssh psykotic12 pt37 +ptdn pubnroh +puddskape69 pudgy pugginSpooky +pugmen +puhkipantu +pul uk +pulinaseppo +puljulaine +pullo viinaa pulpfree +pumiss pummi984 pumpkinslaye +puncher punchlineNL pungur punken @@ -29665,63 +61023,137 @@ puny pur3gh0st99 purEvil808 pure +pure owns al +pure wood23 pure10693 pureblackid puregluttony +purity purpfanatic +pusha tree pvm bioodz pvm-owning +pvmingbr0 pvmrob pvpmirage +pvtRyansPvts pvvm +pwn me plox pwn0grapphy pwn2b3w1ld pwnnya +pwuh px yra pxls +pxtchy +py ze pynergy pyro pyro255 +pyromaangast +pyttyyn +pz pzqlpwbma +q Aleks +q Nossie p +q b0nkerz q +q f z +q l l u +q sl +q-Mini-p +q0k q9q9q qJezza qOsMoSiSq qPepsi qQazp qTiger +qazi qazio +qbc +qbi +qbt qckr +qerw22 +qez +qi e +qiany qiunc qiyamah qlxxlp qnzjosh +qoao +qooo +qop +qorbin +qp +qpwoei1029 +qqgoat qsse +qtAlice +qtb qtei quazepam +quekchose +questarila queundas +quickiies +quickmoist quickster61 +quit afking +quit cry quitb42k quiver81 quky +qwaylub +qwerps qwertralph +qwerty2431 +qwertyboll93 qwertyuiozxc +qwl 2 +qwopr8 qwruqwpourqr +qy +qz qzxz +r a i n i n +r a i q +r d x +r eflex +r ehab +r i ley +r n g o d +r o c h i +r pt +r u a pussy r0adh0g r0jasss r0mera +r0p3_tv r0yalrag3r +r1ch3r mitch +r1chmond +r1ddlbox +r1z1n r3laxed +r3mov3k3bab r4cky rAEbl88 +rIcHmAn4 rMatey rVino +r_rl +raando rabid +raccy rac +rackee chan rackelzz rackemballz rackzcity racoon96 raddawgg +rademakertj3 radox rafa2424 rafnek1 @@ -29731,28 +61163,45 @@ ragegoon206 raid raiden raildex +raisin canes rakete +rallikaar ralliss +ram this +ramafie ramblin +rambo 1206 rambombon +rambroze +ramjamyelham ramsesthecat ranarr ranarrbiss random rang2d range +rangedp00wns rangoraus ransty +rarefleas rarekia rarru rarurrer +rat catcher4 +rat ritual ratboysteve rateddd +ratirl +ratirlAlfred rats +rattiyanee ratzzzzzzzzz +rautamon +raves m4ck raving ravioliwren rawheadshot +rawkneedong rawr rawrsmashh rayhoon @@ -29760,31 +61209,56 @@ raymanvh razorwheels1 razzdnutz razzex +razzmatazz23 +rb winter rbjk rbootsGOD +rcr333 +rcyy rdrluvr77 +re-frozen reBoosted real boyo real-derin realAxu +reallityfail reallyhigh realpcooktho reamillion rebirthofyay rebuildd +rec me reclinedgmr recognizable +reconjack +red eye jedi +red fox8 red504 +redank redberry redditlucio +reddragon950 +redeye q p redgorilla12 +redhunter193 redman211 +redpatch redracecar27 +redrumyliad +redsheik redsox216 +redsp3c redwagon9 +reenur reese +reetznutz reflexlols refurb99 +reggie v2 +reggieblunts +regorydog +regular ph +rei1315 reikimastr reilaria reistje @@ -29794,298 +61268,604 @@ rekrog rektum relac relaxed +relaxed now +rellu riku +reluf +remind remind309498 +remko maxed +renaissance +renasue +renruB +reopened +report you +reptil51 +reptile reas reptilepoop8 +repulz resU resetcentral +resupplyalt +retern retrrd +retuson retzc reznas5 +rezpek +rfr0sti +rg44 rgfji rhey rhiller83 rhygan1 +rhys c ribalibali +ribe4 ricard0live ricardos78 richarb14 richy +richy rain rickrko +rickthick73 +rickystackss +ridewitme riilis +riipx +rikkertik riksa123 riku230 +rikuirl riller rils2 rimpati +ringo794 ringosting0 rino +rip dj ripHuyy11 ripbobthecat +ripend +ripsrc +risbarn +riskbizz +risker +ritcey rithvik ritotrisoto riuCooler +rizn +rjh300 rjweb rl9g10rs +rlkgfseorhfe rnatt +rng god x +rng limey rnom rnue +rnv +ro0b0 road2broke rob nagle +robbinator27 +robhode robilo123 robinchris robo +robombalt +rockcrabpvmr rockeroHN +rocketberg rockhead7746 +rockstarwht +rocky leeg rockyandtaz +rockyou 2 +roest roflbaker roggy roldan_one roldunogene +rollsyy +rommmey romper +roofy rornburst +ros n +rosati924 +roshambee rossdark1234 +rossmain rostiefrosti +rosullivan8 +rot popstar +rotceleS rouge +round cat +round kc +royalpanda53 +royce ranger rqkrtzjvbsuh rrautamies +rriot rrrpR rrrrrrc rryutie +rs3 blows +rs3dansgame rsoby rsruinmelife +rstr expert +rsyux rthgo200 +ru-ne rubengouveia rubikslayer rubj3llyonme rubtuge +ruck ur dad +ruding ruikkuapina +rukdingme +rullakebaani +run amuk +run its bc +runaru +runaway iron rune +rune dogger +rune enjoyer +rune poon runedongs783 runedragslay +runeferyearz runehol1st1 runeika runep3 runequeen163 +runesc4pe +runesoftime runetraction runite +runite bars rupt +russien rusted +rusted shaft +rustigggggg +rustinged +rustys word rusvet rvrse rxbi +rxylvrn ry1n +ryh ryppyreika rythail1 +s h l o o p +s hok +s i r tinly +s k i p o w +s laack +s n u f f e +s nekk +s t i l +s tress +s0spwnz s0uln0te s0ultage s10w s11gm4 s1ayerg0d +s1pa +s1r maximus +s3fa s3nna s3nt s3ppa s3vuu s4mu +s4nc s7v7nty +s7vey +sCUM Runner sKDestine +sNEXyBaker sSahm sSpring +sTs W33D sTxje +sYo +s_ck it +sa ko +sa-ku +sabfas +sackiltrog22 +sackmen sackmyduck +sacredchange +sad nmad saddest sadgeboi sadnmad sadnmad666 +safe bunnys safermoon saffyO1 saffyO2 safino saguyuyu saiko +sailsouls saintffs saiyansmithy +saknoM rD +sakuyaaa salad +saltia saltycups saltynads saltypepper +saltysealife +sam ofc samdegreat same +same hada +samo0o +samoht10 samothon samqwop samtatt1 samuraigod13 samwise1133 +sandai korky +sande108 sanooJ +santa cloud +santa ho ho +santorio saphinix sara +sara 35 +saralandry sarcasmz +sari essayah +sarppatsu sashamii saskecas1 +sassy fool +satisfried +satsuJima +saturos159 +sauna41 sausage savPalestine +savage_grey +savi 2 +savukorilas sawb +sawb0ssnl +sawl7 +sawshoulders sawyfabj +saynototofu sayyless sbrand0n8300 +sburzz +sc arlett sc00ben scaffidi scallicci scape for 1 scape4ever20 +scapey123 +scaredbunny1 +scat wagon +scb +sccrub +sce nes scerp +schaamlap scherzmfromz schetts +schiggs schildknaap schmashmu +schneeple schneky +schnibbyy schzu scidder123 +scitles scnick scone99 scoobydooby9 scoobysdooby +scotian 902 +scottslipper scottuzamaki +scottydo27 scout +scout robot +scrollspirit +scrotumfart scrubEE scuffedbrain scuffi +scumbag 66 scuterholmes scythe scytheXI sdfsd125 +sdotmaxedout sdzl +seBlait +sea owl +seabird seachrome +seacowcow seamondemon +search0 seared +seawolfsam +sebbe osrs secs securite +see attached +see me whip +see4limbs +seepah seetod sefeeee +seffimz seizure sekkuso selfShow selfcurse +selfish coal selling +sembino semper +semperstrik3 senZe senapsgasen sendu2edge +sendykap +senggg senpai +senpai btw senseyf +sentterih seppem seppes121 seppevb seppohaa septynetas +ser angus +ser tugger +seraphine jo +serbuttkiss serious seriouslee98 serpentSmelt +servix +sessarrow settyboy66 +settyz +sex mum +sexy skuxz sexypersian seyed +sezery94 +sfinx71 sfnative sfsdfg +sgaben +sgf419 sgg9779 +sgk +sgq +sgurdevolii +sh-Y-ft sh1nan1gans +sh1ttyrng sha0ski sha7y shabado +shad y shadex94 shadow +shadow brr +shadow btw shadow77440 +shadow926629 +shadowarmy +shadracker +shafli +shakedabooti +shaking irl +shamabeast shamans +shambbles shanemck shantyklawsh +shape share sharingbox +sharkey_32 sharpshot776 sharto86 +sharyn cox shasd whip shawnn1 +shayge +she btw +shed dabber +sheep5 sheev85 shekelgoblin +shelfy 2 +shents +shere khan1 +shes sleepy shezze shhit +shiddingpant +shields_zzz +shift drop shifty +shiftydaboss shigha +shiky shio +shishiodoshi shisui +shizcake +shkoB0 shliure shmoopaladoo +shnizzlebear shoarmamama shokki +shoopa shoot162 +shordilele +shore +shortsleeves shortstroked shower +shoyu shreddin shredness +shredskater shrek5 +shrigma shrlmp +shrooon shroooooooms +shrootfarm shroudyroudy +shtos +shturpants shumili shushlik shvxstxchla shxg +shxyzzz +shy lo siNusas +sibeepboop sickGeneral sicklyhare sideways640 sidney3241 sienna +sienna sleep sieracki sigh sign0ut siik siimzz97 +siiz +sikatopi62 +sikazz +silburr +silemani +silenthenk69 silentical +silenttrew +silim acac silk +silly cowboy silvar93 +silver bean1 silveraze123 +silverwar33 +silvethril +silvio lol +simi sai simmeg +simp 4 life +simple +sims Hsp +simz +sinannani sinappi688 sindicalism +sindulis sinfulnature +singlemom34 sinsofmany sippin siptar +sir ecnar sir skau sirlotje +sirmesoulier sirpaul sirpoopball5 sissijuustox sisuwu sitonmaface7 +six2midnight sixanddagger sixerr sixovercrest sjaq sk0me +sk1rttt sk9bord skaiii +skaios24 skandaali +skaring kids +skateenjoi skaterdogz skatermatt91 skatterpunk1 +skaugi +skcusxegaj +skedie +skeide skek skeletoon skeli sketchdreams +ski skidipoppop skilgrave skill +skillachris2 skiller270 +skilleuhjong skillmaster +skillngbot41 skills2millz +skillz davoo +skin suit skinny227419 skinnypimp71 skipz1419 +skittels +skittlesour +skiu_21 skizzurp +skizzy sammy sknzor +skoalintry +skoowu skorthen +skowotek skranzii +skrenne skrtskrtpvdb +sks110 skuccy +skuirk +skunk nugs +skunkpaste skunkskillzz skyE skyelar27 @@ -30093,50 +61873,101 @@ skyffoxx skyz skzs912lav slaack +slack austin +slacky456 slajdaren +slap her box +slappfisken slartiste slavhouse slay +slayJTIaster slayer slayer92 slayerfrog57 +slayerxp +slayetd slayhore slaying +slayzerot sle3k +sleek2d +sleepinonice sleept1ght +sleepy 940 sleepysleeky sleepyweasel +sleightest +slemgaedda slice +slice O pie +slickstick21 +slickvick21 slidesteps slidtegitte slight slight7 sliginz sliim +slim in dar +slim j3sus slimski +slinnGimme +slippaa +slipstrides slobthyknob +slowmopwns sludgebag +slundersc0re +slurpeeboi9 slurpeeking9 slurpy40 slurpydong15 sluz +slvtty slvt +sly seyda +slyhitman slypupper +slyr4ng3d +sm0ke herbs sm0kebeers smChi smackbo +smaddz +smaggd +smalcano +small boaty smallmichell smallppbigxp +smalsey smasher12121 +smasher95 smaugs +smbonn2005 +smeerpijper smel +smelly fuss smellyducks +smerq +smettjes1 +smh Monkey smiithy smirqqel smithdarts smittty2009 smoe smoke +smoke buds +smokesIetsgo smokin +smokin turdz +smokingalone +smol bat +smol chris +smolBen29 +smoothcamel +smoothlover +smote smoug007 smrgn smuqu @@ -30144,142 +61975,276 @@ smurfrookie smurpfy smushman snaggle +snagnURkill snailydog snakehuntr94 snakenbaked +snaplocket +snapped neck snarfoo snck +sneakY geeB +sneakyleazrd +sneakyyj +sneekeysnek sneeky snek +snek killa69 +snek man_44 +snidletics sniff sniffmapouch snikkels +snipper143 +snoogensss snoppen97 +snorlax481 +snot aap +snow dude678 +snowdance +snowfild +snowkeepuh snowy +snowyhawk45 snowysonic snoxxyl +snp500 snubsnub +snurtfe snuskfet +snuskukken +snusnuending +snygg o smal +so joe +so jung mijo +so much ass +soarix +sobsk soccerdog +soccermom82 soccerrad177 sock socopb sodChamp +soderfalk sodynamic soft +soft dab +softer bugg +sofus64 soggybread4u soggywaffel9 +sohju soiled sojraal +sokoudjou solfam solidon solo solodiyloner +solodoloyolo +soloeraut solopops solos solost7 +sombb +somber some some1saybags someBODY325 +somos papaya sondrep sonera +sonoboymw +sonofablitz +soobli +soombie +soon2bxwife +sophiebear69 soppel +sorris alt +sorry +sorry pls no sorrymatey +sotaneekeri soul +soul et luna souldrainer soulkamikazi soulkra +soundspeeds +soupnbannock +sourkraut soxx +sp3edie +spOnsOrr +space craft +spacemanriff spaceonion44 +spagh bol spam123 spangulation spankmoi sparkoftruth +spartan1137 +sparterrang9 +special k258 +specialton specuri speed speeder269 +speedtrain speeeeeen spell +spenmaso spete +sphicologo spiLLLLL spicke21 +spiderman 13 +spidey spigems spinova +spiwit twee spladay +spleiner spletcher2 spliffens sploobie +spoiled mayo +spondonicles +spooki xd spookib spoon +spoondrngplz spoonfed +spoontarded spoonyg +spoooficus spootineftw spord8 spozz +sppak sppoh +spratel springAnonce springplant springsteen3 +sprite zero spritelum sprits +sprsp +spudmyster +spugEddi spunkontitz +spyde96 +spyrolegend4 +sq shield sqad +sqrls +squareheadfk squatlownslo squidnstab +squirrel1991 +squirt fan +squirts +sralisas +sray +srd srgynt +ssA taE ssei +ssh keys ssj3 sspiriNut sssu ssttaann ssyd +st aeryn st4k3l0rd staarii stabbycut stabekk stackables +stackagawea +stahldog stainalt +staleburrit0 +stan darshhh +stannaz +stannum star starcrosdlvr +starfalI starknightsy starshoppinn +starvn-marvn +static void steadiskill stealthwolf steckubnU steel +steel slime +steeljake steelplums steeveee steezybear +steezyledge stefanopt +steflon don stekkeT stella1 stepbro +steph n stephvn steponnopets +stereos sterre1ch +stertanz steveagogoo stevenovak6 +stew thru stewiii stfn sticc stickuppix sticky clay sticky holes +stickygirl stiff +stig sucks +stiice +stikybandit3 still +stingray2018 stinky +stinkybunny9 +stinkymooner +stokstaart stoned stoned84 stonedowned +stonerwelds +stoneybolgne stony stoodzy +stop log +stopbegging +stopy wersow +stor m storkis95 storm stormynight +stouterikk +stp3ach str3tch33 +str8 balling straangeDayz +stradiSlay stranglege +strap locks strateigo +straw cup strawbery strawnk5 streetshark2 @@ -30288,63 +62253,125 @@ striker strnagetamer stroudlee strp0tzz +stugex +stuntti stupid +stupid game stupidcape stupot845 stylebend3r styrkekram styxRYAN +sub merge sub2purple sublime +submunculus subooptimal +substring subzero +suchti +sudden sloth suga +sugar d0nkey sugarfreeman +sugarwater +sugme nob +suheil69 suhuan123 +sukau sukc +sukidarkra sukii +sullz +sum1elsecall summa +summa arte +sumsy +sun delusion sunaert +sunday tea +sundburgaren +sung101 sunkir +sunkirrr sunny +sunny sponge +sunrakuz +sunris +sunu +suolahappo +sup J sup3r0n3 supagorilla +supalordwar supbruh super +super slooow +super system +super-thoms superbuds supercolds superj4 +superlisko superlonely supermanJJ +supermarket supermaxx +supermoist superr supnoobs10 suppertmain +suppus supra surfboardcat susanno +susdog +suspect12 suss suwo +suxc +suzuky svedanya svennepen svenskeren80 +svettnisse +svimmelskam svoji svrN +svstre +svti svver +sw x swag +swag dr +swagburgler +swaggabawz93 swaggb0y0wnz swaggie365 swagscape666 +swake420 swamp +swamp man_43 swampertman8 swampwitchx +swampy fool +swansoup +swasian sweaty swed +swed 420 +sweet ass sweetpissin +sweety 77 sweggdaddy1 +swerve q p +swfc50 swfc51 swftz +swiet +swiftmango21 swissbagette +swol swolelord swooinc sword @@ -30352,130 +62379,256 @@ swordngun3 swordsplay62 swxasxx sxkes +sxtt0 +sxybro sycp +syklo symmm synack +syndra007 +synnistra synterrafox syua syytu +szer szeth17 sztuk +t iel +t imbo +t r a m +t rio +t u k e +t ux +t-Wrench t-painn +t0_valhalla +t0ast mal0ne t0c00l t0nni +t0xicpoptart +t1n3 t1tz1 t4aker +t4t frot dog tOxI tRIPdoubt tRNA +tSessa tZiMiNt +ta det lugnt taasen +tabbionny +tabulast taco +tad3j +taeyeon tage3xx +tak0981 take +takimoto +takotime +tala 7t talinklion talisam tallest +tallwhitebr1 +tamesh +tandem dooks tanfastics tanguay478 tanklesss tankyster tanuliina +tanzfangplz +tar targ119 targa tarpGC +tastenz tatarsauce tatuwah taxed2 taybonejones +taysmehu tayyab +tazzen +tazzzz31 +tb 3O3 tbaballers tbach tboowscouter tbow +tbradz tbrey24 +tcorky tcroft +tdawgthekid tdoe +tdogtsw +tdslaterG tdufflebags +teagantime teakte00 +techev techeverria technitions +teem0her0 teemerco +teh_new_guy tehe302 tehskoozy teini_horo +tellymantel +temmi69 temx tenac tentacion +tentacruel38 tepaseohijo terenerd teroy terrence +terroristiI9 +terrryfold +tescoworker6 +tess tlckles +testokersa +tetinhaaa tetsundo teum +tevlevdeR +tewwowism tezje tfortal3nt tfsi +tfw +tfzx tgchick3n +tgkiller +th0my188 +th3engineers th3m0nrr0 +th3physicis7 thaiboygoon thajokerkid +thames1000 thasonn that1stoner +thatbaldkid1 +thatbuttguy thats +thats bone thatthicksix +the 2 of us +the G herbo +the Unreal +the Zec +the afg-gun +the assail +the big girl +the capt +the creaper +the girls +the kleeborp +the lupo +the lurkkii +the mighty R +the ocean +the suns theDazzling theFish theH0witzer +theHNC theMatan123 theSuperb0wl theWOODchpr +the_blindguy theachaian thealemdar92 thebestgf thebrucelee +thecoolbro97 thecwakecake +thedamoes +thedarclit thedarklit thedyermaker theebeker +theeib +theforkster +thefunkmonk thegamebad +theguyman160 +thehow112 theironlotus thejonsson +thekingkane1 thelanco theletterbla themaestrox thematrixgg themrgiggles +theon theonebrova thepirateman therangetank +thereal bi n +therealAxu +therealchr1s +therealinfex +therealramba therminy thes5016 +thesavior315 theserpent +thesmurfster +thetibo thetoday thewooshh +they gave up thezucc thhxd +thicassglass +thicc dady thicccc thicchode thiever05 +thijssb thinker thinky this +this blunder +this gu y thiseku thisthat2019 thongmasterb +thoomed +thosma777 thot +thot tub834 thotortiana thoughtz thrakataluk +thrashcan86 +three2one0 +thricer +throat queen thrynandwen +thug z9 thugger +thugli thundeman999 +thurgo pie +thwison thx4zloot +tibbs plural +ticklemesack +tidnabregdab tienermoeder +tigerturtle0 tightteen97 tijgertje3 +tiktok rizz timaye56 timejumpsolo timmaxio @@ -30486,187 +62639,376 @@ timmyjoe643O tinmer tinnaytookit tintaria13 +tippystick tipua +tipyt0p tire +tiredcloth tisbea tissiliisa +titches wit titsanddrags titty tittyjuggler +tj44 tjappko +tjcombro tjd1233 tjomka tksnevrlucky tmahones tmeer +tmeer 18 +tmjdx tmued +to dd to0Oldf0r1t to_o toad toad03 +toasted max toastfinder toastypoast +toatsme42 +tobiasalex4r tobinoo +todd crosset todtplanker +toe2 toebumper +toes +toesmeller87 toff +toff haha +toffelboy +toffij tojo228 toks +tolerable 24 +tom hutch +tom widdle tombaum tombradynfl tominator87 tommybun +tommys488 tomrichmond9 tomriddle09 +tonko tonttitonder +tony danza tony el gros +too bad +too known +toolbar toomastoomas toonits tooowise toot +top her 1000 +topdollar topgun 17 topgun343 +topie +toptom90 toqs1986 +torfy tormutrose +toronomans torpedox1 +tosspot12 +tossta tostaempo +totip46 +tottti touhutimppa +touma +toxi +toxicburn13 +toxiclun toxicsaitama +toy Owner +tozmic +tq tr0nberg tr0nd tra1nwr3ck13 trade tradescreen +trading law traevitz traffic +trafficly trainman222 +tramayne +tranquiltoad tranqzz +trans trapbag +trapizium01 trashy trattqunnar +trav50 travym66 +trcky americ treboolks treetardo +treezy tremmu +trenboloneyy trevor4ever trevs +trevs iron +treyblob triangle28 +trickyerrr trickyricky +trickytoad59 triggaevery1 trikyricky trilla tripin +triple fin triple pre +triple zero triplefiter triplelmao +trippel agen +triv hamzy trojan break troll trolling +tropiiix trout troutking96 +troy the mak trso tru3 trucker74 truskey trustfundcat trustsfund +truucas +try the wiki +trying2quit +tryksta trytohuntme +ts4ever +tsqq tstrong5689 tsukemen +tsumino tsurie +tsw tswiftfan82 tthe ttnq +tubu +tuggly tuhdhuderr +tulieee tum0ppi +tumeken jyra +tumme tummytickler +tumunduktu tunalife tunnepelaaja turban911 turbo +turbo nut +turboChett +turboboost93 turboed son +turbogamer12 turbojoey turbothots turkishh +turkles ahmo turn the 6 +turnt turntBurrito turntgod711 turtl111 tututu tuumas +tv_vt tvmv twasnotready +twelve bags +twelvecharac +twelveswords twiceascool +twink irl +twinr0va +twisted tina +twistedgirls twisty twitterclans +twixinthemix twiztid5000 two4nine +twohandedfap +twotoedsloth twrangles +twubble +ty RuneLite +ty zmith ty4flail tyguy tyler1041 tylorLotus +typage typedef typto tyrant +tz13 +tztok-worm tzuyah tzuyufan14 u dead now09 +u got a dart +u got beaned +u itachi +u kno de wae +u r gay 4 rs +u0h uEnv uKnoTheRules uLiveButOnce +uRattt uSnAvYsEaLs7 uTBER +u_u sunshine +uberHasu btw uberstunts ubiquitous96 ubug +uchar +udq +udr uetzcayotl +ufnn +uganstolfin ugivahrimjob +ugly 67 uglyandfat +uiaF +uiliuiliu +uilz +uimi +ukn0w ukwolf1 ukzharry ulab +uliuli reps +ult u fk jzs ultimo0se +ultracet +um Cya +uma pyoi +umer +umexx +umr +umw +un deux un1versa1 +unFolly +unaroc unawareaxe +unazegamoth uncle +unclefro uncleskrt +und und3adedd undeadgun underslept +undoc uneek2you +ungafknbunga +unholyblood unitewankers unkyjay unla unless unlucky2020 +unluki unravel +unravelslapz +unreaL294 unrequited +unsoy +untc untilnextyea untitled unwarranted +unzips uppahoods upset +upset berry upwindnofear +uqx +ur a bird +ur buttugly +ur cool +ur so mad +ur stinky +ur6 +urBunsRDone urNANS +urano O_o +urashitpker urfault urgirlisf2p +urgnah8me urondelekk +urqt urvinis1 urza +usainb0ltrag +uselessbozo +uselessmap +user187 usergoeshere +userjman1428 +usinlefthand usma6100 +utiliser +utpaatur utsw +uu Sauce +uub uubaidaus +uul uuuoouuououo +uuuuhhh +uwja +uwu merchant +uwu noises +uwu24 uxbridgekid +uyakO +uz x uzei +uzis akimbo +uzui +v Simba v +v olksu +v oltage +v tsng +v uka +v yp v-yordan0702 v0i kehveli v0mbat +v13 v3kz v453 +vAnthony +vBlankie vCamel +vDragzi vFoley vJace vJordxn @@ -30675,310 +63017,662 @@ vLeqacy vNicholas vPikis vRoso +vSnoop vSpectre vTaqq vaderex-1 +vaflyga vageet vaghairs +vagtap +val val val valeriaT3amo valithi +vallihauta96 +vampfrog vampir vampiremiyo +van est +van soi vanVoren +vanacis vanacularr +varla phase vasia +vasxx +vaux One +vavmaster +vb cannsss +vb1 vbehn44 vbhos +vc +vcl +vcnyew +vcw +veEXP veergolio +veetuli10 vega591 +vegiebobs vegiitto +vekter1 veldow +velek +ven g +venazuelan vene venefae veneruuti venezuelan76 +vengedclaws vengedurmom +vennie123 +venom nate vent venturo venzano vepie +veri2222 verlord vernonb2688 versacejean5 versatility4 +vertigo love vertztheone +verychillguy +verzikius +vesikulho22 vesq vestapol +vftvmv vgtrs +vibe check vibing victoriauwu video +video peli videogamer +viento suave +vierges +viet dragon +vieze sjomp vigilant +vihervasuri +viikzt +viilipytty viki +viktor main viktoras300 +villavolta80 villeh vinigha +vinke00 vippaa virtualsucks +visdayox viserbro +vislegis vispikauha vissiman visualduck visuna vitunhomo +vitunkoyha +vitunneekers +vitur scythe vitutor +vituvahe35 vivaa vizzN +vkt vlaamsbelang +vlees petje vllekoo vlyn +vmooo829 vmxn +voddeman vodka vodkapro vodke +voi vattu void-e-d void5 +volconhammer voldersnort volga34 vomax vork4sh vorosity +vosol +vougz +voui voxi6 +voyage_zjo +voyej vpxl +vraakmanus +vriskafan888 +vro +vubervos vulnaamin vulxe vunts vuokko22 vurn +vursa vutr vuur +vuzvuz +vvBearded vval vvtt +vw +vzi +vzkg +w Danko +w e b r l +w en +w ert +w vy +w00_88 +w00d pecker +w00tgh0st +w00x titan +w00xy +w0Ive +w0ked +w0lcomcz +w33dplanter +w3n +w4kenbak3 +w5s +w6rst wYungen waaayneee +waaluigii +wack pack +wacup +waga iron wagen wagween waitwhyudead +wakecub +wakingupsad wakuser walk +walker80 +walli +walloftime39 wallyally13 +walmart nuts +walmart used walnutmonkey +waltjrs legs +wanShy +wana corp +wanna quit wanolo wapwap warcauser33 +warcraftgame +wardongs warestoteles +warface125 warm +warm cuddles +warm is vuur +warmclouds warrior warteryyy +waseem76786 +waste of alt watch +watch hp ty +waterbender +waterdrink +wathx +wavej4 wawuweewa waxRS +waxhitwonder +wayabove +wayne s new +wcdak +wdx +we died fast +weThoom +weak dummy weaknd +wealldiesoon wealthletics weaponman54 +wear croc +weary pigeon wechilling wednesdvy weeb +weeb doggo weebew +weedkillsppl +weegthe32nd +weekendfun weenscape weh8ironmen +wehde weight4 weir19 +weirdo +wekkes +wenwick weoh weppend weregild werkd +wermz8 +werndoggaa wertyer2 wesley 256 +wesley biets +wesrrules92 westsider011 +wet da bed +wet oven weve weweweweoox wewkek +wf_solo123 +wfh atm +wfsdfvwwfsdq +wfsn wh1tey95 whale +whale come +whathitu whatiswork whats +whats skills +whatsoup when +when I chant where +where ask +where moon +where noon +where yat +wheresyaboy whip2b whipbanned whiskey bow +whisoserious whispery white +whitedog8 +whitless +whizprjazpxr +whk +who is react whoawhoami +whodo +whodoyouknow whololo30 whoopdidy whoppinknob whoscherry +whotf whtmicrowave +whuchaka v +why afk +why ego whyaintyoume whyamisofat whynotp2p +whyuboolyme whyzerkbro +wi f +wibeton widefang +wiegehtsmir wienerbread wife4sale wifes wifibananas +wiidziss wikedfix +wil je ket wildarko +wildberryRS wildcheery77 wildystuff6 will +will vv +will win 2 will_mello willc893 willeehawk willie432 willis28 +willmissit willmott willsand2405 willsuck4GMK win we must +winnur +winterburnI winterdaze +wiseguy2187 +wiseoldPapi wiseoldnam wispykarma +wistfulgyre witchbladezz witeboi +witenry with +witnesspower +wiw wizard129 +wizardyoda7 wizkid499 wjsn wkurtin wlkerTXrangr wndow +wndy +wngo woah wocket +wodg woesh0 wohc +wokkejzzbak +wolfbless wolfy +wolrus wombo_zombo womp wonder_wenis wonnie wonniwonkaka woodchopp +woofmaster +wooohooo wooooom woopingcrab +wooski43 +wootex woox woox10k +wormple woshishabi +wowda woxzard +wrdd wrdflexoke wrong ranger wrsrule +wruhtra wsodonnell76 +wsvolt wtbzenyte +wtffixthis wtfix wubzh8black +wucebrilllis +wuckedenergy +wucy +wudi +wudup9696 +wuil10 wulfwulfson wussupfool wutzgood wutzit wwTakun wweadge2 +www +wwwMusic-Map wyat wyattearp99 wyked wytch wyverns4days +wzav423 wzrdddddyo +wzrds +wzs +x 0lev x +x ABBlE +x Argonath x +x Chainz x +x Chelli +x D E E x +x Dante +x Fabinho +x FiFi +x Flux x GS Cookies +x Haste +x Kane x +x Kierac x +x L i o n +x Lady +x Lafferty x +x LostBoy +x Mayhem +x Ndo +x Nex +x Not blue x +x Nym +x Pho +x Red Rum +x Ryu +x Ryuu +x Sorvete +x Verzik x x Zela +x Zink +x a t +x e l a b +x gladiat0r +x husla x iNtrigue +x iyad x +x lollage x +x mk ultra +x preska x +x r +x warri0r121 +x zi +x zn +x073x +x0Mag x0Tub x12ob1n +x1deag +x1flyx +x235 +x2u mania +x3 nuzzle +x7 Curvelo +x86 +x8737 x8mz3hg7zm5f +xAFK_BTWx +xAbysss xAddictive +xAeroWolf +xAndrew +xBL00DSTREAM xBaNeSoldier +xBarlah xBayLiss +xBeefStonks xBeerbear xBehavior xBellax xBenny xBlackDahlia +xBongzilla +xBootySlayer xBottleCap +xBotty +xBowlofPhox xBrendyy +xBrimz xBrown xBusse +xCUFFSx xCallT0Armsx +xCarter +xCastiiel xCheeseheadx +xChemistry +xCherish +xChew xChiro +xChyeaa xClf +xClifffff xCloudie xCodeh xComposure +xD1E xDCx152 +xDOMIN1C +xDRAYx xDab of Iron +xDaf xDagon +xDapzz xDat xDevastor +xDevil +xDied xDieter xDijon +xDilexro +xDingy +xDora +xDoremonx xDrawingDead xDuckyV xET99 +xElliott xElsa +xEnforcerx +xEtiquette xExclusive xFMSx xFailBoatx +xFirespiritx +xFlea +xFloaty +xFranku xFraz +xFremmy xFruity xGallarzax xGigz xGoat +xGongo xGrant xGusBus xH1ckz xH4rry xHades xHamzha +xHannna xHartliss xHarty +xHayez +xHearTBow +xHerp xHmongHerox +xHugsi xHussla xI3reeze +xIron Senpai +xJeb xJiren xJlN +xJolt xJord xJordd xJulia xJuve +xKAJJEx +xKadi +xKdpunx xKing xKodai xKrab +xKril +xL2MUZZx +xLayLay +xLelooToo +xLester +xLrc xLuXx xLumby xLunatiQ xLynn xMBx xMEKANIKx +xMMGx xMardy xMarkos +xMassx xMatah +xMatty +xMedicate xMentalXx +xMetharos +xMewzic +xMochiix xMonkey +xMp5 xMyrupz +xN I K Ex +xNatureladx xNeilzus xNerevar +xNgocdol +xNickaap xNova +xO Poe xOBG +xOG420 xOnetickFap xPager +xPedu xPhil +xPortgas +xPussSmasher xQSS xQuantumxx +xRICK OWENSx +xRadagonx xRakine xRaptor +xReaperx666x xReckless +xRedGlow +xRefactor +xRektByAMain xRemyLacroix xRipple +xRivv xRobdebankx xRobertox22 +xRobscapes xRxmeo xSPAGHETTIx xSamR xScooter +xScribbz +xScrimp xSecret xSeized xServing @@ -30992,184 +63686,419 @@ xSleepgoodx xSlysoft xSnaytronSx xSnvw +xSoKi +xSteezy xSweetHopex xSword +xSxAxMx xSynn +xT o m +xT0A +xTERRIBLEx xTKOx xTWM xTerpenes +xThirlmere +xTopher +xTorsti xTransfer xTrigger xTwister xVektor xVenomx9 xVoidRange +xW R A T Hx +xWANNTEDx xWar +xWarface +xWillowTreex xWillx93 xWoke xWoodChopx +xX Bez Xx xXBlitzO xXCaBiDeXx +xXDurryXx +xXGIMP420Xx xXJoshUKXxHD +xXNaliXx xXightx +xXshadowz7Xx +xYogibear xZAKATAKx xZCH xZITOx +xZayin +xZeeBaby xZuk x_Goddess_xz +x_Huzy_x +x_Theron +x_x Fish +x_xMGKx_x +xaa2 +xaarpus +xal din +xangoose xansinmybody xaoeu xapd xaro xaxon xbox +xboxkid xc00lxDawgx +xceasea xcoda +xcrolles xcvbg +xd domi +xd jumper +xdamanx +xeem xegaF +xemulate +xenaines xeney +xenomuslol xenvzi xeravier xerkin +xexezinh0 +xfishngrillx +xfxe xgamerxx +xhamstr xhard82x xhennamariax xhoq +xi execut3 x +xi li er +xiBubbax +xiaohongshu +xiaolingxiao +xienn +ximix +xinnox xir0nm4skx +xirampagezz xironluckx +xiwitl +xjawz1e +xl Aaron lx +xl cook +xlDerekxl +xlReversal xlibrio xlr704 +xlxl xlxl +xmikeyx +xmxxmx56 xoKt xoRUNExo +xolindseyxo +xoreZ xoro xoxoverdose xozoca +xp per hour +xp waster 47 +xpabax +xpcumsez xpeyotex +xplo it +xpoltergiest xpwast3d +xrated xslayerbobx xson xspacedoll xstic xtcoming999 +xthn +xtothedee xttx xtyrantix +xvn +xvrph +xvza +xwl xwuwesxdrf +xx darkminer xxDerp xxMatter +xxREVENANTxx xxSabin09xx xxSe7en +xxTanner +xxcombatgodx +xxero +xxok xxpurskillxx xxx2sp3cuxxx +xyujah xyzn +xzanle +xzb +xzizzil +xzn 2 +xzwu +y om +y w +y0y0keepitup +y37ir y8s1 +yTried +ya pig +ya winning yaJaeT yaboyalex +yack daniels yacobson99 +yae yahn yai5 yamawaro yamb0 +yamsauze yankmynads yannickal4 +yanq10 +yaowiee +yapgragim +yasuo god69 yayasquirrel ydoc +ye idc +ye ki M +ye p to +yea im jebus yeahboi9992 +yeahsmitty +yeahyoink yearstowaste +yeastyboys yechu +yedgy +yee yee fkrs yeet +yellow car01 yeniL yerrakunt yesigame yesy0u yinghao870 +yinksnerf yinonormal yipcl yippie1317 yispaulcute +ykO Ops +ykeL +yleisradio ylliB +ym y ymca4life +yna +yo eight +yo itz ep +yobacha yodA yoda +yoda monkey yohaha123 yolomuffin +yonex +yonghoon +yooyeet +yorkietootz +yorue +you died123 +you r a qt youb1n +youneedcope +young meows +young vibby +youngbriks +youngmachine youngtrop21 youngwings +youpougou your +your thrall youralterego +youssef +yowasupppbra +yoyoma361 +yp +ypoodle +ypool4 ypools +yragbackward +yrhs yribbles +ytsud mi +ytuiop +yugiiii +yuh huh +yum +yummybolete yung +yung chubs +yung cody yung inf +yungando +yungcozzy +yuor yurciq +yuy165 +yves klein +yvonko ywwoT yxow +yyknaH J +yyttam yyzanadu94 +yzyzyzy +z 5 x +z Animal z +z Rhodes +z Shane +z a p s +z iQ +z man827 z0nk +z0rrda z0up +z1ftz +z4np +z5p +z7co +zBando zBenn zBonesz zCocoa zDaremeth zDeku +zFalcone68 +zGameDance +zGanj +zGibao +zGz zJenga zKamp +zKno zKuru zLost +zMonchi +zNico +zNolan zRarePiece +zRavenx zSlay +zSpaceRaptor +zSwanny zTitan zWxLF +za2 za33erklan zaaza zacharial +zachhy zachte zack +zack_0333 +zacyy zaddy +zak vol zalm zakaru9999 +zakk0 +zakrey +zakrobgames zalem +zancan2 +zapper920 zarehp zarfeq +zartrez zasmaru +zatch_maxed +zazalover69 +zazazhizhma zazyga +zbra zclx zcollins +zdi zdin +zdya ze4l zeKrD zeachh zeall +zeano +zebakkes +zeccStake +zedabranca zeddicus676 zedisabled zedzke +zeeebak zeeno zegg +zehstee +zeikhannes zeker zeldris +zelo1 zendendead zenmort zensix +zenuk zay zenyte4money +zeppelin0ooh zeqha zer0 zer0sirisFHK +zerker seven zerkhelm zero zero gd +zero u_u +zeroblade81 zeroixx zerotwonine zeroz136 zerzerz +zeus energy zewos +zewzh +zhengu +zhipowerz zi0n1 +zibri7 +ziewe zifyr +ziggy man 77 +ziily zilyana zina +zina n chill zinax +ziniD +zinzares +zionari +zippp zirreael +ziurbtw +ziuys ziyi_wangler +zjh +zjind +zlayaa zlink10 zlliM +zlowden zmakisan znap5 zoan @@ -31177,35 +64106,55 @@ zoboz zohcysp zokunashi zole +zomff zomgrick zonares zookwaa zoomixd zop1 zorkie +zoro u zouse +zparky +zppr +zq0 zreL +zrl zruG zrzwns ztaM ztkfps +zu b zubor1 zuenzima +zujal +zuk a cuck +zuk xd +zuk2hard4me +zukushichi +zulogz zulrah zuluTriPig zummorak zurcc zurlond zuuryy +zw zwah zwint zwolle zwqpDEOXl23 +zxpf zyeetz +zygarde92 zygis323 +zykez zymaa zymz zysuna +zzad zzai +zzben zzero zzigma +zzzJonno diff --git a/Server/src/main/content/global/bots/Adventurer.kt b/Server/src/main/content/global/bots/Adventurer.kt index a6c69e8e1..916503945 100644 --- a/Server/src/main/content/global/bots/Adventurer.kt +++ b/Server/src/main/content/global/bots/Adventurer.kt @@ -12,15 +12,16 @@ import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.zone.ZoneBorders import core.game.world.update.flag.* -import core.tools.RandomFunction import org.json.simple.JSONArray import org.json.simple.JSONObject import core.ServerConstants +import core.api.log import core.game.bots.AIRepository import core.game.bots.CombatBotAssembler import core.game.bots.Script import core.game.interaction.IntType import core.game.interaction.InteractionListeners +import core.tools.Log import java.io.File import java.io.FileReader import java.time.LocalDateTime @@ -40,21 +41,27 @@ import kotlin.random.Random * @author Ceikry */ -//Adventure Bots v4.0.0 -Expansion Edition- +// Adventure Bots v1.1.0 : Expansion Edition (Previously v4.0.0) +// Super Grand Exchange Update class Adventurer(val style: CombatStyle): Script() { var city: Location = lumbridge - var ticks = 0 - var freshspawn = true - var sold = false - private val geloc: Location = if (Random.nextBoolean()){ - Location.create(3165, 3487, 0) - }else{ - Location.create(3164, 3492, 0) - } + var poiloc: Location = karamja + var geSocialLoc: Location = getRandomGESocialLocation() + var geClerkLoc: Location = getRandomGELocation() + var geClerksloc: Location = neGEClerk + var freshspawn: Boolean = true + var sold: Boolean = false + var poi: Boolean = false + + val chance: Int = if (cityLocationsGE.contains(city)) 3500 else 3000 + var ticks: Int = 0 var counter: Int = 0 - var random: Int = (5..30).random() + val waitTotal: Int = 8 + var returnToAdventure: Int = 0 + var geWait: Int = 0 + var geLongWait: Int = 0 val type = when(style){ CombatStyle.MELEE -> CombatBotAssembler.Type.MELEE @@ -74,23 +81,81 @@ class Adventurer(val style: CombatStyle): Script() { } override fun toString(): String { - return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city" + return "${bot.username} is an Adventurer bot " + + "at ${bot.location}! " + + "State: $state - " + + "City: $city - " + + "Ticks: $ticks - " + + "Freshspawn: $freshspawn - " + + "Sold: $sold - " + + "Counter: $counter" } var state = State.START - fun getRandomCity(): Location{ + private fun getRandomCity(): Location{ return cities.random() } - fun getRandomPoi(): Location{ + private fun getRandomPoi(): Location{ return pois.random() } + private fun getRandomGESocialLocation(): Location{ + return socialLocationsGE.random() + } + + private fun getRandomGELocation(): Location { + return cityLocationsGE.random() + } + + private fun randomNumberFromOne(maxInt: Int): Int { + return Random.nextInt(0, maxInt) + } + + private fun otherPlayersNearby(): Boolean { + val localPlayers = RegionManager.getLocalPlayers(bot) + val otherPlayers = localPlayers.filter { it.name != bot.name } + return otherPlayers.isNotEmpty() + } + + private fun checkNearBank() { + if(bankMap[city] == null){ + scriptAPI.teleport(getRandomCity().also { city = it }) + } else { + if(bankMap[city]?.insideBorder(bot) == true){ + state = State.FIND_BANK + } else { + bankMap[city]?.let { scriptAPI.walkTo(it.randomLoc) } + } + } + } + + private fun checkCounter(maxCounter: Int) { + if (counter++ >= maxCounter) { + state = State.TELEPORTING + } + } + + private fun teleportToRandomCity() { + city = getRandomCity() + when (city) { + neGEClerk -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-3,2,0,1,0)) } + swGEClerk -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-2,3,-1,0,0)) } + nwGEBanker -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-2,0,-3,2,0)) } + seGEBanker -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,0,2,-2,3,0)) } + else -> { scriptAPI.teleport(scriptAPI.randomizeLocationInRanges(city,-1,1,-1,1,0)) } + } + } + + val resources = listOf( + "Rocks","Tree","Oak","Willow", + "Maple tree","Yew","Magic tree", + "Teak","Mahogany") + //TODO: Optimise and adjust how bots handle picking up ground items further. fun immerse() { - if (counter++ == 180) {state = State.TELEPORTING - } + if (counter++ >= Random.nextInt(150,300)) { state = State.TELEPORTING } val items = AIRepository.groundItems[bot] if (Random.nextBoolean()) { if (items.isNullOrEmpty()) { @@ -98,33 +163,13 @@ class Adventurer(val style: CombatStyle): Script() { state = State.LOOT_DELAY } if (bot.inventory.isFull) { - if(bankMap[city] == null){ - scriptAPI.teleport(getRandomCity().also { city = it }) - } else { - if(bankMap[city]?.insideBorder(bot) == true){ - state = State.FIND_BANK - } else { - scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0)) - } - } + checkNearBank() } } else { if (bot.inventory.isFull){ - if(bankMap[city] == null){ - scriptAPI.teleport(getRandomCity().also { city = it }) - } else { - if(bankMap[city]?.insideBorder(bot) == true){ - state = State.FIND_BANK - } else { - scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0)) - } - } + checkNearBank() } else { - val resources = listOf( - "Rocks","Tree","Oak","Willow", - "Maple tree","Yew","Magic tree", - "Teak","Mahogany") val resource = scriptAPI.getNearestNodeFromList(resources,true) if(resource != null){ if(resource.name.contains("ocks")) InteractionListeners.run(resource.id, @@ -137,18 +182,17 @@ class Adventurer(val style: CombatStyle): Script() { } fun refresh() { +// log(this::class.java, Log.WARN, "${bot.username} refreshed from $state at $city with $ticks and $counter counter.") scriptAPI.teleport(lumbridge) - freshspawn = true state = State.START } - var poi = false - var poiloc = karamja - //Adventure Bots Actual Code STARTS HERE!!! + // 100 ticks = 60 seconds override fun tick() { ticks++ - if (ticks++ >= 800) { + // Hard refresh + if (ticks >= 1000) { ticks = 0 refresh() return @@ -186,49 +230,42 @@ class Adventurer(val style: CombatStyle): Script() { } return } else { - state = State.EXPLORE + state = State.ADVENTURE } } State.START -> { if (freshspawn) { freshspawn = false - scriptAPI.randomWalkTo(lumbridge, 20) + scriptAPI.randomWalkTo(lumbridge, randomNumberFromOne(25)) } else { - city = getRandomCity() state = State.TELEPORTING } } State.TELEPORTING -> { + if (freshspawn){ freshspawn = false } + teleportToRandomCity() + poi = false + sold = false ticks = 0 counter = 0 - if (bot.location != city) { - poi = false - scriptAPI.teleport(city) - } else { - poi = false - state = State.EXPLORE - } + state = State.ADVENTURE + return } - State.EXPLORE -> { - if (counter++ == 350) { - state = State.TELEPORTING - } - - val chance = if (city == ge || city == ge2) 5000 else 2500 - if (RandomFunction.random(chance) <= 10) { - val nearbyPlayers = RegionManager.getLocalPlayers(bot) - if (nearbyPlayers.isNotEmpty()) { + State.ADVENTURE -> { + checkCounter(800) + if (randomNumberFromOne(chance) <= 10) { + if (otherPlayersNearby()) { ticks = 0 dialogue() } } - if (RandomFunction.random(1000) <= 150 && !poi) { - val roamDistance = if (city != ge && city != ge2) 225 else 7 - if ((city == ge || city == ge2) && RandomFunction.random(100) < 90) { + if (!poi && randomNumberFromOne(1000) <= 75) { + val roamDistance = if (!cityLocationsGE.contains(city)) 225 else randomNumberFromOne(5) + if (cityLocationsGE.contains(city) && randomNumberFromOne(100) < 90) { if (!bot.bank.isEmpty) { state = State.FIND_GE } @@ -238,33 +275,46 @@ class Adventurer(val style: CombatStyle): Script() { return } - if (RandomFunction.random(1000) <= 50 && poi){ + if (poi && randomNumberFromOne(1000) <= 100){ + immerse() + return + } + + if (poi && randomNumberFromOne(1000) <= 25){ + dialogue() + } + + if (poi && randomNumberFromOne(1000) <= 50){ val roamDistancePoi = when(poiloc){ - teakfarm, crawlinghands -> 5 - treegnome -> 50 - isafdar -> 40 - eaglespeek -> 40 - keldagrimout -> 30 - teak1 -> 30 - miningguild -> 5 - magics, coal -> 7 gemrocks, chaosnpc, chaosnpc2 -> 1 + magics, coalTrucks -> 7 + miningguild, teakfarm, crawlinghands -> 5 + varLumberYard -> 20 + keldagrimout, teak1 -> 30 + eaglespeek, isafdar -> 40 + treegnome -> 50 else -> 60 } scriptAPI.randomWalkTo(poiloc,roamDistancePoi) return } - if (RandomFunction.random(1000) <= 75) { - if (city != ge && city != ge2) { + if (randomNumberFromOne(1000) <= 75) { + if (!cityLocationsGE.contains(city)) { + ticks = 0 immerse() return - } else { - return + } else if (randomNumberFromOne(chance) <= 55 && otherPlayersNearby()) { + ticks = 0 + dialogue() } } - if (RandomFunction.random(20000) <= 60 && !poi) { + if (cityLocationsGE.contains(city) && randomNumberFromOne(1000) <= 50) { + state = State.IDLE_GE + } + + if (!poi && randomNumberFromOne(1000) <= 5) { poiloc = getRandomPoi() city = teak1 poi = true @@ -272,26 +322,24 @@ class Adventurer(val style: CombatStyle): Script() { return } - if ((city == ge || city == ge2) && RandomFunction.random(1000) >= 999) { - ticks = 0 - city = getRandomCity() + if (cityLocationsGE.contains(city) && randomNumberFromOne(1000) <= 100) { state = State.TELEPORTING - } - - if (city == ge || city == ge2) { return } - if (city == teak1 && counter++ >= 240){ - city = getRandomCity() - state = State.TELEPORTING + if (cityLocationsGE.contains(city)) { + return } - if (counter++ >= 240 && RandomFunction.random(100) >= 10) { + if (poi && randomNumberFromOne(1000) <= 20){ + state = State.TELEPORTING + return + } + + if (counter++ >= 750 && randomNumberFromOne(100) <= 50) { +// log(this::class.java, Log.FINE, "${bot.username} has moved on to a different city at $ticks ticks and $counter counter.") city = getRandomCity() - if (RandomFunction.random(100) % 2 == 0) { - counter = 0 - ticks = 0 + if (randomNumberFromOne(100) % 2 == 0) { state = State.TELEPORTING } else { if (citygroupA.contains(city)) { @@ -309,122 +357,122 @@ class Adventurer(val style: CombatStyle): Script() { return } - State.GE -> { - var ge = false - if (counter++ == 180) { - state = State.TELEPORTING - } - if (!sold) { - if (counter++ >= 15) { - sold = true - ge = true + State.IDLE_GE -> { + returnToAdventure = Random.nextInt(350, 750) + if (counter++ >= returnToAdventure){ + if (randomNumberFromOne(100) <= 25){ + ticks = 0 + counter = 0 + poiloc = getRandomPoi() + city = teak1 + poi = true + scriptAPI.teleport(poiloc) + state = State.ADVENTURE + return + } else { counter = 0 ticks = 0 - scriptAPI.sellAllOnGeAdv() + state = State.TELEPORTING + return + } + } + if (cityLocationsGE.contains(city)){ + if (randomNumberFromOne(1000) <= 5) { + ticks = 0 + geSocialLoc = scriptAPI.randomizeLocationInRanges(getRandomGESocialLocation(),-1,1,-1,1,0) + } else if (randomNumberFromOne(1000) <= 10) { + ticks = 0 + scriptAPI.randomWalkTo(geSocialLoc, randomNumberFromOne(5)) + return + } + if (randomNumberFromOne(1000) <= 5 && otherPlayersNearby()){ + ticks = 0 + dialogue() + } else if (randomNumberFromOne(1000) <= 250){ return } - } else if (ge && sold) { - ge = false - city = getRandomCity() - state = State.TELEPORTING } return } State.FIND_GE -> { - if (counter++ == 180) { - state = State.TELEPORTING - } sold = false val ge: Scenery? = scriptAPI.getNearestNode("Desk", true) as Scenery? - if (ge == null || bot.bank.isEmpty) state = State.EXPLORE + if (ge == null || bot.bank.isEmpty) state = State.ADVENTURE class GEPulse : MovementPulse(bot, ge, DestinationFlag.OBJECT) { override fun pulse(): Boolean { bot.faceLocation(ge?.location) - state = State.GE - return true + return true.also { state = State.GE } } } + if (ge == null || bot.bank.isEmpty) state = State.ADVENTURE if (ge != null && !bot.bank.isEmpty) { - counter = 0 - scriptAPI.randomWalkTo(geloc, 3) - GameWorld.Pulser.submit(GEPulse()) + if (randomNumberFromOne(1000) <= 25 && otherPlayersNearby()){ + dialogue() + scriptAPI.randomWalkTo(geSocialLoc, randomNumberFromOne(5)) + } else if (randomNumberFromOne(500) <= 50) { + GameWorld.Pulser.submit(GEPulse()) + } } + checkCounter(500) + return + } + + State.GE -> { + geClerksloc = clerkLocationsGe.random() + geWait = Random.nextInt(35, 100) + geLongWait = Random.nextInt(350, 750) + if (!sold) { + if (randomNumberFromOne(500) <= 25){ scriptAPI.randomWalkTo(geClerksloc, randomNumberFromOne(4))} + if (counter++ >= geWait) { + scriptAPI.randomWalkTo(geClerksloc, randomNumberFromOne(1)) + sold = true + counter = 0 + ticks = 0 + scriptAPI.sellAllOnGeAdv() + state = State.TELEPORTING + return + } + } else if (counter++ >= geLongWait) { + state = State.TELEPORTING + return + } + checkCounter(1000) return } State.FIND_BANK -> { - if (counter++ == 300) { - state = State.TELEPORTING - } val bank: Scenery? = scriptAPI.getNearestNode("Bank booth", true) as Scenery? - if (badedge.insideBorder(bot) || bot.location == badedge2 || bot.location == badedge3 || bot.location == badedge4) { - bot.randomWalk(5, 5) - } - if (bank == null) state = State.EXPLORE - class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) { - override fun pulse(): Boolean { - bot.faceLocation(bank?.location) - state = State.IDLE_BANKS - return true - } - } - if (bank != null) { - bot.pulseManager.run(BankingPulse()) + if (bank == null) { state = State.TELEPORTING } + if (bank != null && randomNumberFromOne(100) <= 5) { + scriptAPI.depositAtBank() + } else if (bank != null && randomNumberFromOne(100) <= 5){ + scriptAPI.randomWalkTo(bank.location,3) } + checkCounter(500) return } - State.IDLE_BANKS -> { - if (counter++ == 300) { - state = State.TELEPORTING - } - if (RandomFunction.random(1000) < 100) { - for (item in bot.inventory.toArray()) { - item ?: continue - when (item.id) { - 1359, 590, 1271, 995 -> continue - } - bot.bank.add(item) - bot.inventory.remove(item) - } - counter = 0 - state = State.EXPLORE - } - return - } State.FIND_CITY -> { - if (counter++ >= 600 || (city == ge || city == ge2)) { - counter = 0 + if (counter++ >= 500 || cityLocationsGE.contains(city)){ scriptAPI.teleport(getRandomCity().also { city = it }) - state = State.EXPLORE + state = State.ADVENTURE } if (bot.location.equals(city)) { - state = State.EXPLORE + state = State.ADVENTURE } else { - scriptAPI.randomWalkTo(city, 5) + scriptAPI.randomWalkTo(city, randomNumberFromOne(10)) } + checkCounter(600) return } - State.IDLE_CITY -> { - if (counter++ == 300) { - state = State.TELEPORTING - } - var random = (120..300).random() - if (counter++ == random && RandomFunction.random(1000) % 33 == 0) { - counter = 0 - state = State.EXPLORE - } - return - } } } fun dialogue() { - val localPlayer = RegionManager.getLocalPlayers(bot).random() val until = 1225 - dateCode val lineStd = dialogue.getLines("standard").rand() var lineAlt = "" @@ -455,20 +503,29 @@ class Adventurer(val style: CombatStyle): Script() { dateCode == 404 -> lineAlt = dialogue.getLines("easter").rand() } - val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd } - .replace("@name", localPlayer.username) - .replace("@timer", until.toString()) - - scriptAPI.sendChat(chat) + var localPlayers = RegionManager.getLocalPlayers(bot) + if (localPlayers.isNotEmpty()) { + val localPlayer = localPlayers + .filter { it.name != bot.name } + .randomOrNull() + if (localPlayer != null) { + val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd } + .replace("@name", localPlayer.username) + .replace("@timer", until.toString()) + scriptAPI.sendChat(chat) + } else { + val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd } + scriptAPI.sendChat(chat) + } + } } enum class State{ START, - EXPLORE, + ADVENTURE, FIND_BANK, - IDLE_BANKS, FIND_CITY, - IDLE_CITY, + IDLE_GE, GE, TELEPORTING, LOOT, @@ -489,44 +546,94 @@ class Adventurer(val style: CombatStyle): Script() { } companion object { - val badedge = ZoneBorders(3094, 3494, 3096, 3497) - val badedge2 = Location.create(3094, 3492, 0) - val badedge3 = Location.create(3094, 3490, 0) - val badedge4 = Location.create(3094, 3494, 0) - + // Start Cities val yanille: Location = Location.create(2615, 3104, 0) val ardougne: Location = Location.create(2662, 3304, 0) val seers: Location = Location.create(2726, 3485, 0) val edgeville: Location = Location.create(3088, 3486, 0) - val ge: Location = Location.create(3168, 3487, 0) - val ge2: Location = Location.create(3161, 3493, 0) val catherby: Location = Location.create(2809, 3435, 0) val falador: Location = Location.create(2965, 3380, 0) val varrock: Location = Location.create(3213, 3428, 0) val draynor: Location = Location.create(3080, 3250, 0) val rimmington: Location = Location.create(2977, 3239, 0) val lumbridge: Location = Location.create(3222, 3219, 0) - val karamja = Location.create(2849, 3033, 0) - val alkharid = Location.create(3297, 3219, 0) - val feldiphills = Location.create(2535, 2919, 0) - val isafdar = Location.create(2241, 3217, 0) - val eaglespeek = Location.create(2333, 3579, 0) - val canafis = Location.create(3492, 3485, 0) - val treegnome = Location.create(2437, 3441, 0) - val teak1 = Location.create(2334, 3048, 0) - val teakfarm = Location.create(2825, 3085, 0) - val keldagrimout = Location.create(2724,3692,0) - val miningguild = Location.create(3046,9740,0) - val magics = Location.create(2285,3146,0) - val coal = Location.create(2581,3481,0) - val crawlinghands = Location.create(3422,3548,0) - val gemrocks = Location.create(2825,2997,0) - val chaosnpc = Location.create(2612,9484,0) - val chaosnpc2 = Location.create(2580,9501,0) - val taverly = Location.create(2909, 3436, 0) + val karamja: Location = Location.create(2849, 3033, 0) + val alkharid: Location = Location.create(3297, 3219, 0) + + // Start POI + val feldiphills: Location = Location.create(2535, 2919, 0) + val isafdar: Location = Location.create(2241, 3217, 0) + val eaglespeek: Location = Location.create(2333, 3579, 0) + val canafis: Location = Location.create(3492, 3485, 0) + val treegnome: Location = Location.create(2437, 3441, 0) + val teak1: Location = Location.create(2334, 3048, 0) + val teakfarm: Location = Location.create(2825, 3085, 0) + val keldagrimout: Location = Location.create(2724,3692, 0) + val miningguild: Location = Location.create(3046,9740, 0) + val magics: Location = Location.create(2285,3146, 0) + val coalTrucks: Location = Location.create(2581,3481, 0) + val crawlinghands: Location = Location.create(3422,3548, 0) + val gemrocks: Location = Location.create(2825,2997, 0) + val chaosnpc: Location = Location.create(2612,9484, 0) + val chaosnpc2: Location = Location.create(2586, 9501, 0) + val varLumberYard: Location = Location.create(3289, 3482, 0) + val taverly: Location = Location.create(2909, 3436, 0) + + val swGEClerk: Location = Location.create(3164, 3487, 0) + val neGEClerk: Location = Location.create(3165, 3492, 0) + val nwGEBanker: Location = Location.create(3162, 3490, 0) + val seGEBanker: Location = Location.create(3167, 3489, 0) + + val badedge = ZoneBorders(3094, 3494, 3096, 3497) + val badedge2: Location = Location.create(3094, 3492, 0) + val badedge3: Location = Location.create(3094, 3490, 0) + val badedge4: Location = Location.create(3094, 3494, 0) + var citygroupA = listOf(falador, varrock, draynor, rimmington, lumbridge, edgeville) var citygroupB = listOf(yanille, ardougne, seers, catherby) + val cities = listOf( + swGEClerk, neGEClerk, nwGEBanker, seGEBanker, + yanille, ardougne, seers, catherby, + falador, varrock, draynor, rimmington, + lumbridge, edgeville + ) + + val pois = listOf( + karamja, karamja, alkharid, + alkharid, feldiphills, feldiphills, + isafdar, eaglespeek, eaglespeek, + canafis, treegnome, treegnome, + teak1, teakfarm, keldagrimout, + miningguild, coalTrucks, crawlinghands, + magics, gemrocks, chaosnpc, chaosnpc, + chaosnpc2, taverly, + varLumberYard) + + val cityLocationsGE = listOf(swGEClerk, neGEClerk, nwGEBanker, seGEBanker) + + val socialLocationsGE = listOf( + Location.create(3158, 3483, 0), + Location.create(3165, 3480, 0), + Location.create(3172, 3483, 0), + Location.create(3174, 3489, 0), + Location.create(3171, 3497, 0), + Location.create(3164, 3499, 0), + Location.create(3157, 3497, 0), + Location.create(3155, 3489, 0), + Location.create(3167, 3492, 0), + Location.create(3162, 3492, 0), + Location.create(3162, 3487, 0), + Location.create(3167, 3487, 0) + ) + + val clerkLocationsGe = listOf( + Location.create(3165, 3492, 0), + Location.create(3164, 3492, 0), + Location.create(3164, 3487, 0), + Location.create(3165, 3487, 0) + ) + var bankMap = mapOf( falador to ZoneBorders(2950, 3374, 2943, 3368), varrock to ZoneBorders(3182, 3435, 3189, 3446), @@ -538,22 +645,10 @@ class Adventurer(val style: CombatStyle): Script() { catherby to ZoneBorders(2807, 3438, 2811, 3441) ) - val cities = listOf(yanille, ardougne, seers, catherby, falador, varrock, - draynor, rimmington, lumbridge, ge, ge2, edgeville) - - val pois = listOf( - karamja, karamja, alkharid, - alkharid, feldiphills, feldiphills, - isafdar, eaglespeek, eaglespeek, - canafis, treegnome, treegnome, - teak1, teakfarm, keldagrimout, - miningguild, coal, crawlinghands, - magics, gemrocks, chaosnpc, chaosnpc, - chaosnpc2, taverly) - private val whiteWolfMountainTop = Location(2850, 3496, 0) private val catherbyToTopOfWhiteWolf = arrayOf(Location(2856, 3442, 0), Location(2848, 3455, 0), Location(2848, 3471, 0), Location(2848, 3487, 0)) private val tavleryToTopOfWhiteWolf = arrayOf(Location(2872, 3425, 0), Location(2863, 3440, 0), Location(2863, 3459, 0), Location(2854, 3475, 0), Location(2859, 3488, 0)) + val common_stuck_locations = mapOf( // South of Tavlery dungeon ZoneBorders(2878, 3386, 2884, 3395) to { it: Adventurer -> diff --git a/Server/src/main/core/game/bots/CombatBotAssembler.kt b/Server/src/main/core/game/bots/CombatBotAssembler.kt index 7655d98e9..ebbed1402 100644 --- a/Server/src/main/core/game/bots/CombatBotAssembler.kt +++ b/Server/src/main/core/game/bots/CombatBotAssembler.kt @@ -53,7 +53,7 @@ class CombatBotAssembler { val bot = CombatBot(location) generateStats(bot, tier, Skills.RANGE, Skills.DEFENCE) - gearRangedBot(bot, crossbow ?: Random().nextInt() % 2 == 0) + gearRangedBot(bot, (crossbow ?: (Random().nextInt() % 2)) == 0) return bot } @@ -82,7 +82,7 @@ class CombatBotAssembler { fun MeleeAdventurer(tier: Tier, location: Location): CombatBot { val bot = CombatBot(location) var max = 0 - val level = RandomFunction.random(25, 65).also {max = 99 } + val level = RandomFunction.random(25, 69).also {max = 99 } generateStats(bot,tier,Skills.ATTACK, Skills.STRENGTH, Skills.DEFENCE) bot.skills.setStaticLevel(Skills.HITPOINTS, level) bot.skills.setStaticLevel(Skills.ATTACK, level + 5) @@ -114,7 +114,7 @@ class CombatBotAssembler { fun RangeAdventurer(tier: Tier, location: Location): CombatBot { val bot = CombatBot(location) var max = 0 - val level = RandomFunction.random(35, 65).also {max = 75 } + val level = RandomFunction.random(35, 69).also {max = 75 } generateStats(bot,tier,Skills.ATTACK, Skills.STRENGTH) bot.skills.setStaticLevel(Skills.HITPOINTS, level) bot.skills.setStaticLevel(Skills.DEFENCE, level) diff --git a/Server/src/main/core/game/bots/GeneralBotCreator.kt b/Server/src/main/core/game/bots/GeneralBotCreator.kt index 361247a36..7e3cb5478 100644 --- a/Server/src/main/core/game/bots/GeneralBotCreator.kt +++ b/Server/src/main/core/game/bots/GeneralBotCreator.kt @@ -98,7 +98,7 @@ class GeneralBotCreator { }*/ if(!botScript.running) return true //has to be separated this way or it double-submits the respawn pulse. - if (botPulsesTriggeredThisTick++ >= 50) + if (botPulsesTriggeredThisTick++ >= 75) return false val idleRoll = RandomFunction.random(10) diff --git a/Server/src/main/core/game/bots/ScriptAPI.kt b/Server/src/main/core/game/bots/ScriptAPI.kt index 85ac568c1..5a3306e4c 100644 --- a/Server/src/main/core/game/bots/ScriptAPI.kt +++ b/Server/src/main/core/game/bots/ScriptAPI.kt @@ -54,6 +54,7 @@ import kotlin.math.pow import kotlin.math.sqrt import core.ServerConstants import core.api.utils.Vector +import kotlin.random.Random class ScriptAPI(private val bot: Player) { val GRAPHICSUP = Graphics(1576) @@ -396,6 +397,20 @@ class ScriptAPI(private val bot: Player) { } } + /** + * @param location the location you want the coordinates randomized for. + * @param xMin the minimum range value X coordinates should be randomized by, must be xMin <= xMax ex: -1 min 1 max. + * @param xMax the maximum range value X coordinates should be randomized by, must be xMin <= xMax ex: -1 min 1 max. + * @param yMin the minimum range value Y coordinates should be randomized by, must be yMin <= yMax ex: -1 min 1 max. + * @param yMax the maximum range value Y coordinates should be randomized by, must be yMin <= yMax ex: -1 min 1 max. + * @param staticZ this value is static and does not change from what is given, must be actual Z value of location. + * @author Kermit + */ + fun randomizeLocationInRanges(location: Location, xMin: Int, xMax: Int, yMin: Int, yMax: Int, staticZ: Int): Location { + val newX = location.x + Random.nextInt(xMin, xMax) + val newY = location.y + Random.nextInt(yMin, yMax) + return Location(newX, newY, staticZ) + } /** * The iterator for long-distance walking. Limited by doors and large obstacles like mountains. @@ -553,7 +568,7 @@ class ScriptAPI(private val bot: Player) { 1517 -> continue 1519 -> continue 1521 -> continue - else -> Repository.sendNews(SERVER_GE_NAME + " just offered " + itemAmt + " " + ItemDefinition.forId(actualId).name.toLowerCase() + " on the GE.") + else -> sendNews(SERVER_GE_NAME + " just offered " + itemAmt + " " + ItemDefinition.forId(actualId).name.lowercase() + " on the GE.") } } bot.bank.remove(item) @@ -562,7 +577,35 @@ class ScriptAPI(private val bot: Player) { return true } } - bot.pulseManager.run(toCounterPulseAll()) + if (ge != null) { + bot.pulseManager.run(toCounterPulseAll()) + } + } + + /** + * Function to bank all items that are not excluded at a nearby bank. + * @author Kermit & Ceikry + */ + fun depositAtBank(){ + val bank: Scenery? = getNearestNode("Bank booth", true) as Scenery? + class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) { + override fun pulse(): Boolean { + bot.faceLocation(bank?.location) + for (item in bot.inventory.toArray()) { + item ?: continue + when (item.id) { + Items.RUNE_AXE_1359, Items.TINDERBOX_590, Items.ADAMANT_PICKAXE_1271, Items.COINS_995 -> continue + } + bot.bank.add(item) + bot.inventory.remove(item) + } +// log(this::class.java, Log.FINE, "${bot.username} Just finished banking at ${bot.location} || Bank contents: ${bot.bank}") + return true + } + } + if (bank != null) { + bot.pulseManager.run(BankingPulse()) + } } /** diff --git a/Server/src/main/core/game/world/ImmerseWorld.kt b/Server/src/main/core/game/world/ImmerseWorld.kt index 2efed45a8..2adee483f 100644 --- a/Server/src/main/core/game/world/ImmerseWorld.kt +++ b/Server/src/main/core/game/world/ImmerseWorld.kt @@ -11,6 +11,7 @@ import core.game.bots.SkillingBotAssembler import java.util.Timer import java.util.concurrent.Executors import kotlin.concurrent.schedule +import kotlin.random.Random class ImmerseWorld : StartupListener { @@ -24,6 +25,12 @@ class ImmerseWorld : StartupListener { var assembler = CombatBotAssembler() var skillingBotAssembler = SkillingBotAssembler() + private fun randomizeLocationInRanges(location: Location, xMin: Int, xMax: Int, yMin: Int, yMax: Int): Location { + val newX = location.x + Random.nextInt(xMin, xMax) + val newY = location.y + Random.nextInt(yMin, yMax) + return Location(newX, newY, 0) + } + fun spawnBots() { if(GameWorld.settings!!.enable_bots) @@ -43,10 +50,10 @@ class ImmerseWorld : StartupListener { } } - fun immerseAdventurer() { - for (i in 0..(GameWorld.settings?.max_adv_bots ?: 50)) { - var random: Long = (10000..300000).random().toLong() - Timer().schedule(random) { + fun immerseAdventurer(){ + for (i in 0..(GameWorld.settings?.max_adv_bots ?: 50)){ + var random = Random.nextInt(20000, 400000).toLong() + Timer().schedule(random){ spawn_adventurers() } } @@ -55,14 +62,17 @@ class ImmerseWorld : StartupListener { fun spawn_adventurers() { val lumbridge = Location.create(3221, 3219, 0) val tiers = listOf(CombatBotAssembler.Tier.LOW, CombatBotAssembler.Tier.MED) - GeneralBotCreator( - Adventurer(CombatStyle.MELEE), - assembler.MeleeAdventurer(tiers.random(), lumbridge) - ) - GeneralBotCreator( - Adventurer(CombatStyle.RANGE), - assembler.RangeAdventurer(tiers.random(), lumbridge) - ) + if (Random.nextBoolean()) { + GeneralBotCreator( + Adventurer(CombatStyle.MELEE), + assembler.MeleeAdventurer(tiers.random(), randomizeLocationInRanges(lumbridge,-1,1,-1,1)) + ) + } else { + GeneralBotCreator( + Adventurer(CombatStyle.RANGE), + assembler.RangeAdventurer(tiers.random(), randomizeLocationInRanges(lumbridge,-1,1,-1,1)) + ) + } } fun immerseFishingGuild() { From 2b460b64f2c219a01f7e9eef6c93af96a2aad09d Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 10 Oct 2024 07:14:48 +0000 Subject: [PATCH 035/306] Thread now correctly disappears every 5 items crafted, including bug fixes related to the fact Ring of forging now correctly disappears every 140 iron ores smelt, including bug fixes related to the fact --- .../crafting/armour/DragonCraftPulse.java | 3 - .../skill/crafting/armour/HardCraftPulse.java | 3 - .../crafting/armour/LeatherCrafting.java | 55 ++++--------------- .../skill/crafting/armour/SnakeSkinPulse.java | 3 - .../skill/crafting/armour/SoftCraftPulse.java | 4 -- .../smithing/smelting/SmeltingPulse.java | 29 ++++------ .../neitiznot/handlers/YakArmourPlugin.java | 3 - 7 files changed, 24 insertions(+), 76 deletions(-) diff --git a/Server/src/main/content/global/skill/crafting/armour/DragonCraftPulse.java b/Server/src/main/content/global/skill/crafting/armour/DragonCraftPulse.java index bc8022884..924d1364a 100644 --- a/Server/src/main/content/global/skill/crafting/armour/DragonCraftPulse.java +++ b/Server/src/main/content/global/skill/crafting/armour/DragonCraftPulse.java @@ -95,9 +95,6 @@ public final class DragonCraftPulse extends SkillPulse { player.getInventory().add(item); player.getSkills().addExperience(Skills.CRAFTING, hide.getExperience(), true); LeatherCrafting.decayThread(player); - if (LeatherCrafting.isLastThread(player)) { - LeatherCrafting.removeThread(player); - } amount--; } return amount < 1; diff --git a/Server/src/main/content/global/skill/crafting/armour/HardCraftPulse.java b/Server/src/main/content/global/skill/crafting/armour/HardCraftPulse.java index 4d02be91c..5a2207b4a 100644 --- a/Server/src/main/content/global/skill/crafting/armour/HardCraftPulse.java +++ b/Server/src/main/content/global/skill/crafting/armour/HardCraftPulse.java @@ -75,9 +75,6 @@ public final class HardCraftPulse extends SkillPulse { player.getInventory().add(item); player.getSkills().addExperience(Skills.CRAFTING, 35, true); LeatherCrafting.decayThread(player); - if (LeatherCrafting.isLastThread(player)) { - LeatherCrafting.removeThread(player); - } } amount--; return amount < 1; diff --git a/Server/src/main/content/global/skill/crafting/armour/LeatherCrafting.java b/Server/src/main/content/global/skill/crafting/armour/LeatherCrafting.java index 2767fbc65..02f14d1ee 100644 --- a/Server/src/main/content/global/skill/crafting/armour/LeatherCrafting.java +++ b/Server/src/main/content/global/skill/crafting/armour/LeatherCrafting.java @@ -1,8 +1,12 @@ package content.global.skill.crafting.armour; +import core.api.Container; import core.game.component.Component; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import org.rs09.consts.Items; + +import static core.api.ContentAPIKt.*; /** * Represents a useful class for leather crafting related information. @@ -40,52 +44,17 @@ public final class LeatherCrafting { */ private static final Component COMPONENT = new Component(154); - /** - * Checks if its the last thrad. - * @return {@code True} if so. - */ - public static boolean isLastThread(final Player player) { - final Item thread = getThread(player); - if (thread == null) { - return false; - } - int charge = thread.getCharge(); - return charge >= 1004; - } - /** * Method used to decay thread. - */ - public static void decayThread(final Player player) { - final Item thread = getThread(player); - if (thread == null) { - return; - } - int charge = thread.getCharge(); - thread.setCharge(charge + 1); - } - - /** - * Method used to remove thread. - * @param player the player. - */ - public static void removeThread(final Player player) { - if (player.getInventory().remove(THREAD)) { - player.getPacketDispatch().sendMessage("You use a reel of your thread."); - Item thread = getThread(player); - if (thread != null) { - thread.setCharge(1000); - } - } - } - - /** - * Gets the thread. - * @param player the player. - * @return the item. + * @author Player Name */ - public static Item getThread(final Player player) { - return player.getInventory().get(player.getInventory().getSlot(THREAD)); + public static void decayThread(final Player player) { + int charges = getAttribute(player, "threadCharges", 5) - 1; + if (charges <= 0 && removeItem(player, Items.THREAD_1734, Container.INVENTORY)) { + charges = 5; + sendMessage(player, "You use a reel of your thread."); + } + setAttribute(player, "/save:threadCharges", charges); } /** diff --git a/Server/src/main/content/global/skill/crafting/armour/SnakeSkinPulse.java b/Server/src/main/content/global/skill/crafting/armour/SnakeSkinPulse.java index a851caaf6..be012d01c 100644 --- a/Server/src/main/content/global/skill/crafting/armour/SnakeSkinPulse.java +++ b/Server/src/main/content/global/skill/crafting/armour/SnakeSkinPulse.java @@ -82,9 +82,6 @@ public final class SnakeSkinPulse extends SkillPulse { player.getInventory().add(item); player.getSkills().addExperience(Skills.CRAFTING, skin.getExperience(), true); LeatherCrafting.decayThread(player); - if (LeatherCrafting.isLastThread(player)) { - LeatherCrafting.removeThread(player); - } } amount--; return amount < 1; diff --git a/Server/src/main/content/global/skill/crafting/armour/SoftCraftPulse.java b/Server/src/main/content/global/skill/crafting/armour/SoftCraftPulse.java index 2d62c165a..ab49815cf 100644 --- a/Server/src/main/content/global/skill/crafting/armour/SoftCraftPulse.java +++ b/Server/src/main/content/global/skill/crafting/armour/SoftCraftPulse.java @@ -90,10 +90,6 @@ public final class SoftCraftPulse extends SkillPulse { player.getInventory().add(item); player.getSkills().addExperience(Skills.CRAFTING, soft.getExperience(), true); LeatherCrafting.decayThread(player); - if (LeatherCrafting.isLastThread(player)) { - LeatherCrafting.removeThread(player); - } - if (soft == LeatherCrafting.SoftLeather.GLOVES) { player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 1, 3); } diff --git a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java index e48e85508..7ceb2143c 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java +++ b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java @@ -1,9 +1,12 @@ package content.global.skill.smithing.smelting; import static core.api.ContentAPIKt.*; + +import core.api.Container; import core.api.EquipmentSlot; import core.game.event.ResourceProducedEvent; import core.game.container.impl.EquipmentContainer; +import core.tools.Log; import org.rs09.consts.Items; import core.game.world.map.Location; import core.game.node.entity.skill.SkillPulse; @@ -174,16 +177,6 @@ public class SmeltingPulse extends SkillPulse { return amount < 1; } - /** - * Checks if the player has a ring of forging. - * - * @param player the player. - * @return {@code True} if so. - */ - public boolean hasForgingRing(Player player) { - return player.getEquipment().containsItem(RING_OF_FORGING); - } - /** * Checks if the forging is a succes. * @@ -192,16 +185,18 @@ public class SmeltingPulse extends SkillPulse { */ public boolean success(Player player) { if (bar == Bar.IRON && !superHeat) { - if (hasForgingRing(player)) { - Item ring = getItemFromEquipment(player, EquipmentSlot.RING); - if(ring != null){ - if(getCharge(ring) == 1000) setCharge(ring, 140); - adjustCharge(ring, -1); - if(getCharge(ring) == 0){ - player.getEquipment().remove(ring); + if (inEquipment(player, Items.RING_OF_FORGING_2568, 1)) { + int charges = getAttribute(player, "ringOfForgingCharges", 140) - 1; + if (charges <= 0) { + if (removeItem(player, Items.RING_OF_FORGING_2568, Container.EQUIPMENT)) { + charges = 140; sendMessage(player, "Your ring of forging uses up its last charge and disintegrates."); + } else { + log(this.getClass(), Log.ERR, "Failed to delete empty ring of forging for player " + player.getName()); + return false; //unfair but prevents exploit if the impossible happens } } + setAttribute(player, "/save:ringOfForgingCharges", charges); return true; } else { return RandomFunction.nextBool(); diff --git a/Server/src/main/content/region/fremennik/neitiznot/handlers/YakArmourPlugin.java b/Server/src/main/content/region/fremennik/neitiznot/handlers/YakArmourPlugin.java index e746965b7..135470838 100644 --- a/Server/src/main/content/region/fremennik/neitiznot/handlers/YakArmourPlugin.java +++ b/Server/src/main/content/region/fremennik/neitiznot/handlers/YakArmourPlugin.java @@ -135,9 +135,6 @@ public class YakArmourPlugin extends UseWithHandler { player.getInventory().add(node); player.getSkills().addExperience(Skills.CRAFTING, 32, true); LeatherCrafting.decayThread(player); - if (LeatherCrafting.isLastThread(player)) { - LeatherCrafting.removeThread(player); - } player.sendMessage("You make " + node.getName().toLowerCase() + "."); } amount--; From 393752d77b1d0011257da1202f455492f7b1d9d7 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Fri, 11 Oct 2024 04:52:08 +0000 Subject: [PATCH 036/306] Fixed vinesweeper point exchange ratio bug Disabled spirit kalphite scroll until bug is fixed --- .../summoning/familiar/SpiritKalphiteNPC.java | 49 ++++++++++--------- .../minigame/vinesweeper/Vinesweeper.kt | 33 +++++++------ 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritKalphiteNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritKalphiteNPC.java index 3768df594..09a83505c 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritKalphiteNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritKalphiteNPC.java @@ -44,30 +44,31 @@ public class SpiritKalphiteNPC extends BurdenBeast { @Override protected boolean specialMove(FamiliarSpecial special) { - if (!isOwnerAttackable()) { - return false; - } - final List entitys = RegionManager.getLocalEntitys(owner, 6); - visualize(Animation.create(8517), Graphics.create(1350)); - GameWorld.getPulser().submit(new Pulse(1, owner) { - @Override - public boolean pulse() { - int count = 0; - for (Entity entity : entitys) { - if (count > 5) { - return true; - } - if (!canCombatSpecial(entity)) { - continue; - } - Projectile.magic(SpiritKalphiteNPC.this, entity, 1349, 40, 36, 50, 5).send(); - sendFamiliarHit(entity, 20); - count++; - } - return true; - } - }); - return false; + return false; ///bodge this for now, until someone fixes this abomination. +// if (!isOwnerAttackable()) { +// return false; +// } +// final List entitys = RegionManager.getLocalEntitys(owner, 6); +// visualize(Animation.create(8517), Graphics.create(1350)); +// GameWorld.getPulser().submit(new Pulse(1, owner) { +// @Override +// public boolean pulse() { +// int count = 0; +// for (Entity entity : entitys) { +// if (count > 5) { +// return true; +// } +// if (!canCombatSpecial(entity)) { +// continue; +// } +// Projectile.magic(SpiritKalphiteNPC.this, entity, 1349, 40, 36, 50, 5).send(); +// sendFamiliarHit(entity, 20); +// count++; +// } +// return true; +// } +// }); +// return false; } @Override diff --git a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt index cce206947..9fe119605 100644 --- a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt +++ b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt @@ -3,8 +3,21 @@ package content.minigame.vinesweeper import BlinkinDialogue import FarmerDialogue.Companion.FARMER_FLAG_LINES import WinkinDialogue +import content.minigame.vinesweeper.Vinesweeper.Companion.FARMERS +import content.minigame.vinesweeper.Vinesweeper.Companion.FARMER_CLEAR_RADIUS +import content.minigame.vinesweeper.Vinesweeper.Companion.HOLES +import content.minigame.vinesweeper.Vinesweeper.Companion.NUMBERS +import content.minigame.vinesweeper.Vinesweeper.Companion.RABBITS +import content.minigame.vinesweeper.Vinesweeper.Companion.SEED_LOCS +import content.minigame.vinesweeper.Vinesweeper.Companion.populateSeeds +import content.minigame.vinesweeper.Vinesweeper.Companion.scheduleNPCs +import content.minigame.vinesweeper.Vinesweeper.Companion.sendPoints import core.api.* +import core.cache.def.impl.ItemDefinition import core.game.component.Component +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.InterfaceListener import core.game.interaction.MovementPulse import core.game.node.entity.Entity import core.game.node.entity.combat.DeathTask @@ -18,6 +31,8 @@ import core.game.node.item.Item import core.game.node.scenery.Scenery import core.game.node.scenery.SceneryBuilder import core.game.system.task.Pulse +import core.game.world.GameWorld +import core.game.world.GameWorld.ticks import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.zone.ZoneBorders @@ -25,22 +40,8 @@ import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Graphics import core.plugin.Initializable import core.tools.RandomFunction -import content.minigame.vinesweeper.Vinesweeper.Companion.FARMERS -import content.minigame.vinesweeper.Vinesweeper.Companion.FARMER_CLEAR_RADIUS -import content.minigame.vinesweeper.Vinesweeper.Companion.HOLES -import content.minigame.vinesweeper.Vinesweeper.Companion.NUMBERS -import content.minigame.vinesweeper.Vinesweeper.Companion.RABBITS -import content.minigame.vinesweeper.Vinesweeper.Companion.SEED_LOCS -import content.minigame.vinesweeper.Vinesweeper.Companion.populateSeeds -import content.minigame.vinesweeper.Vinesweeper.Companion.scheduleNPCs -import content.minigame.vinesweeper.Vinesweeper.Companion.sendPoints -import core.cache.def.impl.ItemDefinition -import core.game.interaction.InteractionListener -import core.game.interaction.IntType -import core.game.interaction.InterfaceListener -import core.game.world.GameWorld -import core.game.world.GameWorld.ticks import org.rs09.consts.* +import kotlin.math.max import kotlin.math.min import org.rs09.consts.Graphics as Gfx import org.rs09.consts.Scenery as Sceneries @@ -217,7 +218,7 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { player.packetDispatch.sendInterfaceConfig(686, 60, true) val level = player.skills.getStaticLevel(Skills.FARMING) // TODO: more precise formula - val points_per_xp = if (level < 40) { 2.0*(40.0 - level.toDouble())/10.0 } else { 1.0 } + val points_per_xp = if (level < 40) { max(1.0, 2.0*(40.0 - level.toDouble())/10.0) } else { 1.0 } val points = player.getAttribute("vinesweeper:points", 0) val xp = points / points_per_xp player.skills.addExperience(Skills.FARMING, xp) From 32cd17bfa2cd82a7572acc9e11235693a681e4c2 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 12 Oct 2024 04:21:49 +0000 Subject: [PATCH 037/306] Fixed bugs relating to player location and random events Improved handling of random events when the location of the abducted player is missing from save file Added per-tick auditing of data relating to player location --- .../events/drilldemon/DrillDemonListeners.kt | 4 +-- .../ame/events/drilldemon/DrillDemonUtils.kt | 4 ++- .../ame/events/evilbob/EvilBobListeners.kt | 5 +-- .../global/ame/events/evilbob/EvilBobUtils.kt | 3 +- .../events/freakyforester/FreakListeners.kt | 4 +-- .../ame/events/freakyforester/FreakUtils.kt | 3 +- .../supriseexam/SupriseExamListeners.kt | 31 ++++++++++++------- .../events/supriseexam/SurpriseExamUtils.kt | 12 +++---- .../core/game/node/entity/player/Player.java | 17 ++++++++-- .../game/world/map/zone/ZoneRestriction.java | 12 +++++-- 10 files changed, 63 insertions(+), 32 deletions(-) diff --git a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonListeners.kt b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonListeners.kt index cb270f02f..2287de37d 100644 --- a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonListeners.kt +++ b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonListeners.kt @@ -79,7 +79,7 @@ class DrillDemonListeners : InteractionListener, MapArea { } override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS) + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP) } override fun areaEnter(entity: Entity) { @@ -90,4 +90,4 @@ class DrillDemonListeners : InteractionListener, MapArea { setComponentVisibility(entity.asPlayer(), 746, 12, true) } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt index 105b14fc2..84cba68d6 100644 --- a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt +++ b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt @@ -1,5 +1,6 @@ package content.global.ame.events.drilldemon +import core.ServerConstants import core.api.* import core.game.interaction.QueueStrength import core.game.node.entity.player.Player @@ -67,7 +68,8 @@ object DrillDemonUtils { fun cleanup(player: Player) { player.locks.unlockTeleport() unlock(player) - teleport(player, getAttribute(player, DD_KEY_RETURN_LOC, Location.create(3222, 3218, 0))) + val destination = getAttribute(player, DD_KEY_RETURN_LOC, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) + teleport(player, destination) removeAttribute(player, DD_KEY_RETURN_LOC) removeAttribute(player, DD_KEY_TASK) removeAttribute(player, DD_CORRECT_OFFSET) diff --git a/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt b/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt index fc71ebd68..b40c42bf6 100644 --- a/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt +++ b/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt @@ -121,7 +121,8 @@ class EvilBobListeners : InteractionListener, MapArea { } 3 -> { sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.") - teleport(player, getAttribute(player, EvilBobUtils.prevLocation, Location.create(3222, 3219, 0))) + val destination = getAttribute(player, EvilBobUtils.prevLocation, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) + teleport(player, destination) EvilBobUtils.reward(player) EvilBobUtils.cleanup(player) resetAnimator(player) @@ -139,7 +140,7 @@ class EvilBobListeners : InteractionListener, MapArea { } override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS) + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP) } override fun areaEnter(entity: Entity) { diff --git a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt index a74835f33..55ef8c2db 100644 --- a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt +++ b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt @@ -1,5 +1,6 @@ package content.global.ame.events.evilbob +import core.ServerConstants import core.api.* import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills @@ -60,7 +61,7 @@ object EvilBobUtils { fun cleanup(player: Player) { player.locks.unlockTeleport() - player.properties.teleportLocation = getAttribute(player, prevLocation, null) + player.properties.teleportLocation = getAttribute(player, prevLocation, ServerConstants.HOME_LOCATION) removeAttributes(player, assignedFishingZone, eventComplete, prevLocation, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen) removeAll(player, Items.FISHLIKE_THING_6202) removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK) diff --git a/Server/src/main/content/global/ame/events/freakyforester/FreakListeners.kt b/Server/src/main/content/global/ame/events/freakyforester/FreakListeners.kt index e2d36acc0..8754a8d08 100644 --- a/Server/src/main/content/global/ame/events/freakyforester/FreakListeners.kt +++ b/Server/src/main/content/global/ame/events/freakyforester/FreakListeners.kt @@ -57,10 +57,10 @@ class FreakListeners : InteractionListener, MapArea { } override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS) + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP) } override fun areaEnter(entity: Entity) { entity.locks.lockTeleport(1000000) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt index c49d155d7..e777e3c05 100644 --- a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt +++ b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt @@ -1,5 +1,6 @@ package content.global.ame.events.freakyforester +import core.ServerConstants import core.api.* import org.rs09.consts.Items import org.rs09.consts.NPCs @@ -35,7 +36,7 @@ object FreakUtils{ fun cleanup(player: Player) { player.locks.unlockTeleport() - player.properties.teleportLocation = getAttribute(player,freakPreviousLoc,null) + player.properties.teleportLocation = getAttribute(player,freakPreviousLoc, ServerConstants.HOME_LOCATION) removeAttributes(player, freakPreviousLoc, freakTask, freakComplete, pheasantKilled) removeAll(player, Items.RAW_PHEASANT_6178) removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK) diff --git a/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt b/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt index 6629982fa..55d61ca09 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt +++ b/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt @@ -9,16 +9,17 @@ import org.rs09.consts.NPCs import core.game.interaction.InteractionListener import core.game.interaction.IntType import content.global.handlers.iface.ExperienceInterface +import core.api.MapArea +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction -class SupriseExamListeners : InteractionListener { - val MORDAUT = NPCs.MR_MORDAUT_6117 - val BOOK_OF_KNOWLEDGE = Items.BOOK_OF_KNOWLEDGE_11640 +class SupriseExamListeners : InteractionListener, MapArea { override fun defineListeners() { - on(MORDAUT, IntType.NPC, "talk-to"){ player, node -> + on(NPCs.MR_MORDAUT_6117, IntType.NPC, "talk-to") { player, node -> player.faceLocation(Location.create(1886, 5024, 0)) - val examComplete = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT,0) == 3 - player.dialogueInterpreter.open(MordautDialogue(examComplete),node.asNpc()) + val examComplete = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT, 0) == 3 + player.dialogueInterpreter.open(MordautDialogue(examComplete), node.asNpc()) return@on true } @@ -39,9 +40,9 @@ class SupriseExamListeners : InteractionListener { return@on true } - on(BOOK_OF_KNOWLEDGE, IntType.ITEM, "read"){ player, _ -> - player.setAttribute("caller"){skill: Int,p: Player -> - if(p.inventory.remove(Item(BOOK_OF_KNOWLEDGE))) { + on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ -> + player.setAttribute("caller") { skill: Int, p: Player -> + if (p.inventory.remove(Item(Items.BOOK_OF_KNOWLEDGE_11640))) { val level = p.skills.getStaticLevel(skill) val experience = level * 15.0 p.skills.addExperience(skill, experience) @@ -54,8 +55,16 @@ class SupriseExamListeners : InteractionListener { } override fun defineDestinationOverrides() { - setDest(IntType.NPC,MORDAUT){ _, _ -> + setDest(IntType.NPC, NPCs.MR_MORDAUT_6117) { _, _ -> return@setDest Location.create(1886, 5025, 0) } } -} \ No newline at end of file + + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders.forRegion(7502)) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.OFF_MAP) + } +} diff --git a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt b/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt index f3b5f10b9..aa7797b59 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt +++ b/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt @@ -1,5 +1,6 @@ package content.global.ame.events.supriseexam +import core.Server import core.api.* import core.game.node.entity.impl.PulseType import core.game.node.entity.player.Player @@ -40,17 +41,12 @@ object SurpriseExamUtils { } fun cleanup(player: Player){ - player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC,null) + player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC, ServerConstants.HOME_LOCATION) clearLogoutListener(player, SE_LOGOUT_KEY) - player.removeAttribute(SE_KEY_LOC) - player.removeAttribute(SE_KEY_INDEX) - player.removeAttribute(SE_KEY_CORRECT) + removeAttributes(player, SE_KEY_LOC, SE_KEY_INDEX, SE_KEY_CORRECT) player.pulseManager.run(object : Pulse(2){ override fun pulse(): Boolean { - val reward = Item(Items.BOOK_OF_KNOWLEDGE_11640) - if(!player.inventory.add(reward)){ - GroundItemManager.create(reward,player) - } + addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640) return true } }, PulseType.CUSTOM_1) diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 361fa58c8..a23d472c7 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -2,6 +2,7 @@ package core.game.node.entity.player; import content.global.handlers.item.equipment.special.SalamanderSwingHandler; import content.global.skill.runecrafting.PouchManager; +import core.api.ContentAPIKt; import core.api.EquipmentSlot; import core.game.component.Component; import core.game.container.Container; @@ -44,6 +45,7 @@ import core.game.system.task.Pulse; import core.game.world.map.*; import core.game.world.map.build.DynamicRegion; import core.game.world.map.path.Pathfinder; +import core.game.world.map.zone.ZoneRestriction; import core.game.world.map.zone.ZoneType; import core.game.world.update.flag.PlayerFlags; import core.game.world.update.flag.*; @@ -475,11 +477,22 @@ public class Player extends Entity { settings.setSpecialEnergy(100); } - //Decrements prayer points + // Decrement prayer points getPrayer().tick(); - //update wealth tracking + // Update wealth tracking checkForWealthUpdate(false); + + // Check if the player is on the map + // This is only a sanity check to detect improper usage of the 'original-loc' attribute, hence only do this work if the attribute is set + if (ContentAPIKt.getAttribute(this, "/save:original-loc", null) != null) { + int rid = location.getRegionId(); + Region r = RegionManager.forId(rid); + if (!(r instanceof DynamicRegion) && !getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) { + log(this.getClass(), Log.ERR, "Player " + getUsername() + " has the original-loc attribute set but isn't actually off-map! This indicates a bug in the code that set that attribute. The original-loc is: " + getAttribute("/save:original-loc") + ", good luck debugging!"); + ContentAPIKt.removeAttribute(this, "original-loc"); + } + } } private void checkForWealthUpdate(boolean force) { diff --git a/Server/src/main/core/game/world/map/zone/ZoneRestriction.java b/Server/src/main/core/game/world/map/zone/ZoneRestriction.java index f73b50014..64dd971db 100644 --- a/Server/src/main/core/game/world/map/zone/ZoneRestriction.java +++ b/Server/src/main/core/game/world/map/zone/ZoneRestriction.java @@ -31,7 +31,7 @@ public enum ZoneRestriction { */ CANNON, /** - * Do not spawn a grave if a player dies here + * Do not spawn a grave if a player dies here. */ GRAVES, @@ -39,6 +39,14 @@ public enum ZoneRestriction { * No teleporting allowed. */ TELEPORT, + + /** + * This region is not a part of the normal overworld or cave system. + * Used for temporary areas that use the 'original-loc' attribute to teleport the player back when they are done in the area. + * Example: non-dynamic/non-instanced random-event areas (e.g. Damien's bootcamp) + * Dynamic regions are implicitly off-map and do not require this attribute. + */ + OFF_MAP, ; /** @@ -48,4 +56,4 @@ public enum ZoneRestriction { public int getFlag() { return 1 << ordinal(); } -} \ No newline at end of file +} From 876b87b72a05796bd0ec499fb222d1549d97a2d1 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 12 Oct 2024 05:34:12 +0000 Subject: [PATCH 038/306] Fixed exception occuring when JohnnyBeard dies --- .../varrock/quest/shieldofarrav/JohnnyBeardNPC.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java index 9208ad74b..da7ef94ba 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java @@ -43,10 +43,12 @@ public final class JohnnyBeardNPC extends AbstractNPC { @Override public void finalizeDeath(final Entity killer) { super.finalizeDeath(killer); - final Player p = ((Player) killer); - final Quest quest = p.getQuestRepository().getQuest("Shield of Arrav"); - if (quest.getStage(p) == 60 && ShieldofArrav.isPhoenixMission(p) && !p.getInventory().containsItem(ShieldofArrav.INTEL_REPORT) && !p.getBank().containsItem(ShieldofArrav.INTEL_REPORT)) { - GroundItemManager.create(ShieldofArrav.INTEL_REPORT, getLocation(), p); + if (killer instanceof Player) { + final Player p = ((Player) killer); + final Quest quest = p.getQuestRepository().getQuest("Shield of Arrav"); + if (quest.getStage(p) == 60 && ShieldofArrav.isPhoenixMission(p) && !p.getInventory().containsItem(ShieldofArrav.INTEL_REPORT) && !p.getBank().containsItem(ShieldofArrav.INTEL_REPORT)) { + GroundItemManager.create(ShieldofArrav.INTEL_REPORT, getLocation(), p); + } } } From 661aa22e417b8376e9b9d62a4b33d0b248a1a6a2 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:16:48 -0600 Subject: [PATCH 039/306] Disable Random events --- Server/src/main/core/game/system/timer/impl/AntiMacro.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt index 4f9ba872a..ab3c18394 100644 --- a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt +++ b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt @@ -16,7 +16,7 @@ import core.tools.colorize import org.json.simple.JSONObject class AntiMacro : PersistTimer(0, "antimacro", isAuto = true), Commands { - var paused = false + var paused = true var nextRandom: RandomEvents? = null override fun run(entity: Entity): Boolean { From af47ae42c17a795c73b0c12bf3f71bd4901c51d6 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:22:13 -0600 Subject: [PATCH 040/306] Disabled logout timer --- Server/src/main/core/net/packet/PacketProcessor.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/net/packet/PacketProcessor.kt b/Server/src/main/core/net/packet/PacketProcessor.kt index ca967213c..51e4324e9 100644 --- a/Server/src/main/core/net/packet/PacketProcessor.kt +++ b/Server/src/main/core/net/packet/PacketProcessor.kt @@ -307,8 +307,8 @@ object PacketProcessor { pkt.player.interfaceManager.switchWindowMode(pkt.windowMode) } is Packet.TrackingAfkTimeout -> { - if (pkt.player.details.rights != Rights.ADMINISTRATOR) - pkt.player.packetDispatch.sendLogout() + //if (pkt.player.details.rights != Rights.ADMINISTRATOR) + //pkt.player.packetDispatch.sendLogout() } is Packet.TrackingCameraPos -> { //TODO Refactor the player monitor to be actually useful and log this From ab78bce7699097c75707e4976664745094e7959e Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:24:20 -0600 Subject: [PATCH 041/306] Extend grave timers --- .../node/entity/combat/graves/GraveType.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt b/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt index 7d4f7bc5b..f36c3ad1d 100644 --- a/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt +++ b/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt @@ -3,19 +3,19 @@ package core.game.node.entity.combat.graves import org.rs09.consts.NPCs enum class GraveType(val npcId: Int, val cost: Int, val durationMinutes: Int, val isMembers: Boolean, val requiredQuest: String = "", val text: String) { - MEM_PLAQUE(NPCs.GRAVE_MARKER_6565, 0, 2, false, text = "In memory of @name,
who died here."), - FLAG(NPCs.GRAVE_MARKER_6568, 50, 2, false, text = MEM_PLAQUE.text), - SMALL_GS(NPCs.GRAVESTONE_6571, 500, 2, false, text = "In loving memory of our dear friend @name,
who died in this place @mins ago."), - ORNATE_GS(NPCs.GRAVESTONE_6574, 5000, 3, false, text = SMALL_GS.text), - FONT_OF_LIFE(NPCs.GRAVESTONE_6577, 50000, 4, true, text = "In your travels,
pause awhile to remember @name,
who passed away at this spot."), - STELE(NPCs.STELE_6580, 50000, 4, true, text = FONT_OF_LIFE.text), - SARA_SYMBOL(NPCs.SARADOMIN_SYMBOL_6583, 50000, 4, true, text = "@name,
an enlightened servant of Saradomin,
perished in this place."), - ZAM_SYMBOL(NPCs.ZAMORAK_SYMBOL_6586, 50000, 4, true, text = "@name,
a most bloodthirsty follower of Zamorak,
perished in this place."), - GUTH_SYMBOL(NPCs.GUTHIX_SYMBOL_6589, 50000, 4, true, text = "@name,
who walked with the Balance of Guthix,
perished in this place."), - BAND_SYMBOL(NPCs.BANDOS_SYMBOL_6592, 50000, 4, true, requiredQuest = "Land of the Goblins", text = "@name,
a vicious warrior dedicated to Bandos,
perished in this place. "), - ARMA_SYMBOL(NPCs.ARMADYL_SYMBOL_6595, 50000, 4, true, requiredQuest = "Temple of Ikov", text = "@name,
a follower of the Law of Armadyl,
perished in this place."), - ZARO_SYMBOL(NPCs.MEMORIAL_STONE_6598, 50000, 4, true, requiredQuest = "Desert Treasure", text = "@name,
servant of the Unknown Power,
perished in this place."), - ANGEL_DEATH(NPCs.MEMORIAL_STONE_6601, 500000, 5, true, text = "Ye frail mortals who gaze upon this sight,
forget not the fate of @name, once mighty, now
surrendered to the inescapable grasp of destiny.
Requiescat in pace."); + MEM_PLAQUE(NPCs.GRAVE_MARKER_6565, 0, 5, false, text = "In memory of @name,
who died here."), + FLAG(NPCs.GRAVE_MARKER_6568, 50, 10, false, text = MEM_PLAQUE.text), + SMALL_GS(NPCs.GRAVESTONE_6571, 500, 15, false, text = "In loving memory of our dear friend @name,
who died in this place @mins ago."), + ORNATE_GS(NPCs.GRAVESTONE_6574, 5000, 30, false, text = SMALL_GS.text), + FONT_OF_LIFE(NPCs.GRAVESTONE_6577, 50000, 45, true, text = "In your travels,
pause awhile to remember @name,
who passed away at this spot."), + STELE(NPCs.STELE_6580, 50000, 45, true, text = FONT_OF_LIFE.text), + SARA_SYMBOL(NPCs.SARADOMIN_SYMBOL_6583, 50000, 45, true, text = "@name,
an enlightened servant of Saradomin,
perished in this place."), + ZAM_SYMBOL(NPCs.ZAMORAK_SYMBOL_6586, 50000, 45, true, text = "@name,
a most bloodthirsty follower of Zamorak,
perished in this place."), + GUTH_SYMBOL(NPCs.GUTHIX_SYMBOL_6589, 50000, 45, true, text = "@name,
who walked with the Balance of Guthix,
perished in this place."), + BAND_SYMBOL(NPCs.BANDOS_SYMBOL_6592, 50000, 45, true, requiredQuest = "Land of the Goblins", text = "@name,
a vicious warrior dedicated to Bandos,
perished in this place. "), + ARMA_SYMBOL(NPCs.ARMADYL_SYMBOL_6595, 50000, 45, true, requiredQuest = "Temple of Ikov", text = "@name,
a follower of the Law of Armadyl,
perished in this place."), + ZARO_SYMBOL(NPCs.MEMORIAL_STONE_6598, 50000, 45, true, requiredQuest = "Desert Treasure", text = "@name,
servant of the Unknown Power,
perished in this place."), + ANGEL_DEATH(NPCs.MEMORIAL_STONE_6601, 500000, 60, true, text = "Ye frail mortals who gaze upon this sight,
forget not the fate of @name, once mighty, now
surrendered to the inescapable grasp of destiny.
Requiescat in pace."); companion object { val ids = values().fold(ArrayList()) {list, type -> From ea980fe909a10906d00aa8e9f8cf3e4b83f3c450 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:41:11 -0600 Subject: [PATCH 042/306] Updating Smithing levels Each item's smithing level requirement has been lowered to match the level required to smith that bar. Adamant and Rune are lowered to 60 and 70 respectively. --- .../content/global/skill/smithing/Bars.java | 304 +++++++++--------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/Server/src/main/content/global/skill/smithing/Bars.java b/Server/src/main/content/global/skill/smithing/Bars.java index 7514693fe..0c8c36181 100644 --- a/Server/src/main/content/global/skill/smithing/Bars.java +++ b/Server/src/main/content/global/skill/smithing/Bars.java @@ -26,122 +26,122 @@ public enum Bars { /** * Bronze Mace */ - BRONZE_MACE(BarType.BRONZE, SmithingType.TYPE_MACE, 1422, 2), + BRONZE_MACE(BarType.BRONZE, SmithingType.TYPE_MACE, 1422, 1), /** * Bronze Medium helm */ - BRONZE_MED_HELM(BarType.BRONZE, SmithingType.TYPE_MEDIUM_HELM, 1139, 3), + BRONZE_MED_HELM(BarType.BRONZE, SmithingType.TYPE_MEDIUM_HELM, 1139, 1), /** * Bronze Crossbow Bolt */ - BRONZE_CROSSBOW_BOLT(BarType.BRONZE, SmithingType.TYPE_CROSSBOW_BOLT, 9375, 3), + BRONZE_CROSSBOW_BOLT(BarType.BRONZE, SmithingType.TYPE_CROSSBOW_BOLT, 9375, 1), /** * Bronze Sword */ - BRONZE_SWORD(BarType.BRONZE, SmithingType.TYPE_SWORD, 1277, 4), + BRONZE_SWORD(BarType.BRONZE, SmithingType.TYPE_SWORD, 1277, 1), /** * Bronze Dart Tips */ - BRONZE_DART_TIPS(BarType.BRONZE, SmithingType.TYPE_DART_TIP, 819, 4), + BRONZE_DART_TIPS(BarType.BRONZE, SmithingType.TYPE_DART_TIP, 819, 1), /** * Bronze Nails */ - BRONZE_NAILS(BarType.BRONZE, SmithingType.TYPE_NAIL, 4819, 4), + BRONZE_NAILS(BarType.BRONZE, SmithingType.TYPE_NAIL, 4819, 1), /** * Bronze Wire */ - BRONZE_WIRE(BarType.BRONZE, SmithingType.TYPE_WIRE, 1794, 4), + BRONZE_WIRE(BarType.BRONZE, SmithingType.TYPE_WIRE, 1794, 1), /** * Bronze Arrow Tips */ - BRONZE_ARROW_TIPS(BarType.BRONZE, SmithingType.TYPE_ARROW_TIP, 39, 5), + BRONZE_ARROW_TIPS(BarType.BRONZE, SmithingType.TYPE_ARROW_TIP, 39, 1), /** * Bronze Scimitar */ - BRONZE_SCIMITAR(BarType.BRONZE, SmithingType.TYPE_SCIMITAR, 1321, 5), + BRONZE_SCIMITAR(BarType.BRONZE, SmithingType.TYPE_SCIMITAR, 1321, 1), /** * Bronze Crossbow Limbs */ - BRONZE_CROSSBOW_LIMBS(BarType.BRONZE, SmithingType.TYPE_CROSSBOW_LIMB, 9420, 6), + BRONZE_CROSSBOW_LIMBS(BarType.BRONZE, SmithingType.TYPE_CROSSBOW_LIMB, 9420, 1), /** * Bronze longsword */ - BRONZE_LONGSWORD(BarType.BRONZE, SmithingType.TYPE_LONGSWORD, 1291, 6), + BRONZE_LONGSWORD(BarType.BRONZE, SmithingType.TYPE_LONGSWORD, 1291, 1), /** * Bronze ThrowingKnife */ - BRONZE_THROWINGKNFIE(BarType.BRONZE, SmithingType.TYPE_THROWING_KNIFE, 864, 7), + BRONZE_THROWINGKNFIE(BarType.BRONZE, SmithingType.TYPE_THROWING_KNIFE, 864, 1), /** * Bronze Full helmet */ - BRONZE_FULL_HELM(BarType.BRONZE, SmithingType.TYPE_FULL_HELM, 1155, 7), + BRONZE_FULL_HELM(BarType.BRONZE, SmithingType.TYPE_FULL_HELM, 1155, 1), /** * Bronze Square Shield */ - BRONZE_SQUARE_SHIELD(BarType.BRONZE, SmithingType.TYPE_SQUARE_SHIELD, 1173, 8), + BRONZE_SQUARE_SHIELD(BarType.BRONZE, SmithingType.TYPE_SQUARE_SHIELD, 1173, 1), /** * Bronze Warhammer */ - BRONZE_WAR_HAMMER(BarType.BRONZE, SmithingType.TYPE_WARHAMMER, 1337, 9), + BRONZE_WAR_HAMMER(BarType.BRONZE, SmithingType.TYPE_WARHAMMER, 1337, 1), /** * Bronze BattleAxe */ - BRONZE_BATTLEAXE(BarType.BRONZE, SmithingType.TYPE_BATTLE_AXE, 1375, 10), + BRONZE_BATTLEAXE(BarType.BRONZE, SmithingType.TYPE_BATTLE_AXE, 1375, 1), /** * Bronze ChainBody */ - BRONZE_CHAINBODY(BarType.BRONZE, SmithingType.TYPE_CHAINBODY, 1103, 11), + BRONZE_CHAINBODY(BarType.BRONZE, SmithingType.TYPE_CHAINBODY, 1103, 1), /** * Bronze KitShield */ - BRONZE_KITESHIELD(BarType.BRONZE, SmithingType.TYPE_KITE_SHIELD, 1189, 12), + BRONZE_KITESHIELD(BarType.BRONZE, SmithingType.TYPE_KITE_SHIELD, 1189, 1), /** * Bronze Claws */ - BRONZE_CLAWS(BarType.BRONZE, SmithingType.TYPE_CLAWS, 3095, 13), + BRONZE_CLAWS(BarType.BRONZE, SmithingType.TYPE_CLAWS, 3095, 1), /** * Bronze 2h */ - BRONZE_TWO_HANDED(BarType.BRONZE, SmithingType.TYPE_TWO_HAND_SWORD, 1307, 14), + BRONZE_TWO_HANDED(BarType.BRONZE, SmithingType.TYPE_TWO_HAND_SWORD, 1307, 1), /** * Bronze PlateSkirt */ - BRONZE_PLATE_SKIRT(BarType.BRONZE, SmithingType.TYPE_PLATE_SKIRT, 1087, 16), + BRONZE_PLATE_SKIRT(BarType.BRONZE, SmithingType.TYPE_PLATE_SKIRT, 1087, 1), /** * Bronze PlateLegs */ - BRONZE_PLATELEGS(BarType.BRONZE, SmithingType.TYPE_PLATELEG, 1075, 16), + BRONZE_PLATELEGS(BarType.BRONZE, SmithingType.TYPE_PLATELEG, 1075, 1), /** * Bronze PlateBody */ - BRONZE_PLATEBODY(BarType.BRONZE, SmithingType.TYPE_PLATEBODY, 1117, 18), + BRONZE_PLATEBODY(BarType.BRONZE, SmithingType.TYPE_PLATEBODY, 1117, 1), /** * Bronze Pickaxe */ - BRONZE_PICKAXE(BarType.BRONZE, SmithingType.TYPE_PICKAXE, 1265, 5), + BRONZE_PICKAXE(BarType.BRONZE, SmithingType.TYPE_PICKAXE, 1265, 1), /** * Iron Dagger @@ -151,131 +151,131 @@ public enum Bars { /** * Iron Hatchet */ - IRON_AXE(BarType.IRON, SmithingType.TYPE_AXE, 1349, 16), + IRON_AXE(BarType.IRON, SmithingType.TYPE_AXE, 1349, 15), /** * Iron Mace */ - IRON_MACE(BarType.IRON, SmithingType.TYPE_MACE, 1420, 17), + IRON_MACE(BarType.IRON, SmithingType.TYPE_MACE, 1420, 15), /** * Iron Med Helm */ - IRON_MED_HELM(BarType.IRON, SmithingType.TYPE_MEDIUM_HELM, 1137, 18), + IRON_MED_HELM(BarType.IRON, SmithingType.TYPE_MEDIUM_HELM, 1137, 15), /** * Iron Bolt */ - IRON_BOLT(BarType.IRON, SmithingType.TYPE_CROSSBOW_BOLT, 9377, 18), + IRON_BOLT(BarType.IRON, SmithingType.TYPE_CROSSBOW_BOLT, 9377, 15), /** * Iron Sword */ - IRON_SWORD(BarType.IRON, SmithingType.TYPE_SWORD, 1279, 19), + IRON_SWORD(BarType.IRON, SmithingType.TYPE_SWORD, 1279, 15), /** * Iron Dart Tips */ - IRON_DART_TIPS(BarType.IRON, SmithingType.TYPE_DART_TIP, 820, 19), + IRON_DART_TIPS(BarType.IRON, SmithingType.TYPE_DART_TIP, 820, 15), /** * Iron Nails */ - IRON_NAILS(BarType.IRON, SmithingType.TYPE_NAIL, 4820, 19), + IRON_NAILS(BarType.IRON, SmithingType.TYPE_NAIL, 4820, 15), /** * Iron Split */ - IRON_SPIT(BarType.IRON, SmithingType.TYPE_SPIT_IRON, 7225, 16), + IRON_SPIT(BarType.IRON, SmithingType.TYPE_SPIT_IRON, 7225, 15), /** * Iron Arrow Tips */ - IRON_ARROW_TIPS(BarType.IRON, SmithingType.TYPE_ARROW_TIP, 40, 20), + IRON_ARROW_TIPS(BarType.IRON, SmithingType.TYPE_ARROW_TIP, 40, 15), /** * Iron Scimitar */ - IRON_SCIMITAR(BarType.IRON, SmithingType.TYPE_SCIMITAR, 1323, 20), + IRON_SCIMITAR(BarType.IRON, SmithingType.TYPE_SCIMITAR, 1323, 15), /** * Iron Crossbow Limbs */ - IRON_CROSSBOW_LimbS(BarType.IRON, SmithingType.TYPE_CROSSBOW_LIMB, 9423, 23), + IRON_CROSSBOW_LimbS(BarType.IRON, SmithingType.TYPE_CROSSBOW_LIMB, 9423, 15), /** * Iron LongSword */ - IRON_LONGSWORD(BarType.IRON, SmithingType.TYPE_LONGSWORD, 1293, 21), + IRON_LONGSWORD(BarType.IRON, SmithingType.TYPE_LONGSWORD, 1293, 15), /** * Iron Knife */ - IRON_KNIFE(BarType.IRON, SmithingType.TYPE_THROWING_KNIFE, 863, 22), + IRON_KNIFE(BarType.IRON, SmithingType.TYPE_THROWING_KNIFE, 863, 15), /** * Iron Full Helm */ - IRON_FULL_HELM(BarType.IRON, SmithingType.TYPE_FULL_HELM, 1153, 22), + IRON_FULL_HELM(BarType.IRON, SmithingType.TYPE_FULL_HELM, 1153, 15), /** * Iron Square Shield */ - IRON_SQUARE_SHIELD(BarType.IRON, SmithingType.TYPE_SQUARE_SHIELD, 1175, 23), + IRON_SQUARE_SHIELD(BarType.IRON, SmithingType.TYPE_SQUARE_SHIELD, 1175, 15), /** * Oil Lantern Frame */ - OIL_LANTERN_FRAME(BarType.IRON, SmithingType.TYPE_OIL_LANTERN, 4540, 26), + OIL_LANTERN_FRAME(BarType.IRON, SmithingType.TYPE_OIL_LANTERN, 4540, 15), /** * Iron WarHammer */ - IRON_WARHAMMER(BarType.IRON, SmithingType.TYPE_WARHAMMER, 1335, 24), + IRON_WARHAMMER(BarType.IRON, SmithingType.TYPE_WARHAMMER, 1335, 15), /** * Iron Battleaxe */ - IRON_BATTLEAXE(BarType.IRON, SmithingType.TYPE_BATTLE_AXE, 1363, 25), + IRON_BATTLEAXE(BarType.IRON, SmithingType.TYPE_BATTLE_AXE, 1363, 15), /** * Iron ChainBody */ - IRON_CHAINBODY(BarType.IRON, SmithingType.TYPE_CHAINBODY, 1101, 26), + IRON_CHAINBODY(BarType.IRON, SmithingType.TYPE_CHAINBODY, 1101, 15), /** * Iron Kite Shield */ - IRON_KITE_SHIELD(BarType.IRON, SmithingType.TYPE_KITE_SHIELD, 1191, 27), + IRON_KITE_SHIELD(BarType.IRON, SmithingType.TYPE_KITE_SHIELD, 1191, 15), /** * Iron Claws */ - IRON_CLAWS(BarType.IRON, SmithingType.TYPE_CLAWS, 3096, 28), + IRON_CLAWS(BarType.IRON, SmithingType.TYPE_CLAWS, 3096, 15), /** * Iron 2H */ - IRON_TWO_HANDED_SWORD(BarType.IRON, SmithingType.TYPE_TWO_HAND_SWORD, 1309, 29), + IRON_TWO_HANDED_SWORD(BarType.IRON, SmithingType.TYPE_TWO_HAND_SWORD, 1309, 15), /** * Iron PlateSkirt */ - IRON_PLATESKIRT(BarType.IRON, SmithingType.TYPE_PLATE_SKIRT, 1081, 31), + IRON_PLATESKIRT(BarType.IRON, SmithingType.TYPE_PLATE_SKIRT, 1081, 15), /** * Iron PlateLegs */ - IRON_PLATELEGS(BarType.IRON, SmithingType.TYPE_PLATELEG, 1067, 31), + IRON_PLATELEGS(BarType.IRON, SmithingType.TYPE_PLATELEG, 1067, 15), /** * Iron PlateBody */ - IRON_PLATEBODY(BarType.IRON, SmithingType.TYPE_PLATEBODY, 1115, 33), + IRON_PLATEBODY(BarType.IRON, SmithingType.TYPE_PLATEBODY, 1115, 15), /** * Iron PickAxe */ - IRON_PICKAXE(BarType.IRON, SmithingType.TYPE_PICKAXE, 1267, 20), + IRON_PICKAXE(BarType.IRON, SmithingType.TYPE_PICKAXE, 1267, 15), /** * Steel Dagger @@ -285,132 +285,132 @@ public enum Bars { /** * Steel Axe */ - STEEL_AXE(BarType.STEEL, SmithingType.TYPE_AXE, 1353, 31), + STEEL_AXE(BarType.STEEL, SmithingType.TYPE_AXE, 1353, 30), /** * Steel Mace */ - STEEL_MACE(BarType.STEEL, SmithingType.TYPE_MACE, 1424, 32), + STEEL_MACE(BarType.STEEL, SmithingType.TYPE_MACE, 1424, 30), /** * Steel Medium Helm */ - STEEL_MED_HELM(BarType.STEEL, SmithingType.TYPE_MEDIUM_HELM, 1141, 33), + STEEL_MED_HELM(BarType.STEEL, SmithingType.TYPE_MEDIUM_HELM, 1141, 30), /** * Steel CrossBow bolts */ - STEEL_CROSSBOW_BOLT(BarType.STEEL, SmithingType.TYPE_CROSSBOW_BOLT, 9378, 33), + STEEL_CROSSBOW_BOLT(BarType.STEEL, SmithingType.TYPE_CROSSBOW_BOLT, 9378, 30), /** * Steel Sword */ - STEEL_SWORD(BarType.STEEL, SmithingType.TYPE_SWORD, 1281, 34), + STEEL_SWORD(BarType.STEEL, SmithingType.TYPE_SWORD, 1281, 30), /** * Steel Dart Tips */ - STEEL_DART_TIPS(BarType.STEEL, SmithingType.TYPE_DART_TIP, 821, 34), + STEEL_DART_TIPS(BarType.STEEL, SmithingType.TYPE_DART_TIP, 821, 30), /** * Steel Nails */ - STEEL_NAILS(BarType.STEEL, SmithingType.TYPE_NAIL, 1539, 34), + STEEL_NAILS(BarType.STEEL, SmithingType.TYPE_NAIL, 1539, 30), /** * Steel ArrowTips */ - STEEL_ARROW_TIPS(BarType.STEEL, SmithingType.TYPE_ARROW_TIP, 41, 35), + STEEL_ARROW_TIPS(BarType.STEEL, SmithingType.TYPE_ARROW_TIP, 41, 30), /** * Steel Scimitar */ - STEEL_SCIMITAR(BarType.STEEL, SmithingType.TYPE_SCIMITAR, 1325, 35), + STEEL_SCIMITAR(BarType.STEEL, SmithingType.TYPE_SCIMITAR, 1325, 30), /** * Steel Crossbow Limbs */ - STEEL_CROSSBOW_LIMBS(BarType.STEEL, SmithingType.TYPE_CROSSBOW_LIMB, 9425, 36), + STEEL_CROSSBOW_LIMBS(BarType.STEEL, SmithingType.TYPE_CROSSBOW_LIMB, 9425, 30), /** * Steel LongSword */ - STEEL_LONGSWORD(BarType.STEEL, SmithingType.TYPE_LONGSWORD, 1295, 36), + STEEL_LONGSWORD(BarType.STEEL, SmithingType.TYPE_LONGSWORD, 1295, 30), /** * Steel Knife */ - STEEL_THROWING_KNIFE(BarType.STEEL, SmithingType.TYPE_THROWING_KNIFE, 865, 37), + STEEL_THROWING_KNIFE(BarType.STEEL, SmithingType.TYPE_THROWING_KNIFE, 865, 30), /** * Steel Full Helm */ - STEEL_FULL_HELM(BarType.STEEL, SmithingType.TYPE_FULL_HELM, 1157, 37), + STEEL_FULL_HELM(BarType.STEEL, SmithingType.TYPE_FULL_HELM, 1157, 30), /** * Steel Studs */ - STEEL_STUDS(BarType.STEEL, SmithingType.TYPE_STUDS, 2370, 36), + STEEL_STUDS(BarType.STEEL, SmithingType.TYPE_STUDS, 2370, 30), /** * Steel Square Shield */ - STEEL_SQUARE_SHIELD(BarType.STEEL, SmithingType.TYPE_SQUARE_SHIELD, 1177, 38), + STEEL_SQUARE_SHIELD(BarType.STEEL, SmithingType.TYPE_SQUARE_SHIELD, 1177, 30), /** * Steel Lantern */ - STEEL_BULLSEYE(BarType.STEEL, SmithingType.TYPE_BULLSEYE, 4544, 49), + STEEL_BULLSEYE(BarType.STEEL, SmithingType.TYPE_BULLSEYE, 4544, 30), /** * Steel WarHammer */ - STEEL_WARHAMMER(BarType.STEEL, SmithingType.TYPE_WARHAMMER, 1339, 39), + STEEL_WARHAMMER(BarType.STEEL, SmithingType.TYPE_WARHAMMER, 1339, 30), /** * Steel battle axe */ - STEEL_BATTLE_AXE(BarType.STEEL, SmithingType.TYPE_BATTLE_AXE, 1365, 40), + STEEL_BATTLE_AXE(BarType.STEEL, SmithingType.TYPE_BATTLE_AXE, 1365, 30), /** * Steel ChainBody */ - STEEL_CHAINBODY(BarType.STEEL, SmithingType.TYPE_CHAINBODY, 1105, 41), + STEEL_CHAINBODY(BarType.STEEL, SmithingType.TYPE_CHAINBODY, 1105, 30), /** * Steel Kite Shield */ - STEEL_KITE_SHIELD(BarType.STEEL, SmithingType.TYPE_KITE_SHIELD, 1193, 42), + STEEL_KITE_SHIELD(BarType.STEEL, SmithingType.TYPE_KITE_SHIELD, 1193, 30), /** * Steel Claws */ - STEEL_CLAWS(BarType.STEEL, SmithingType.TYPE_CLAWS, 3097, 43), + STEEL_CLAWS(BarType.STEEL, SmithingType.TYPE_CLAWS, 3097, 30), /** * Steel 2h */ - STEEL_TWO_HANDED_SWORD(BarType.STEEL, SmithingType.TYPE_TWO_HAND_SWORD, 1311, 44), + STEEL_TWO_HANDED_SWORD(BarType.STEEL, SmithingType.TYPE_TWO_HAND_SWORD, 1311, 30), /** * Steel plate skirt */ - STEEL_PLATE_SKIRT(BarType.STEEL, SmithingType.TYPE_PLATE_SKIRT, 1083, 46), + STEEL_PLATE_SKIRT(BarType.STEEL, SmithingType.TYPE_PLATE_SKIRT, 1083, 30), /** * Steel platelegs */ - STEEL_PLATELEGS(BarType.STEEL, SmithingType.TYPE_PLATELEG, 1069, 46), + STEEL_PLATELEGS(BarType.STEEL, SmithingType.TYPE_PLATELEG, 1069, 30), /** * Steel platebody */ - STEEL_PLATEBODY(BarType.STEEL, SmithingType.TYPE_PLATEBODY, 1119, 48), + STEEL_PLATEBODY(BarType.STEEL, SmithingType.TYPE_PLATEBODY, 1119, 30), /** * Steel pickaxe */ - STEEL_PICKAXE(BarType.STEEL, SmithingType.TYPE_PICKAXE, 1269, 35), + STEEL_PICKAXE(BarType.STEEL, SmithingType.TYPE_PICKAXE, 1269, 30), /** * Mithril Dagger @@ -420,377 +420,377 @@ public enum Bars { /** * Mithril Hatchet */ - MITHRIL_HATCHET(BarType.MITHRIL, SmithingType.TYPE_AXE, 1355, 51), + MITHRIL_HATCHET(BarType.MITHRIL, SmithingType.TYPE_AXE, 1355, 50), /** * Mithril Mace */ - MITHRIL_MACE(BarType.MITHRIL, SmithingType.TYPE_MACE, 1428, 52), + MITHRIL_MACE(BarType.MITHRIL, SmithingType.TYPE_MACE, 1428, 50), /** * Mithril Med Helm */ - MITHRIL_MED_HELM(BarType.MITHRIL, SmithingType.TYPE_MEDIUM_HELM, 1143, 53), + MITHRIL_MED_HELM(BarType.MITHRIL, SmithingType.TYPE_MEDIUM_HELM, 1143, 50), /** * Mithril Crossbow Bolt */ - MITHRIL_CROSSBOW_BOLT(BarType.MITHRIL, SmithingType.TYPE_CROSSBOW_BOLT, 9379, 53), + MITHRIL_CROSSBOW_BOLT(BarType.MITHRIL, SmithingType.TYPE_CROSSBOW_BOLT, 9379, 50), /** * Mithril Sword */ - MITHRIL_SWORD(BarType.MITHRIL, SmithingType.TYPE_SWORD, 1285, 54), + MITHRIL_SWORD(BarType.MITHRIL, SmithingType.TYPE_SWORD, 1285, 50), /** * Mithril Dart Tips */ - MITHRIL_DART_TIPS(BarType.MITHRIL, SmithingType.TYPE_DART_TIP, 822, 54), + MITHRIL_DART_TIPS(BarType.MITHRIL, SmithingType.TYPE_DART_TIP, 822, 50), /** * Mithril Nails */ - MITHRIL_NAILS(BarType.MITHRIL, SmithingType.TYPE_NAIL, 4822, 54), + MITHRIL_NAILS(BarType.MITHRIL, SmithingType.TYPE_NAIL, 4822, 50), /** * Mithril Arrow Tips */ - MITHRIL_ARROW_TIPS(BarType.MITHRIL, SmithingType.TYPE_ARROW_TIP, 42, 55), + MITHRIL_ARROW_TIPS(BarType.MITHRIL, SmithingType.TYPE_ARROW_TIP, 42, 50), /** * Mithril Scimitar */ - MITHRIL_SCIMITAR(BarType.MITHRIL, SmithingType.TYPE_SCIMITAR, 1329, 55), + MITHRIL_SCIMITAR(BarType.MITHRIL, SmithingType.TYPE_SCIMITAR, 1329, 50), /** * Mithril Crossbow Limbs */ - MITHRIL_CROSSBOW_LIMBS(BarType.MITHRIL, SmithingType.TYPE_CROSSBOW_LIMB, 9427, 56), + MITHRIL_CROSSBOW_LIMBS(BarType.MITHRIL, SmithingType.TYPE_CROSSBOW_LIMB, 9427, 50), /** * Mithril LongSword */ - MITHRIL_LONGSWORD(BarType.MITHRIL, SmithingType.TYPE_LONGSWORD, 1299, 56), + MITHRIL_LONGSWORD(BarType.MITHRIL, SmithingType.TYPE_LONGSWORD, 1299, 50), /** * Mithril Knife */ - MITHRIL_KNIFE(BarType.MITHRIL, SmithingType.TYPE_THROWING_KNIFE, 866, 57), + MITHRIL_KNIFE(BarType.MITHRIL, SmithingType.TYPE_THROWING_KNIFE, 866, 50), /** * Mithril Full Helm */ - MITHRIL_FULL_HELM(BarType.MITHRIL, SmithingType.TYPE_FULL_HELM, 1159, 57), + MITHRIL_FULL_HELM(BarType.MITHRIL, SmithingType.TYPE_FULL_HELM, 1159, 50), /** * Mithril SquareShield */ - MITHRIL_SQUARE_SHIELD(BarType.MITHRIL, SmithingType.TYPE_SQUARE_SHIELD, 1181, 58), + MITHRIL_SQUARE_SHIELD(BarType.MITHRIL, SmithingType.TYPE_SQUARE_SHIELD, 1181, 50), /** * Mithril Grapple Tips */ - MITHRIL_GRAPPLE_TIPS(BarType.MITHRIL, SmithingType.TYPE_GRAPPLE_TIP, 9416, 59), + MITHRIL_GRAPPLE_TIPS(BarType.MITHRIL, SmithingType.TYPE_GRAPPLE_TIP, 9416, 50), /** * Mithril Warhammer */ - MITHRIL_WARHAMMER(BarType.MITHRIL, SmithingType.TYPE_WARHAMMER, 1343, 59), + MITHRIL_WARHAMMER(BarType.MITHRIL, SmithingType.TYPE_WARHAMMER, 1343, 50), /** * Mithril BattleAxe */ - MITHRIL_BATTLEAXE(BarType.MITHRIL, SmithingType.TYPE_BATTLE_AXE, 1369, 60), + MITHRIL_BATTLEAXE(BarType.MITHRIL, SmithingType.TYPE_BATTLE_AXE, 1369, 50), /** * Mithril ChainBody */ - MITHRIL_CHAINBODY(BarType.MITHRIL, SmithingType.TYPE_CHAINBODY, 1109, 61), + MITHRIL_CHAINBODY(BarType.MITHRIL, SmithingType.TYPE_CHAINBODY, 1109, 50), /** * Mithril KiteShield */ - MITHRIL_KITE_SHIELD(BarType.MITHRIL, SmithingType.TYPE_KITE_SHIELD, 1197, 62), + MITHRIL_KITE_SHIELD(BarType.MITHRIL, SmithingType.TYPE_KITE_SHIELD, 1197, 50), /** * Mithril Claws */ - MITHRIL_CLAWS(BarType.MITHRIL, SmithingType.TYPE_CLAWS, 3099, 63), + MITHRIL_CLAWS(BarType.MITHRIL, SmithingType.TYPE_CLAWS, 3099, 50), /** * Mithril 2H */ - MITHRIL_TWO_HANDED_SWORD(BarType.MITHRIL, SmithingType.TYPE_TWO_HAND_SWORD, 1315, 64), + MITHRIL_TWO_HANDED_SWORD(BarType.MITHRIL, SmithingType.TYPE_TWO_HAND_SWORD, 1315, 50), /** * Mithril PlateSkirt */ - MITHRIL_PLATESKIRT(BarType.MITHRIL, SmithingType.TYPE_PLATE_SKIRT, 1085, 66), + MITHRIL_PLATESKIRT(BarType.MITHRIL, SmithingType.TYPE_PLATE_SKIRT, 1085, 50), /** * Mithril PlateLegs */ - MITHRIL_PLATELEGS(BarType.MITHRIL, SmithingType.TYPE_PLATELEG, 1071, 66), + MITHRIL_PLATELEGS(BarType.MITHRIL, SmithingType.TYPE_PLATELEG, 1071, 50), /** * Mithril PlateBody */ - MITHRIL_PLATEBODY(BarType.MITHRIL, SmithingType.TYPE_PLATEBODY, 1121, 68), + MITHRIL_PLATEBODY(BarType.MITHRIL, SmithingType.TYPE_PLATEBODY, 1121, 50), /** * Mithril PickAxe */ - MITHRIL_PICKAXE(BarType.MITHRIL, SmithingType.TYPE_PICKAXE, 1273, 55), + MITHRIL_PICKAXE(BarType.MITHRIL, SmithingType.TYPE_PICKAXE, 1273, 50), /** * Adamant Dagger */ - ADAMANT_DAGGER(BarType.ADAMANT, SmithingType.TYPE_DAGGER, 1211, 70), + ADAMANT_DAGGER(BarType.ADAMANT, SmithingType.TYPE_DAGGER, 1211, 60), /** * Adamant Hatchet */ - ADAMANT_AXE(BarType.ADAMANT, SmithingType.TYPE_AXE, 1357, 71), + ADAMANT_AXE(BarType.ADAMANT, SmithingType.TYPE_AXE, 1357, 60), /** * Adamant Mace */ - ADAMANT_MACE(BarType.ADAMANT, SmithingType.TYPE_MACE, 1430, 72), + ADAMANT_MACE(BarType.ADAMANT, SmithingType.TYPE_MACE, 1430, 60), /** * Adamant Med Helm */ - ADAMANT_MEDIUM_HELM(BarType.ADAMANT, SmithingType.TYPE_MEDIUM_HELM, 1145, 73), + ADAMANT_MEDIUM_HELM(BarType.ADAMANT, SmithingType.TYPE_MEDIUM_HELM, 1145, 60), /** * Adamant Crossbow Bolt */ - ADAMANT_BOLT(BarType.ADAMANT, SmithingType.TYPE_CROSSBOW_BOLT, 9380, 73), + ADAMANT_BOLT(BarType.ADAMANT, SmithingType.TYPE_CROSSBOW_BOLT, 9380, 60), /** * Adamant Sword */ - ADAMANT_SWORD(BarType.ADAMANT, SmithingType.TYPE_SWORD, 1287, 74), + ADAMANT_SWORD(BarType.ADAMANT, SmithingType.TYPE_SWORD, 1287, 60), /** * Adamant Dart Tips */ - ADAMANT_DART_TIPS(BarType.ADAMANT, SmithingType.TYPE_DART_TIP, 823, 74), + ADAMANT_DART_TIPS(BarType.ADAMANT, SmithingType.TYPE_DART_TIP, 823, 60), /** * Adamant Nails */ - ADAMANT_NAILS(BarType.ADAMANT, SmithingType.TYPE_NAIL, 4823, 74), + ADAMANT_NAILS(BarType.ADAMANT, SmithingType.TYPE_NAIL, 4823, 60), /** * Adamant Arrow Tips */ - ADAMANT_ARROW_TIPS(BarType.ADAMANT, SmithingType.TYPE_ARROW_TIP, 43, 75), + ADAMANT_ARROW_TIPS(BarType.ADAMANT, SmithingType.TYPE_ARROW_TIP, 43, 60), /** * Adamant Scmitar */ - ADAMANT_SCIMITAR(BarType.ADAMANT, SmithingType.TYPE_SCIMITAR, 1331, 75), + ADAMANT_SCIMITAR(BarType.ADAMANT, SmithingType.TYPE_SCIMITAR, 1331, 60), /** * Adamant Crossbow Limbs */ - ADAMANT_LIMBS(BarType.ADAMANT, SmithingType.TYPE_CROSSBOW_LIMB, 9429, 76), + ADAMANT_LIMBS(BarType.ADAMANT, SmithingType.TYPE_CROSSBOW_LIMB, 9429, 60), /** * Adamant LongSword */ - ADAMANT_LONGSWORD(BarType.ADAMANT, SmithingType.TYPE_LONGSWORD, 1301, 76), + ADAMANT_LONGSWORD(BarType.ADAMANT, SmithingType.TYPE_LONGSWORD, 1301, 60), /** * Adamant Knife */ - ADAMANT_KNIFE(BarType.ADAMANT, SmithingType.TYPE_THROWING_KNIFE, 867, 77), + ADAMANT_KNIFE(BarType.ADAMANT, SmithingType.TYPE_THROWING_KNIFE, 867, 60), /** * Adamant Full Helm */ - ADAMANT_FULL_HELM(BarType.ADAMANT, SmithingType.TYPE_FULL_HELM, 1161, 77), + ADAMANT_FULL_HELM(BarType.ADAMANT, SmithingType.TYPE_FULL_HELM, 1161, 60), /** * Adamant Square Shield */ - ADAMANT_SQUARE_SHIELD(BarType.ADAMANT, SmithingType.TYPE_SQUARE_SHIELD, 1183, 78), + ADAMANT_SQUARE_SHIELD(BarType.ADAMANT, SmithingType.TYPE_SQUARE_SHIELD, 1183, 60), /** * Adamant Warhammer */ - ADAMANT_WARHAMMER(BarType.ADAMANT, SmithingType.TYPE_WARHAMMER, 1345, 79), + ADAMANT_WARHAMMER(BarType.ADAMANT, SmithingType.TYPE_WARHAMMER, 1345, 60), /** * Adamant BattleAxe */ - ADAMANT_BATTLEAXE(BarType.ADAMANT, SmithingType.TYPE_BATTLE_AXE, 1371, 80), + ADAMANT_BATTLEAXE(BarType.ADAMANT, SmithingType.TYPE_BATTLE_AXE, 1371, 60), /** * Adamant ChainBody */ - ADAMANT_CHAINBODY(BarType.ADAMANT, SmithingType.TYPE_CHAINBODY, 1111, 81), + ADAMANT_CHAINBODY(BarType.ADAMANT, SmithingType.TYPE_CHAINBODY, 1111, 60), /** * Adamant KiteShield */ - ADAMANT_KITESHIELD(BarType.ADAMANT, SmithingType.TYPE_KITE_SHIELD, 1199, 82), + ADAMANT_KITESHIELD(BarType.ADAMANT, SmithingType.TYPE_KITE_SHIELD, 1199, 60), /** * Adamant Claws */ - ADAMANT_CLAWS(BarType.ADAMANT, SmithingType.TYPE_CLAWS, 3100, 83), + ADAMANT_CLAWS(BarType.ADAMANT, SmithingType.TYPE_CLAWS, 3100, 60), /** * Adamant 2H */ - ADAMANT_TWO_HANDED_SWORD(BarType.ADAMANT, SmithingType.TYPE_TWO_HAND_SWORD, 1317, 84), + ADAMANT_TWO_HANDED_SWORD(BarType.ADAMANT, SmithingType.TYPE_TWO_HAND_SWORD, 1317, 60), /** * Adamant PlateSkirt */ - ADAMANT_PLATE_SKIRT(BarType.ADAMANT, SmithingType.TYPE_PLATE_SKIRT, 1091, 86), + ADAMANT_PLATE_SKIRT(BarType.ADAMANT, SmithingType.TYPE_PLATE_SKIRT, 1091, 60), /** * Adamant PlateLegs */ - ADAMANT_PLATE_LEGS(BarType.ADAMANT, SmithingType.TYPE_PLATELEG, 1073, 86), + ADAMANT_PLATE_LEGS(BarType.ADAMANT, SmithingType.TYPE_PLATELEG, 1073, 60), /** * Adamant PlateBody */ - ADAMANT_PLATE_BODY(BarType.ADAMANT, SmithingType.TYPE_PLATEBODY, 1123, 88), + ADAMANT_PLATE_BODY(BarType.ADAMANT, SmithingType.TYPE_PLATEBODY, 1123, 60), /** * Adamant PickAxe */ - ADAMANT_PICKAXE(BarType.ADAMANT, SmithingType.TYPE_PICKAXE, 1271, 75), + ADAMANT_PICKAXE(BarType.ADAMANT, SmithingType.TYPE_PICKAXE, 1271, 60), /** * Rune Dagger */ - RUNE_DAGGER(BarType.RUNITE, SmithingType.TYPE_DAGGER, 1213, 85), + RUNE_DAGGER(BarType.RUNITE, SmithingType.TYPE_DAGGER, 1213, 70), /** * Rune Hatchet */ - RUNITE_AXE(BarType.RUNITE, SmithingType.TYPE_AXE, 1359, 86), + RUNITE_AXE(BarType.RUNITE, SmithingType.TYPE_AXE, 1359, 70), /** * Rune Mace */ - RUNITE_MACE(BarType.RUNITE, SmithingType.TYPE_MACE, 1432, 87), + RUNITE_MACE(BarType.RUNITE, SmithingType.TYPE_MACE, 1432, 70), /** * Rune Med Helm */ - RUNITE_MEDIUM_HELM(BarType.RUNITE, SmithingType.TYPE_MEDIUM_HELM, 1147, 88), + RUNITE_MEDIUM_HELM(BarType.RUNITE, SmithingType.TYPE_MEDIUM_HELM, 1147, 70), /** * Rune Crossbow Bolt */ - RUNITE_BOLT(BarType.RUNITE, SmithingType.TYPE_CROSSBOW_BOLT, 9381, 88), + RUNITE_BOLT(BarType.RUNITE, SmithingType.TYPE_CROSSBOW_BOLT, 9381, 70), /** * Rune Sword */ - RUNITE_SWORD(BarType.RUNITE, SmithingType.TYPE_SWORD, 1289, 89), + RUNITE_SWORD(BarType.RUNITE, SmithingType.TYPE_SWORD, 1289, 70), /** * Rune Dart Tips */ - RUNITE_DART_TIPS(BarType.RUNITE, SmithingType.TYPE_DART_TIP, 824, 89), + RUNITE_DART_TIPS(BarType.RUNITE, SmithingType.TYPE_DART_TIP, 824, 70), /** * Rune Nails */ - RUNITE_NAILS(BarType.RUNITE, SmithingType.TYPE_NAIL, 4824, 89), + RUNITE_NAILS(BarType.RUNITE, SmithingType.TYPE_NAIL, 4824, 70), /** * Rune Arrow Tips */ - RUNITE_ARROW_TIPS(BarType.RUNITE, SmithingType.TYPE_ARROW_TIP, 44, 90), + RUNITE_ARROW_TIPS(BarType.RUNITE, SmithingType.TYPE_ARROW_TIP, 44, 70), /** * Rune Scmitar */ - RUNITE_SCIMITAR(BarType.RUNITE, SmithingType.TYPE_SCIMITAR, 1333, 90), + RUNITE_SCIMITAR(BarType.RUNITE, SmithingType.TYPE_SCIMITAR, 1333, 70), /** * Rune Crossbow Limbs */ - RUNITE_LIMBS(BarType.RUNITE, SmithingType.TYPE_CROSSBOW_LIMB, 9431, 91), + RUNITE_LIMBS(BarType.RUNITE, SmithingType.TYPE_CROSSBOW_LIMB, 9431, 70), /** * Rune LongSword */ - RUNITE_LONGSWORD(BarType.RUNITE, SmithingType.TYPE_LONGSWORD, 1303, 91), + RUNITE_LONGSWORD(BarType.RUNITE, SmithingType.TYPE_LONGSWORD, 1303, 70), /** * Rune Knife */ - RUNITE_KNIFE(BarType.RUNITE, SmithingType.TYPE_THROWING_KNIFE, 868, 92), + RUNITE_KNIFE(BarType.RUNITE, SmithingType.TYPE_THROWING_KNIFE, 868, 70), /** * Rune Full Helm */ - RUNITE_FULL_HELM(BarType.RUNITE, SmithingType.TYPE_FULL_HELM, 1163, 92), + RUNITE_FULL_HELM(BarType.RUNITE, SmithingType.TYPE_FULL_HELM, 1163, 70), /** * Rune Square Shield */ - RUNITE_SQUARE_SHIELD(BarType.RUNITE, SmithingType.TYPE_SQUARE_SHIELD, 1185, 93), + RUNITE_SQUARE_SHIELD(BarType.RUNITE, SmithingType.TYPE_SQUARE_SHIELD, 1185, 70), /** * Rune Warhammer */ - RUNITE_WARHAMMER(BarType.RUNITE, SmithingType.TYPE_WARHAMMER, 1347, 94), + RUNITE_WARHAMMER(BarType.RUNITE, SmithingType.TYPE_WARHAMMER, 1347, 70), /** * Rune BattleAxe */ - RUNITE_BATTLEAXE(BarType.RUNITE, SmithingType.TYPE_BATTLE_AXE, 1373, 95), + RUNITE_BATTLEAXE(BarType.RUNITE, SmithingType.TYPE_BATTLE_AXE, 1373, 70), /** * Rune ChainBody */ - RUNITE_CHAINBODY(BarType.RUNITE, SmithingType.TYPE_CHAINBODY, 1113, 96), + RUNITE_CHAINBODY(BarType.RUNITE, SmithingType.TYPE_CHAINBODY, 1113, 70), /** * Rune KiteShield */ - RUNITE_KITESHIELD(BarType.RUNITE, SmithingType.TYPE_KITE_SHIELD, 1201, 97), + RUNITE_KITESHIELD(BarType.RUNITE, SmithingType.TYPE_KITE_SHIELD, 1201, 70), /** * Rune Claws */ - RUNITE_CLAWS(BarType.RUNITE, SmithingType.TYPE_CLAWS, 3101, 98), + RUNITE_CLAWS(BarType.RUNITE, SmithingType.TYPE_CLAWS, 3101, 70), /** * Rune 2H */ - RUNITE_TWO_HANDED_SWORD(BarType.RUNITE, SmithingType.TYPE_TWO_HAND_SWORD, 1319, 99), + RUNITE_TWO_HANDED_SWORD(BarType.RUNITE, SmithingType.TYPE_TWO_HAND_SWORD, 1319, 70), /** * Rune PlateSkirt */ - RUNITE_PLATE_SKIRT(BarType.RUNITE, SmithingType.TYPE_PLATE_SKIRT, 1093, 99), + RUNITE_PLATE_SKIRT(BarType.RUNITE, SmithingType.TYPE_PLATE_SKIRT, 1093, 70), /** * Rune PlateLegs */ - RUNITE_PLATE_LEGS(BarType.RUNITE, SmithingType.TYPE_PLATELEG, 1079, 99), + RUNITE_PLATE_LEGS(BarType.RUNITE, SmithingType.TYPE_PLATELEG, 1079, 70), /** * Rune PlateBody */ - RUNITE_PLATE_BODY(BarType.RUNITE, SmithingType.TYPE_PLATEBODY, 1127, 99), + RUNITE_PLATE_BODY(BarType.RUNITE, SmithingType.TYPE_PLATEBODY, 1127, 70), /** * Rune PickAxe */ - RUNITE_PICKAXE(BarType.RUNITE, SmithingType.TYPE_PICKAXE, 1275, 90), + RUNITE_PICKAXE(BarType.RUNITE, SmithingType.TYPE_PICKAXE, 1275, 70), /** * Blurite CrossBow bolts @@ -800,7 +800,7 @@ public enum Bars { /** * Blurite Crossbow Limbs */ - BLURITE_CROSSBOW_LIMBS(BarType.BLURITE, SmithingType.TYPE_CROSSBOW_LIMB, 9422, 13); + BLURITE_CROSSBOW_LIMBS(BarType.BLURITE, SmithingType.TYPE_CROSSBOW_LIMB, 9422, 8); /** * A map of object ids to primary ingredients. From 62dc8bc3241ce74ae5370025aa3bd7a9a9c3c2cf Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:42:40 -0600 Subject: [PATCH 043/306] Updated Smelting levels Lowered Adamant and Runite smelting to 60 and 70 respectively. --- .../src/main/content/global/skill/smithing/smelting/Bar.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/smithing/smelting/Bar.java b/Server/src/main/content/global/skill/smithing/smelting/Bar.java index 04177c11a..88b4eea74 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/Bar.java +++ b/Server/src/main/content/global/skill/smithing/smelting/Bar.java @@ -15,8 +15,8 @@ public enum Bar { STEEL(30, 17.5, new Item(2353, 1), new Item(453, 2), new Item(440, 1)), GOLD(40, 22.5, new Item(2357, 1), new Item(444, 1)), MITHRIL(50, 30, new Item(2359, 1), new Item(447, 1), new Item(453, 4)), - ADAMANT(70, 37.5, new Item(2361, 1), new Item(449, 1), new Item(453, 6)), - RUNITE(85, 50, new Item(2363, 1), new Item(451, 1), new Item(453, 8)); + ADAMANT(60, 37.5, new Item(2361, 1), new Item(449, 1), new Item(453, 6)), + RUNITE(70, 50, new Item(2363, 1), new Item(451, 1), new Item(453, 8)); /** * The ore required. From cc6f33ab7ef218b99c1588b1a6ebd25b8126e9a4 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:49:19 -0600 Subject: [PATCH 044/306] Updating mining levels for mithril, adamant, and rune to 50, 60, 70. --- .../main/content/global/skill/gather/mining/MiningNode.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/gather/mining/MiningNode.java b/Server/src/main/content/global/skill/gather/mining/MiningNode.java index 5f7f00cf3..11a564cf8 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningNode.java +++ b/Server/src/main/content/global/skill/gather/mining/MiningNode.java @@ -522,21 +522,21 @@ public enum MiningNode{ experience = 80.0; rate = 0.70; reward = 447; - level = 55; + level = 50; break; case 11: respawnRate = 400 | 800 << 16; experience = 95.0; rate = 0.85; reward = 449; - level = 70; + level = 60; break; case 12: respawnRate = 1250 | 2500 << 16; experience = 125.0; rate = 0.95; reward = 451; - level = 85; + level = 70; break; case 13: respawnRate = 166 | 175 << 16; From bc5958b60db92409dd37c248989a0759cc6abba7 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 20:57:03 -0600 Subject: [PATCH 045/306] Added -Xmx flag to specify the amount of RAM the server allocates --- run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run b/run index e1c4fdc10..ed57b2f4a 100755 --- a/run +++ b/run @@ -10,7 +10,7 @@ REFRESH_BUILD=1 GAMESERVER_ONLY=1 -GS_EXEC="cd $GS_SRC && java -Dnashorn.args=--no-deprecation-warning -jar $BUILD_DIR/server.jar" +GS_EXEC="cd $GS_SRC && java -Xmx7g -Dnashorn.args=--no-deprecation-warning -jar $BUILD_DIR/server.jar" MS_EXEC="cd $MS_SRC && java -Dnashorn.args=--no-deprecation-warning -jar $BUILD_DIR/ms.jar" # 0: parallel From 490c6d42ec18ebeae1275933159fa2ec40196778 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 27 Oct 2024 21:06:08 -0600 Subject: [PATCH 046/306] Autocast changes - All God staves can autocast, and autocast is now independent of active spellbook. --- .../combat/equipment/WeaponInterface.java | 61 +++++++++++++++---- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java index cb74f3fa6..6a38729fe 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/WeaponInterface.java @@ -46,10 +46,20 @@ public final class WeaponInterface extends Component { private static final int[] SLAYER_STAFF_SPELL_IDS = { 22, 31, 45, 48, 52, 55 }; /** - * The void staff spell ids + * The void and guthix staff spell ids */ private static final int[] VOID_STAFF_SPELL_IDS = { 22, 42, 45, 48, 52, 55 }; + /** + * The saradomin staff spell ids + */ + private static final int[] SARADOMIN_STAFF_SPELL_IDS = { 22, 41, 45, 48, 52, 55 }; + + /** + * The zamorak staff spell ids + */ + private static final int[] ZAMORAK_STAFF_SPELL_IDS = { 22, 43, 45, 48, 52, 55 }; + /** * The default attack animations. */ @@ -333,13 +343,23 @@ public final class WeaponInterface extends Component { * @return The component id for the autocast select tab. */ public int getAutospellId(int spellId) { - boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; - int[] data = modern ? MODERN_SPELL_IDS : ANCIENT_SPELL_IDS; - if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { + //boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; + boolean modern = !player.getEquipment().getNew(3).getName().equalsIgnoreCase("Ancient Staff") && !player.getEquipment().getNew(3).getName().contains("uriel's staff"); + int[] data = MODERN_SPELL_IDS; + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Ancient Staff") || player.getEquipment().getNew(3).getName().contains("uriel's staff")) { + data = ANCIENT_SPELL_IDS; + } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { data = SLAYER_STAFF_SPELL_IDS; } - if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace")) { + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace") || player.getEquipment().getNew(3).getName().equalsIgnoreCase("Guthix Staff")) { data = VOID_STAFF_SPELL_IDS; + } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Saradomin Staff")) { + data = SARADOMIN_STAFF_SPELL_IDS; + } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Zamorak Staff")) { + data = ZAMORAK_STAFF_SPELL_IDS; } for (int i = 0; i < data.length; i++) { if (data[i] == spellId) { @@ -355,14 +375,24 @@ public final class WeaponInterface extends Component { * @param adjustAttackStyle If the attack style should be adjusted. */ public void selectAutoSpell(int buttonId, boolean adjustAttackStyle) { - boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; - int[] data = modern ? MODERN_SPELL_IDS : ANCIENT_SPELL_IDS; - if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { + //boolean modern = player.getSpellBookManager().getSpellBook() == Components.MAGIC_192; + boolean modern = !player.getEquipment().getNew(3).getName().equalsIgnoreCase("Ancient Staff") && !player.getEquipment().getNew(3).getName().contains("uriel's staff"); + int[] data = MODERN_SPELL_IDS; + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Ancient staff") || player.getEquipment().getNew(3).getName().contains("uriel's staff")) { + data = ANCIENT_SPELL_IDS; + } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff")) { data = SLAYER_STAFF_SPELL_IDS; } - if (modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace")) { + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace") || modern && player.getEquipment().getNew(3).getName().equalsIgnoreCase("Guthix Staff")) { data = VOID_STAFF_SPELL_IDS; } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Saradomin Staff")) { + data = SARADOMIN_STAFF_SPELL_IDS; + } + if (player.getEquipment().getNew(3).getName().equalsIgnoreCase("Zamorak Staff")) { + data = ZAMORAK_STAFF_SPELL_IDS; + } CombatSpell current = player.getProperties().getAutocastSpell(); if (buttonId >= data.length) { return; @@ -455,15 +485,20 @@ public final class WeaponInterface extends Component { return; } player.setAttribute("autocast_select", true); - int id = player.getSpellBookManager().getSpellBook() == 193 ? 797 : 319; + //int id = player.getSpellBookManager().getSpellBook() == 193 ? 797 : 319; + int id = 319; + boolean ancient = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Ancient staff") || player.getEquipment().getNew(3).getName().contains("uriel's staff"); boolean slayer = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Slayer's staff"); - boolean mace = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace"); + boolean mace = player.getEquipment().getNew(3).getName().equalsIgnoreCase("Void knight mace") || player.getEquipment().getNew(3).getName().equalsIgnoreCase("Guthix Staff") || player.getEquipment().getNew(3).getName().equalsIgnoreCase("Saradomin Staff") || player.getEquipment().getNew(3).getName().equalsIgnoreCase("Zamorak Staff"); if (slayer) { id = 310; } if (mace) { id = 406; } + if (ancient) { + id = 797; + } Component component = new Component(id); component.getDefinition().setTabIndex(0); component.getDefinition().setType(InterfaceType.TAB); @@ -480,7 +515,7 @@ public final class WeaponInterface extends Component { if (current != WeaponInterfaces.STAFF) { return false; } - if (player.getSpellBookManager().getSpellBook() == SpellBookManager.SpellBook.LUNAR.getInterfaceId()) { + /* if (player.getSpellBookManager().getSpellBook() == SpellBookManager.SpellBook.LUNAR.getInterfaceId()) { if (message) { player.getPacketDispatch().sendMessage("You can't autocast Lunar magic."); } @@ -492,7 +527,7 @@ public final class WeaponInterface extends Component { player.getPacketDispatch().sendMessage("You can only autocast ancient magicks with an Ancient or Zuriel's staff."); } return false; - } + } */ return true; } From b35159b5b7ccc356f464476db60b72b2eebba65d Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 28 Oct 2024 12:54:33 -0600 Subject: [PATCH 047/306] Implement pickpocketing auto-repeating if the player is wearing Gloves of Silence The player.lock function doesn't run if the player has gloves on, since it prevents triggering the pickpocket action immediately afterwards. To avoid pickpocketing every tick, we check the game ticks if the player has gloves and only perform the action every other tick. Testing indicates that manual pickpocketing can occur every 2 ticks, so the auto-repeat occurs at the same rate. If the player fails pickpocketing, the stun will prevent the auto-repeat from activating. --- .../global/skill/thieving/ThievingListeners.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt index d6123fcda..a236ca291 100644 --- a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt +++ b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt @@ -15,6 +15,9 @@ import core.game.node.entity.player.Player import core.game.node.item.Item import org.rs09.consts.Sounds +import core.game.interaction.InteractionListeners +import core.game.world.GameWorld + class ThievingListeners : InteractionListener { companion object { @@ -64,6 +67,10 @@ class ThievingListeners : InteractionListener { player.sendMessage("You don't have enough inventory space to do that.") return@on true } + + //Custom portion. If the player has gloves of silence, only proceed every other tick + val glovesOfSilence = player.equipment.contains(Items.GLOVES_OF_SILENCE_10075,1) + if (!glovesOfSilence || GameWorld.ticks % 2 == 0) { player.animator.animate(PICKPOCKET_ANIM) val lootTable = pickpocketRoll(player, pickpocketData.low, pickpocketData.high, pickpocketData.table) @@ -80,11 +87,17 @@ class ThievingListeners : InteractionListener { node.asNpc().face(null) } else { playAudio(player, Sounds.PICK_2581) - player.lock(2) + if (!glovesOfSilence) { + player.lock(2) + } lootTable.forEach { player.inventory.add(it) } player.skills.addExperience(Skills.THIEVING,pickpocketData.experience) } - + } + // if wearing gloves of silence, pickpocket again. + if (glovesOfSilence) { + InteractionListeners.run(node.id, IntType.NPC,"Pickpocket",player,node) + } return@on true } } From 0fddd2134b25e7ffd1e67c2637ef119c3a432b19 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 31 Oct 2024 15:20:14 -0600 Subject: [PATCH 048/306] Firemaking now repeats until all the matching logs in your inventory are used --- .../global/skill/firemaking/FireMakingPulse.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java index 50b969efd..a2612543d 100644 --- a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java +++ b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java @@ -19,6 +19,8 @@ import org.rs09.consts.Items; import static core.api.ContentAPIKt.inInventory; import static core.api.ContentAPIKt.replaceSlot; +import static core.api.ContentAPIKt.removeItem; + /** * Represents the pulse used to light a log. * @author 'Vexia @@ -102,10 +104,12 @@ public final class FireMakingPulse extends SkillPulse { @Override public boolean reward() { + /* Snowscape: this section allows making a new fire without an animation if you're fast enough, but since we auto-repeat we don't need that if (getLastFire() >= GameWorld.getTicks()) { createFire(); return true; } + */ if (ticks == 0) { player.animate(ANIMATION); } @@ -119,7 +123,13 @@ public final class FireMakingPulse extends SkillPulse { return false; } createFire(); - return true; + // Snowscape: attempt to remove another log. If successful, the pulse continues and the player makes another fire + if (removeItem(player, new Item(node.getId(), 1), Container.INVENTORY)) { + return false; + } else { + return true; + } + } /** From bbf8f3c3487e0e937610f9c3ddeeaa9d1803693f Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 31 Oct 2024 21:49:05 -0600 Subject: [PATCH 049/306] Ore rocks now only have a chance to deplete based on Mining Level and rock respawn time --- .../main/content/global/skill/gather/mining/MiningListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/gather/mining/MiningListener.kt b/Server/src/main/content/global/skill/gather/mining/MiningListener.kt index d744b0a8f..9233b836f 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningListener.kt +++ b/Server/src/main/content/global/skill/gather/mining/MiningListener.kt @@ -136,7 +136,7 @@ class MiningListener : InteractionListener { } // Transform ore to depleted version - if (!isEssence && resource!!.respawnRate != 0) { + if (!isEssence && resource!!.respawnRate != 0 && RandomFunction.roll(getDynLevel(player, Skills.MINING)*5/resource!!.respawnDuration + 1)) { SceneryBuilder.replace(node as Scenery, Scenery(resource!!.emptyId, node.getLocation(), node.type, node.rotation), resource!!.respawnDuration) node.setActive(false) return true From 0f00221cd945dbb7b9f72e94543c11b1bfb38f5f Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 3 Nov 2024 18:32:19 -0700 Subject: [PATCH 050/306] Updated Soul Rift in Abyss to teleport to new altar on Crandor --- .../src/main/content/global/skill/runecrafting/Altar.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Server/src/main/content/global/skill/runecrafting/Altar.java b/Server/src/main/content/global/skill/runecrafting/Altar.java index 8be433efc..5bb2f0794 100644 --- a/Server/src/main/content/global/skill/runecrafting/Altar.java +++ b/Server/src/main/content/global/skill/runecrafting/Altar.java @@ -82,6 +82,14 @@ public enum Altar { if (this == BLOOD) { if (!hasRequirement(player, "Legacy of Seergaze")) return; + } + if (this == SOUL) { + if (player.getQuestRepository().isComplete("Dragon Slayer")) { + player.getProperties().setTeleportLocation(Location.create(2836, 3285, 0)); + } else { + player.sendMessage("You need to have completed the Dragon Slayer quest in order to do that."); + return; + } } if (this == LAW) { if (!ItemDefinition.canEnterEntrana(player)) { From 020c10d96165172e8c0262ce1e3637227eb5b077 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 3 Nov 2024 18:34:44 -0700 Subject: [PATCH 051/306] Placed new Soul Altar on Crandor --- Server/data/ObjectParser.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/data/ObjectParser.xml b/Server/data/ObjectParser.xml index b10a0d445..547e2eaf1 100644 --- a/Server/data/ObjectParser.xml +++ b/Server/data/ObjectParser.xml @@ -25,4 +25,6 @@ + + From 540db8e15ad9302dbc75562e46f6d4cf99c9e2a5 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 3 Nov 2024 18:40:32 -0700 Subject: [PATCH 052/306] Added ability to craft altar teleport tablets by bringing soft clay to the respective altar. --- .../skill/runecrafting/RuneCraftPulse.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index d32bea579..b5e2745b6 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -40,6 +40,7 @@ public final class RuneCraftPulse extends SkillPulse { * Represents the pure essence item. */ private static final Item PURE_ESSENCE = new Item(7936); + private static final Item SOFT_CLAY = new Item(1761); /** * Represents the binding necklace item. @@ -119,12 +120,12 @@ public final class RuneCraftPulse extends SkillPulse { player.getPacketDispatch().sendMessage("You need pure essence to craft this rune."); return false; } - if (!altar.isOurania() && !rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need pure essence to craft this rune."); + if (!altar.isOurania() && !rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE) && !player.getInventory().containsItem(SOFT_CLAY)) { + player.getPacketDispatch().sendMessage("You need pure essence to craft this rune, or soft clay to craft teleport tablets."); return false; } - if (!altar.isOurania() && rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE) && !player.getInventory().containsItem(RUNE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need rune essence or pure essence in order to craft this rune."); + if (!altar.isOurania() && rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE) && !player.getInventory().containsItem(RUNE_ESSENCE) && !player.getInventory().containsItem(SOFT_CLAY)) { + player.getPacketDispatch().sendMessage("You need rune essence or pure essence in order to craft this rune, or soft clay to craft teleport tablets."); return false; } if (altar.isOurania() && !player.getInventory().containsItem(PURE_ESSENCE)) { @@ -160,6 +161,7 @@ public final class RuneCraftPulse extends SkillPulse { @Override public boolean reward() { if (!combination) { + craftTablet(); craft(); } else { combine(); @@ -268,6 +270,33 @@ public final class RuneCraftPulse extends SkillPulse { } } + /** + * Method used to craft tablets. Custom for Snowscape + */ + private final void craftTablet() { + int amount = player.getInventory().getAmount(new Item(1761)); + Item clay = new Item(1761, amount); + Item tablet = null; + if (altar == Altar.AIR) { tablet = new Item(13599, amount); } + if (altar == Altar.MIND) { tablet = new Item(13600, amount); } + if (altar == Altar.WATER) { tablet = new Item(13601, amount); } + if (altar == Altar.EARTH) { tablet = new Item(13602, amount); } + if (altar == Altar.FIRE) { tablet = new Item(13603, amount); } + if (altar == Altar.BODY) { tablet = new Item(13604, amount); } + if (altar == Altar.COSMIC) { tablet = new Item(13605, amount); } + if (altar == Altar.CHAOS) { tablet = new Item(13606, amount); } + if (altar == Altar.ASTRAL) { tablet = new Item(13611, amount); } + if (altar == Altar.NATURE) { tablet = new Item(13607, amount); } + if (altar == Altar.LAW) { tablet = new Item(13608, amount); } + if (altar == Altar.DEATH) { tablet = new Item(13609, amount); } + if (altar == Altar.BLOOD) { tablet = new Item(13610, amount); } + if (altar == Altar.SOUL) { tablet = new Item(13598, amount); } + if (tablet != null && player.getInventory().remove(clay)) { + player.getInventory().add(tablet); + player.getPacketDispatch().sendMessage("You bind the temple's power into teleport tablets."); + } + } + /** * Checks if the player has the spell imbue. * From 78847c2415a9febcda5d50be35b1f680a65feb09 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 3 Nov 2024 18:44:48 -0700 Subject: [PATCH 053/306] Ourania altar now gives multiple runes per essence, the same as all other altars. --- .../content/global/skill/runecrafting/RuneCraftPulse.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index b5e2745b6..edd7a05e1 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -179,7 +179,7 @@ public final class RuneCraftPulse extends SkillPulse { int total = 0; for(int j = 0; j < amount; j++) { // since getMultiplier is stochastic, roll `amount` independent copies - total += getMultiplier(); + total += getMultiplier(rune); } Item i = new Item(rune.getRune().getId(), total); @@ -229,7 +229,7 @@ public final class RuneCraftPulse extends SkillPulse { } } player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * 2, true); - Item runeItem = rune.getRune(); + Item runeItem = new Item(rune.getRune().getId(),getMultiplier(rune)); player.getInventory().add(runeItem); } } @@ -347,10 +347,12 @@ public final class RuneCraftPulse extends SkillPulse { * * @return the amount. */ - public int getMultiplier() { + public int getMultiplier(Rune rune) { + /* if (altar.isOurania()) { return 1; } + */ int rcLevel = player.getSkills().getLevel(Skills.RUNECRAFTING); int runecraftingFormulaRevision = ServerConstants.RUNECRAFTING_FORMULA_REVISION; boolean lumbridgeDiary = player.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE).isComplete(1); From 2abf5405159444ddd78e59f4f7412e6ae54822a5 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 3 Nov 2024 18:54:51 -0700 Subject: [PATCH 054/306] Added Runecrafting Guild Teleport tablet (teleports to Soul Altar) --- Server/src/main/content/global/handlers/item/TeleTabsListener.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt index 21a291360..f04b421f8 100644 --- a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt +++ b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt @@ -32,6 +32,7 @@ class TeleTabsListener : InteractionListener { LUMBRIDGE_TELEPORT(8008, Location.create(3222, 3218, 0), 41.0), MIND_ALTAR_TELEPORT(13600, Location.create(2979, 3510, 0), 0.0), NATURE_ALTAR_TELEPORT(13607, Location.create(2868, 3013, 0), 0.0), + RUNECRAFTING_GUILD_TELEPORT(13598, Location.create(2836, 3285, 0), 0.0), VARROCK_TELEPORT(8007, Location.create(3212, 3423, 0), 35.00), WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00), WATER_ALTAR_TELEPORT(13601, Location.create(3182, 3162, 0), 0.0); From d74d83b2ecbc9ac267a6d388bc03d0c2e03dee6c Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 06:13:23 -0700 Subject: [PATCH 055/306] Fixed missing dependency for Soul Rift teleport --- Server/src/main/content/global/skill/runecrafting/Altar.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/global/skill/runecrafting/Altar.java b/Server/src/main/content/global/skill/runecrafting/Altar.java index 5bb2f0794..53f4773b0 100644 --- a/Server/src/main/content/global/skill/runecrafting/Altar.java +++ b/Server/src/main/content/global/skill/runecrafting/Altar.java @@ -6,6 +6,8 @@ import core.game.node.scenery.Scenery; import static core.api.ContentAPIKt.hasRequirement; +import core.game.world.map.Location; + /** * Represents an altar an it's relative information(corresponding ruin, etc) * @author 'Vexia From 82681e8303198a073f663ff1ae2d514dedb05c04 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:18:39 -0700 Subject: [PATCH 056/306] Changed Runecrafting Guild Teleport tablet to the unused Telekinetic Grab tablet --- .../src/main/content/global/handlers/item/TeleTabsListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt index f04b421f8..4a3a0bf75 100644 --- a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt +++ b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt @@ -32,7 +32,7 @@ class TeleTabsListener : InteractionListener { LUMBRIDGE_TELEPORT(8008, Location.create(3222, 3218, 0), 41.0), MIND_ALTAR_TELEPORT(13600, Location.create(2979, 3510, 0), 0.0), NATURE_ALTAR_TELEPORT(13607, Location.create(2868, 3013, 0), 0.0), - RUNECRAFTING_GUILD_TELEPORT(13598, Location.create(2836, 3285, 0), 0.0), + TELEKINETIC_GRAB(8022, Location.create(2836, 3285, 0), 0.0), VARROCK_TELEPORT(8007, Location.create(3212, 3423, 0), 35.00), WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00), WATER_ALTAR_TELEPORT(13601, Location.create(3182, 3162, 0), 0.0); From 845a00079b2cb1cfc24be7f4de85b48b69ea0986 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:19:38 -0700 Subject: [PATCH 057/306] Changed Soul Altar to use the Telekinetic Grab tablet instead of the Runecrafting Guild tablet --- .../main/content/global/skill/runecrafting/RuneCraftPulse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index edd7a05e1..aff74d903 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -290,7 +290,7 @@ public final class RuneCraftPulse extends SkillPulse { if (altar == Altar.LAW) { tablet = new Item(13608, amount); } if (altar == Altar.DEATH) { tablet = new Item(13609, amount); } if (altar == Altar.BLOOD) { tablet = new Item(13610, amount); } - if (altar == Altar.SOUL) { tablet = new Item(13598, amount); } + if (altar == Altar.SOUL) { tablet = new Item(8022, amount); } if (tablet != null && player.getInventory().remove(clay)) { player.getInventory().add(tablet); player.getPacketDispatch().sendMessage("You bind the temple's power into teleport tablets."); From 17ac2ab4da965278d235d25383a50579c588185d Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:30:28 -0700 Subject: [PATCH 058/306] Added Death and Blood Talismans to the drop tables of abyssal creatures --- Server/data/configs/drop_tables.json | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 1a8525af4..87af56441 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -29532,6 +29532,18 @@ "id": "1438", "maxAmount": "1" }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1456", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1450", + "maxAmount": "1" + }, { "minAmount": "1", "weight": "25.0", @@ -29704,6 +29716,18 @@ "id": "1438", "maxAmount": "1" }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1456", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1450", + "maxAmount": "1" + }, { "minAmount": "1", "weight": "25.0", @@ -29876,6 +29900,18 @@ "id": "1438", "maxAmount": "1" }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1456", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "25.0", + "id": "1450", + "maxAmount": "1" + }, { "minAmount": "1", "weight": "25.0", From 4912b39831c50bc2d77b99ff454b86e8754fdb69 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:39:29 -0700 Subject: [PATCH 059/306] Added additional stats to Monster Examine and removed the coin cost from Plank Make. --- .../skill/magic/lunar/LunarListeners.kt | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 40e27939a..03286c62f 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -372,16 +372,26 @@ class LunarListeners : SpellListener("lunar"), Commands { setDelay(player, false) openSingleTab(player, Components.DREAM_MONSTER_STAT_522) - setInterfaceText(player, "Monster name : ${npc.definition.name}", Components.DREAM_MONSTER_STAT_522, 0) - setInterfaceText(player, "Combat Level : ${npc.definition.combatLevel}", Components.DREAM_MONSTER_STAT_522, 1) - setInterfaceText(player, "Hitpoints : ${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0}", Components.DREAM_MONSTER_STAT_522, 2) - setInterfaceText(player, "Max hit : ${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}", Components.DREAM_MONSTER_STAT_522, 3) + var bonuses = npc.properties.bonuses + setInterfaceText(player, "Monster name: ${npc.definition.name} (${npc.definition.combatLevel})", Components.DREAM_MONSTER_STAT_522, 0) + setInterfaceText(player, """ +Att:${npc.definition.handlers[NPCConfigParser.ATTACK_LEVEL] ?: 0} +Str:${npc.definition.handlers[NPCConfigParser.STRENGTH_LEVEL] ?: 0} +Ranged:${npc.definition.handlers[NPCConfigParser.RANGE_LEVEL] ?: 0} +Magic:${npc.definition.handlers[NPCConfigParser.MAGIC_LEVEL] ?: 0}""", Components.DREAM_MONSTER_STAT_522, 1) + setInterfaceText(player, """ +Defence:${npc.definition.handlers[NPCConfigParser.DEFENCE_LEVEL] ?: 0} +HP:${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0} +Max hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Components.DREAM_MONSTER_STAT_522, 2) + setInterfaceText(player, "${bonuses[0]},${bonuses[1]},${bonuses[2]},${bonuses[3]},${bonuses[4]}, ${bonuses[5]},${bonuses[6]},${bonuses[7]},${bonuses[8]},${bonuses[9]}", Components.DREAM_MONSTER_STAT_522, 3) val poisonStatus = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISON_IMMUNE,false) == true){ - "This creature is immune to poison." - } else "This creature is not immune to poison." - - setInterfaceText(player, poisonStatus, Components.DREAM_MONSTER_STAT_522, 4) + "Immune to poison. " + } else "" + val poisonStatus2 = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISONOUS,false) == true){ + "Poisonous." + } else "" + setInterfaceText(player, poisonStatus + poisonStatus2, Components.DREAM_MONSTER_STAT_522, 4) } // Level 67 @@ -667,10 +677,12 @@ class LunarListeners : SpellListener("lunar"), Commands { sendMessage(player, "You need to use this spell on logs.") return } + /* if (amountInInventory(player, Items.COINS_995) < plankType.price || !removeItem(player, Item(Items.COINS_995, plankType.price))) { sendMessage(player, "You need ${plankType.price} coins to convert that log into a plank.") return } + */ lock(player, 3) setDelay(player, false) visualizeSpell(player, Animations.LUNAR_SPELLBOOK_PLANK_MAKE_6298, Graphics.LUNAR_SPELLBOOK_PLANK_MAKE_1063, 120, Sounds.LUNAR_MAKE_PLANK_3617) From 90c80fbd8e3be38b1247a9a5cf3fdb1e147ac7fd Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:40:36 -0700 Subject: [PATCH 060/306] revert 4912b39831c50bc2d77b99ff454b86e8754fdb69 revert Added additional stats to Monster Examine and removed the coin cost from Plank Make. --- .../skill/magic/lunar/LunarListeners.kt | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 03286c62f..40e27939a 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -372,26 +372,16 @@ class LunarListeners : SpellListener("lunar"), Commands { setDelay(player, false) openSingleTab(player, Components.DREAM_MONSTER_STAT_522) - var bonuses = npc.properties.bonuses - setInterfaceText(player, "Monster name: ${npc.definition.name} (${npc.definition.combatLevel})", Components.DREAM_MONSTER_STAT_522, 0) - setInterfaceText(player, """ -Att:${npc.definition.handlers[NPCConfigParser.ATTACK_LEVEL] ?: 0} -Str:${npc.definition.handlers[NPCConfigParser.STRENGTH_LEVEL] ?: 0} -Ranged:${npc.definition.handlers[NPCConfigParser.RANGE_LEVEL] ?: 0} -Magic:${npc.definition.handlers[NPCConfigParser.MAGIC_LEVEL] ?: 0}""", Components.DREAM_MONSTER_STAT_522, 1) - setInterfaceText(player, """ -Defence:${npc.definition.handlers[NPCConfigParser.DEFENCE_LEVEL] ?: 0} -HP:${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0} -Max hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Components.DREAM_MONSTER_STAT_522, 2) - setInterfaceText(player, "${bonuses[0]},${bonuses[1]},${bonuses[2]},${bonuses[3]},${bonuses[4]}, ${bonuses[5]},${bonuses[6]},${bonuses[7]},${bonuses[8]},${bonuses[9]}", Components.DREAM_MONSTER_STAT_522, 3) + setInterfaceText(player, "Monster name : ${npc.definition.name}", Components.DREAM_MONSTER_STAT_522, 0) + setInterfaceText(player, "Combat Level : ${npc.definition.combatLevel}", Components.DREAM_MONSTER_STAT_522, 1) + setInterfaceText(player, "Hitpoints : ${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0}", Components.DREAM_MONSTER_STAT_522, 2) + setInterfaceText(player, "Max hit : ${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}", Components.DREAM_MONSTER_STAT_522, 3) val poisonStatus = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISON_IMMUNE,false) == true){ - "Immune to poison. " - } else "" - val poisonStatus2 = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISONOUS,false) == true){ - "Poisonous." - } else "" - setInterfaceText(player, poisonStatus + poisonStatus2, Components.DREAM_MONSTER_STAT_522, 4) + "This creature is immune to poison." + } else "This creature is not immune to poison." + + setInterfaceText(player, poisonStatus, Components.DREAM_MONSTER_STAT_522, 4) } // Level 67 @@ -677,12 +667,10 @@ Max hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Compone sendMessage(player, "You need to use this spell on logs.") return } - /* if (amountInInventory(player, Items.COINS_995) < plankType.price || !removeItem(player, Item(Items.COINS_995, plankType.price))) { sendMessage(player, "You need ${plankType.price} coins to convert that log into a plank.") return } - */ lock(player, 3) setDelay(player, false) visualizeSpell(player, Animations.LUNAR_SPELLBOOK_PLANK_MAKE_6298, Graphics.LUNAR_SPELLBOOK_PLANK_MAKE_1063, 120, Sounds.LUNAR_MAKE_PLANK_3617) From 86913bf75f96e2b6d78427e884b846384a535118 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 19:42:31 -0700 Subject: [PATCH 061/306] Added additional stats to Monster Examine and removed the coin cost from Plank Make. Correctly done on the dev branch this time. --- .../skill/magic/lunar/LunarListeners.kt | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 40e27939a..ca302bfba 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -372,16 +372,26 @@ class LunarListeners : SpellListener("lunar"), Commands { setDelay(player, false) openSingleTab(player, Components.DREAM_MONSTER_STAT_522) - setInterfaceText(player, "Monster name : ${npc.definition.name}", Components.DREAM_MONSTER_STAT_522, 0) - setInterfaceText(player, "Combat Level : ${npc.definition.combatLevel}", Components.DREAM_MONSTER_STAT_522, 1) - setInterfaceText(player, "Hitpoints : ${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0}", Components.DREAM_MONSTER_STAT_522, 2) - setInterfaceText(player, "Max hit : ${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}", Components.DREAM_MONSTER_STAT_522, 3) + var bonuses = npc.properties.bonuses + setInterfaceText(player, "Monster name: ${npc.definition.name} (${npc.definition.combatLevel})", Components.DREAM_MONSTER_STAT_522, 0) + setInterfaceText(player, """ +Att:${npc.definition.handlers[NPCConfigParser.ATTACK_LEVEL] ?: 0} +Str:${npc.definition.handlers[NPCConfigParser.STRENGTH_LEVEL] ?: 0} +Ranged:${npc.definition.handlers[NPCConfigParser.RANGE_LEVEL] ?: 0} +Magic:${npc.definition.handlers[NPCConfigParser.MAGIC_LEVEL] ?: 0}""", Components.DREAM_MONSTER_STAT_522, 1) + setInterfaceText(player, """ +Defence:${npc.definition.handlers[NPCConfigParser.DEFENCE_LEVEL] ?: 0} +HP:${npc.definition.handlers[NPCConfigParser.LIFEPOINTS] ?: 0} +Max-hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Components.DREAM_MONSTER_STAT_522, 2) + setInterfaceText(player, "${bonuses[0]},${bonuses[1]},${bonuses[2]},${bonuses[3]},${bonuses[4]}, ${bonuses[5]},${bonuses[6]},${bonuses[7]},${bonuses[8]},${bonuses[9]}", Components.DREAM_MONSTER_STAT_522, 3) val poisonStatus = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISON_IMMUNE,false) == true){ - "This creature is immune to poison." - } else "This creature is not immune to poison." - - setInterfaceText(player, poisonStatus, Components.DREAM_MONSTER_STAT_522, 4) + "Immune to poison. " + } else "" + val poisonStatus2 = if(npc.definition.handlers.getOrDefault(NPCConfigParser.POISONOUS,false) == true){ + "Poisonous." + } else "" + setInterfaceText(player, poisonStatus + poisonStatus2, Components.DREAM_MONSTER_STAT_522, 4) } // Level 67 @@ -667,10 +677,12 @@ class LunarListeners : SpellListener("lunar"), Commands { sendMessage(player, "You need to use this spell on logs.") return } + /* if (amountInInventory(player, Items.COINS_995) < plankType.price || !removeItem(player, Item(Items.COINS_995, plankType.price))) { sendMessage(player, "You need ${plankType.price} coins to convert that log into a plank.") return } + */ lock(player, 3) setDelay(player, false) visualizeSpell(player, Animations.LUNAR_SPELLBOOK_PLANK_MAKE_6298, Graphics.LUNAR_SPELLBOOK_PLANK_MAKE_1063, 120, Sounds.LUNAR_MAKE_PLANK_3617) From 9295c91a7d3e08e89e4f35b50d5cdfe469dc94a4 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 4 Nov 2024 20:37:26 -0700 Subject: [PATCH 062/306] Plank Make now automatically recasts on matching logs --- .../skill/magic/lunar/LunarListeners.kt | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index ca302bfba..ba2483cc7 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -677,12 +677,28 @@ Max-hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Compone sendMessage(player, "You need to use this spell on logs.") return } - /* + player.pulseManager.run(object : Pulse() { + var counter = 0 + override fun pulse(): Boolean { + removeAttribute(player, "spell:runes") + if (amountInInventory(player, item.id) == 0 ) + return true + requires(player, 86, arrayOf(Item(Items.ASTRAL_RUNE_9075, 2), Item(Items.NATURE_RUNE_561, 1), Item(Items.EARTH_RUNE_557, 15))) + if(removeItem(player, item.id) && addItem(player, plankType.plank.id)) { + removeRunes(player, false) + if (counter % 6 == 0) + visualizeSpell(player, Animations.LUNAR_SPELLBOOK_PLANK_MAKE_6298, Graphics.LUNAR_SPELLBOOK_PLANK_MAKE_1063, 120, Sounds.LUNAR_MAKE_PLANK_3617) + addXP(player, 90.0) + } + counter++ + return false + } + }) + /* Vanilla Spell if (amountInInventory(player, Items.COINS_995) < plankType.price || !removeItem(player, Item(Items.COINS_995, plankType.price))) { sendMessage(player, "You need ${plankType.price} coins to convert that log into a plank.") return } - */ lock(player, 3) setDelay(player, false) visualizeSpell(player, Animations.LUNAR_SPELLBOOK_PLANK_MAKE_6298, Graphics.LUNAR_SPELLBOOK_PLANK_MAKE_1063, 120, Sounds.LUNAR_MAKE_PLANK_3617) @@ -690,6 +706,7 @@ Max-hit:${npc.getSwingHandler(false).calculateHit(npc, player, 1.0)}""", Compone replaceSlot(player, item.slot, plankType.plank) addXP(player, 90.0) showMagicTab(player) + */ } // Level 91 From 010cd584609fc64e4c7179937a92b66639d56ac8 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 5 Nov 2024 19:29:58 -0700 Subject: [PATCH 063/306] Updated server config to desired settings --- Server/worldprops/default.conf | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index 6024160fe..063fb5cbc 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -11,18 +11,18 @@ secret_key = "2009scape_development" write_logs = true msip = "127.0.0.1" #preload the map (Increases memory usage by 2GB but makes game ticks smoother) -preload_map = false +preload_map = true #--------Note: If both of the below are false, no database is required to run the server.-------------- #true = login requires password to be correct, passwords are hashed before stored. false = login does not care about the correctness of a password. -use_auth = false #NOTE: THIS MUST BE SET TO TRUE IN PRODUCTION! +use_auth = true #NOTE: THIS MUST BE SET TO TRUE IN PRODUCTION! #true - account data (credits, playtime, etc) is persisted, false - account data is purely temporary #NOTE: this does not affect actual save data, like stats, inventory, etc. -persist_accounts = false #NOTE: THIS MUST BE SET TO TRUE IN PRODUCTION! +persist_accounts = true #NOTE: THIS MUST BE SET TO TRUE IN PRODUCTION! noauth_default_admin = true #NOTE: If we are not using auth, this determines whether or not players are admins by default. #------------------------------------------------------------------------------------------------------ #The limit on how many different accounts a player can log into per day. -daily_accounts_per_ip = 3 -watchdog_enabled = true +daily_accounts_per_ip = 30 +watchdog_enabled = false connectivity_check_url = "https://google.com,https://2009scape.org" connectivity_timeout = 500 @@ -44,21 +44,21 @@ grafana_log_ttl_days = 7 [world] -name = "2009Scape" +name = "SnowScape" #name used for announcements of bots selling items on the GE -name_ge = "2009Scape" -debug = true -dev = true +name_ge = "SnowScape" +debug = false +dev = false start_gui = false -daily_restart = false +daily_restart = true #world number world_id = "1" country_id = "0" members = true #activity as displayed on the world list -activity = "2009Scape Classic." +activity = "SnowScape" pvp = false -default_xp_rate = 5.0 +default_xp_rate = 1.0 allow_slayer_reroll = false #enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already. enable_default_clan = true @@ -81,14 +81,14 @@ enable_doubling_money_scammers = true wild_pvp_enabled = true jad_practice_enabled = true #minimum HA value for announcements of bots selling on ge -ge_announcement_limit = 500 -enable_castle_wars = false +ge_announcement_limit = 500000 +enable_castle_wars = true personalized_shops = true -bots_influence_ge_price = true +bots_influence_ge_price = false #verbose cutscene logging (for cutscenes in the new system) verbose_cutscene = false #show the rules the first time a player logs in -show_rules = true +show_rules = false #the number of revenants active at a time revenant_population = 30 #enable auto-buy/auto-sell on the GE. @@ -100,7 +100,7 @@ better_dfs = true #new player announcement new_player_announcement = true #enables holiday random events (no effect on normal random events) -holiday_event_randoms = true +holiday_event_randoms = false #force holiday randoms (can only force one at a time) force_halloween_randoms = false force_christmas_randoms = false From 54d755b12d5dc86d7631e3a894b1bc5109131a97 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 5 Nov 2024 19:48:25 -0700 Subject: [PATCH 064/306] Enabled quick banking --- Server/worldprops/default.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index 063fb5cbc..fd25dd94c 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -108,6 +108,8 @@ force_christmas_randoms = false runecrafting_formula_revision = 581 #enable the enhanced deep wilderness, where the area past the members' fence applies a red skull that boosts brawler/pvp drop rates enhanced_deep_wilderness = true +#enable opening the bank on left-clicking the booth, instead of starting dialogue with the banker +bank_booth_quick_open = true [paths] #path to the data folder, which contains the cache subfolder and such From 1ef61d8c33328800537ae911e60be6e133187662 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 5 Nov 2024 20:00:47 -0700 Subject: [PATCH 065/306] Reduced Magic Training Arena costs to 1/5th --- Server/src/main/content/minigame/mta/MTAShop.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/minigame/mta/MTAShop.java b/Server/src/main/content/minigame/mta/MTAShop.java index beb64a1b2..d8db649a8 100644 --- a/Server/src/main/content/minigame/mta/MTAShop.java +++ b/Server/src/main/content/minigame/mta/MTAShop.java @@ -32,8 +32,8 @@ public class MTAShop { /** * The prices. */ - private static final int[][] PRICES = new int[][] { { 30, 30, 300, 30 }, { 60, 60, 600, 60 }, { 150, 200, 1500, 150 }, { 240, 240, 2400, 240 }, { 400, 450, 4000, 400 }, { 350, 400, 3000, 350 }, { 120, 120, 1200, 120 }, { 175, 225, 1500, 175 }, { 450, 500, 5000, 450 }, { 500, 550, 6000, 500 }, { 200, 300, 2000, 200 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 0, 0, 5, 0 }, { 0, 1, 5, 1 }, { 0, 1, 0, 1 }, { 2, 1, 20, 1 }, { 2, 0, 0, 0 }, { 2, 2, 25, 2 }, { 2, 2, 25, 2 } }; - + private static final int[][] PRICES = new int[][] { { 6, 6, 60, 6 }, { 12, 12, 120, 12 }, { 30, 40, 300, 30 }, { 48, 48, 480, 48 }, { 80, 90, 800, 80 }, { 70, 80, 600, 70 }, { 24, 24, 240, 24 }, { 35, 45, 300, 35 }, { 90, 100, 1000, 90 }, { 100, 110, 1200, 100 }, { 40, 60, 400, 40 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 1, 1, 15, 1 }, { 0, 0, 5, 0 }, { 0, 1, 5, 1 }, { 0, 1, 0, 1 }, { 2, 1, 20, 1 }, { 2, 0, 0, 0 }, { 2, 2, 25, 2 }, { 2, 2, 25, 2 } }; + /** * The container. */ From 4cd703097c576f2af7bfd46b476aa118220340b4 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 6 Nov 2024 11:03:21 -0700 Subject: [PATCH 066/306] Increased Pest Control reward points by 5x (10, 15, and 25 for each boat) --- .../minigame/pestcontrol/PestControlActivityPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java b/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java index f1fb680a0..396d22355 100644 --- a/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java +++ b/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java @@ -133,14 +133,14 @@ public final class PestControlActivityPlugin extends ActivityPlugin { // type, // default } else if (success && p.getAttribute("pc_zeal", 0) >= 50) { - int amount = type.ordinal() + 2; + int amount = type.ordinal() == 0 ? 10 : type.ordinal() == 1 ? 15 : 25; p.getSavedData().getActivityData().increasePestPoints(amount); Item coins = new Item(995, p.getProperties().getCurrentCombatLevel() * 10); if (!p.getInventory().add(coins)) { GroundItemManager.create(coins, p); } // default, type, name - p.getDialogueInterpreter().open(3781, true, 1, type.ordinal() == 0 ? "two" : type.ordinal() == 1 ? "three" : "four"); + p.getDialogueInterpreter().open(3781, true, 1, type.ordinal() == 0 ? "ten" : type.ordinal() == 1 ? "fifteen" : "twenty-five"); } else { // default type, default p.getDialogueInterpreter().open(3781, true, 2, true); From bbaa4bbdbea730dfa0dce2a2264e804dda08ba2b Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 6 Nov 2024 11:06:23 -0700 Subject: [PATCH 067/306] Fixed exp reward calc and reduced to one fifth The reward formula double-dipped with exp multipliers. Corrected the formula to match the original 2009 version, then reduced to 1/5 to account for the increased points given for each round. The increased points are meant to reduce the grind for the items, but not the purchasable exp. --- .../minigame/pestcontrol/reward/PCRewardInterface.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java b/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java index 9dc6aab16..1fd3c5ca7 100644 --- a/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java +++ b/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java @@ -192,13 +192,13 @@ public final class PCRewardInterface extends ComponentPlugin { */ public static double calculateExperience(final Player player, final int skillId) { int level = player.getSkills().getStaticLevel(skillId); - double divideBy = 30;//17.5-33 ideal range + double multiplier = 35; if (skillId == Skills.PRAYER) { - divideBy = 67;// 34-75 ideal range + multiplier = 18; } else if (skillId == Skills.MAGIC || skillId == Skills.RANGE) { - divideBy = 29;//19.1-31 ideal range + multiplier = 32; } - return (int) ((level * level) / divideBy) * (player.getSkills().experienceMultiplier / 2); + return (int) ((level * level) / 600) * (multiplier) / 5; } /** From 6305e2a718add434d083bda5d802a99885cbfd79 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 6 Nov 2024 13:36:24 -0700 Subject: [PATCH 068/306] Rewrote Alchemy spells to use pulse, repeating up to 30 times --- .../skill/magic/modern/ModernListeners.kt | 54 ++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 262824d2c..0d35ef56a 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -30,6 +30,8 @@ import org.rs09.consts.Items import org.rs09.consts.Scenery import org.rs09.consts.Sounds +import core.game.system.task.Pulse + class ModernListeners : SpellListener("modern"){ override fun defineListeners() { onCast(Modern.HOME_TELEPORT, NONE){ player, _ -> @@ -232,25 +234,41 @@ class ModernListeners : SpellListener("modern"){ player.pulseManager.clear() } - if (explorersRing) { - visualize(player, LOW_ALCH_ANIM, EXPLORERS_RING_GFX) - } else { - val weapon = getItemFromEquipment(player, EquipmentSlot.WEAPON) - if (weapon != null && weapon.id in MagicStaff.FIRE_RUNE.staves) { - visualize(player, if (high) HIGH_ALCH_STAFF_ANIM else LOW_ALCH_STAFF_ANIM, if (high) HIGH_ALCH_STAFF_GFX else LOW_ALCH_STAFF_GFX) - } else { - visualize(player, if (high) HIGH_ALCH_ANIM else LOW_ALCH_ANIM, if (high) HIGH_ALCH_GFX else LOW_ALCH_GFX) + player.pulseManager.run(object : Pulse(){ + var counter = 0 + override fun pulse(): Boolean { + if (amountInInventory(player, item.id) == 0 || counter >= 150) + return true + removeAttribute(player, "spell:runes") + if (counter % 5 == 0) { + if (explorersRing) { + visualize(player, LOW_ALCH_ANIM, EXPLORERS_RING_GFX) + } else { + val weapon = getItemFromEquipment(player, EquipmentSlot.WEAPON) + if (weapon != null && weapon.id in MagicStaff.FIRE_RUNE.staves) { + visualize(player, if (high) HIGH_ALCH_STAFF_ANIM else LOW_ALCH_STAFF_ANIM, if (high) HIGH_ALCH_STAFF_GFX else LOW_ALCH_STAFF_GFX) + } else { + visualize(player, if (high) HIGH_ALCH_ANIM else LOW_ALCH_ANIM, if (high) HIGH_ALCH_GFX else LOW_ALCH_GFX) + } + } + playAudio(player, if (high) Sounds.HIGH_ALCHEMY_97 else Sounds.LOW_ALCHEMY_98) + player.dispatch(ItemAlchemizationEvent(item.id, high)) + if (high) + requires(player,55, arrayOf(Item(Items.FIRE_RUNE_554,5),Item(Items.NATURE_RUNE_561,1))) + else + requires(player,21, arrayOf(Item(Items.FIRE_RUNE_554,3),Item(Items.NATURE_RUNE_561))) + removeRunes(player, false) + addXP(player, if (high) 65.0 else 31.0) + if (player.inventory.remove(Item(item.id, 1)) && coins.amount > 0) { + player.inventory.add(coins) + } + //showMagicTab(player) + setDelay(player, 5) + } + counter++ + return false } - } - playAudio(player, if (high) Sounds.HIGH_ALCHEMY_97 else Sounds.LOW_ALCHEMY_98) - player.dispatch(ItemAlchemizationEvent(item.id, high)) - if (player.inventory.remove(Item(item.id, 1)) && coins.amount > 0) { - player.inventory.add(coins) - } - removeRunes(player) - addXP(player, if (high) 65.0 else 31.0) - showMagicTab(player) - setDelay(player, 5) + }) return true } From 8094465579da7bcecd838214375a913c0088e206 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 7 Nov 2024 10:02:10 -0700 Subject: [PATCH 069/306] Added ability to toggle bonecrusher function on blessed sickle When using "cast bloom", the sickle will grow nearby fungus as usual. If no fungus are grown, it will instead toggle the bone crusher attribute. --- .../region/morytania/quest/naturespirit/NSUtils.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NSUtils.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NSUtils.kt index 03263c6c4..c47754946 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NSUtils.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NSUtils.kt @@ -85,10 +85,12 @@ object NSUtils { fun castBloom(player: Player): Boolean{ var success = false val region = forId(player.location.regionId) + /* if (player.skills.prayerPoints < 1) { player.packetDispatch.sendMessage("You don't have enough prayer points to do this.") return false } + */ handleVisuals(player) val locs = player.location.surroundingTiles for (o in locs) { @@ -114,6 +116,17 @@ object NSUtils { } } } + if (success) { + player.skills.decrementPrayerPoints(RandomFunction.random(1, 3).toDouble()) + } else { + if (getAttribute(player, "bonecrusher:enabled", false)) { + setAttribute(player, "/save:bonecrusher:enabled",false) + player.packetDispatch.sendMessage("Automatic Bone Burial: Disabled.") + } else { + setAttribute(player, "/save:bonecrusher:enabled",true) + player.packetDispatch.sendMessage("Automatic Bone Burial: Enabled.") + } + } return success } @@ -122,7 +135,6 @@ object NSUtils { * animation. */ private fun handleVisuals(player: Player) { - player.skills.decrementPrayerPoints(RandomFunction.random(1, 3).toDouble()) playAudio(player, Sounds.CAST_BLOOM_1493) val AROUND_YOU = player.location.surroundingTiles for (location in AROUND_YOU) { From d4da75e6abe34de54a0879438ff32cfcafce9ac5 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 7 Nov 2024 10:05:10 -0700 Subject: [PATCH 070/306] Added bonecrusher functionality If the blessed silver sickle is in the player inventory (not equipped) and they have enabled the feature by using "cast bloom", bones will not drop and instead the player will directly get the prayer experience. --- .../src/main/core/game/node/entity/npc/drop/NPCDropTables.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index e4e1cd3b6..5a5db3d49 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -206,7 +206,7 @@ public final class NPCDropTables { if (bone == null) { return false; } - if (!player.getGlobalData().isEnableBoneCrusher()) { + if (!player.getInventory().containsItem(new Item(2963, 1)) || !player.getAttribute("bonecrusher:enabled", false)) { return false; } player.getSkills().addExperience(Skills.PRAYER, item.getAmount() * bone.getExperience()); From 4b5687b8ab328a703e4181fad6a60f7d7c6742e1 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 7 Nov 2024 11:53:41 -0700 Subject: [PATCH 071/306] Added small slayer exp drop even when not on slayer task --- Server/src/main/content/global/skill/slayer/SlayerManager.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/slayer/SlayerManager.kt b/Server/src/main/content/global/skill/slayer/SlayerManager.kt index 5542a7777..1bcf56803 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerManager.kt +++ b/Server/src/main/content/global/skill/slayer/SlayerManager.kt @@ -101,9 +101,11 @@ class SlayerManager(val player: Player? = null) : LoginListener, PersistPlayer, val player = entity as? Player ?: return val slayer = getInstance(player) val flags = slayer.flags + var xp = npc.skills.maximumLifepoints.toDouble() + rewardXP(player, Skills.SLAYER, xp/3) if (slayer.hasTask() && npc.id in slayer.task!!.npcs) { - var xp = npc.skills.maximumLifepoints.toDouble() + if (slayer.task!!.dragon && inEquipment(player, Items.DRAGON_SLAYER_GLOVES_12862)) { xp *= 1.15 FOGGlovesManager.updateCharges(player) From 1f538d2976ddf3aa291015945fbe298ab460e81c Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 7 Nov 2024 15:56:58 -0700 Subject: [PATCH 072/306] Added agility exp gain when running --- Server/src/main/core/game/node/entity/impl/WalkingQueue.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java index fbd9d2e36..f20768b70 100644 --- a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java +++ b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java @@ -193,6 +193,9 @@ public final class WalkingQueue { if (hasTimerActive(player, "hamstrung")) { rate *= 4; } + //Snowscape custom: gain agility exp when running. getLevel returns int so we convert to double for the math + double experience = (Double.valueOf(player.getSkills().getLevel(Skills.AGILITY)) + 10)/50; + player.getSkills().addExperience(Skills.AGILITY, experience); return rate; } From 7779d03654e6fa06b94e2ca4819eee90d373f748 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 15:42:16 -0700 Subject: [PATCH 073/306] Added Beast of Burden Looting Mob drops will go to a beast of burden inventory if there is room. The Pack Yak, if it has Winter Storage scrolls in its inventory, will instead send drops straight to the bank at the cost of one scroll. --- .../node/entity/npc/drop/NPCDropTables.java | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 5a5db3d49..7421228f7 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -23,6 +23,11 @@ import core.api.utils.NPCDropTable; import core.game.ge.GrandExchange; import core.game.world.repository.Repository; +import content.global.skill.summoning.familiar.BurdenBeast; +import content.global.skill.summoning.familiar.Forager; +import content.global.skill.summoning.SummoningPouch; +import content.global.skill.summoning.familiar.PackYakNPC; + import java.util.ArrayList; import java.util.List; @@ -106,9 +111,17 @@ public final class NPCDropTables { item = item.getPlugin().getItem(item, npc); } if (!item.getDefinition().isStackable() && item.getAmount() > 1) { + if (hasValidFamiliar(player)) { + for (int i = 0; i < item.getAmount(); i++) { + if (!addItemFamiliar(player, new Item(item.getId()))) { + GroundItemManager.create(new Item(item.getId()), l, player); + } + } + } else { for (int i = 0; i < item.getAmount(); i++) { GroundItemManager.create(new Item(item.getId()), l, player); } + } return; } announceIfRare(player, item); @@ -121,7 +134,11 @@ public final class NPCDropTables { GroundItemManager.create(item, l); } } else { - GroundItem groundItem = GroundItemManager.create(item, l, getLooter(player, npc, item)); + Player looter = getLooter(player, npc, item); + if (hasValidFamiliar(looter) && addItemFamiliar(looter, item)) { + return; + } + GroundItem groundItem = GroundItemManager.create(item, l, looter); if(player instanceof AIPlayer) { AIRepository.addItem(groundItem); } @@ -134,6 +151,37 @@ public final class NPCDropTables { } } + /** Snowlab custom looting + * Check if the player has a valid familiar that can loot. + * @param player The player + * @return true if they have a valid familiar. + */ + private boolean hasValidFamiliar(Player player) { + if (!(player instanceof AIPlayer) && player.getFamiliarManager().hasFamiliar() && player.getFamiliarManager().getFamiliar().isBurdenBeast() && !(player.getFamiliarManager().getFamiliar() instanceof Forager) && !SummoningPouch.get(player.getFamiliarManager().getFamiliar().getPouchId()).abyssal){ + return true; + } else { + return false; + } + } + /** Snowlab custom looting + * Attempt adding item to familiar inventory. + * @param player The player + * @return true if item was successfully added. + */ + private boolean addItemFamiliar(Player player, Item item) { + if ((player.getFamiliarManager().getFamiliar() instanceof PackYakNPC) && ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().contains(12435, 1) && player.getBank().add(item)) { + ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().remove(new Item(12435, 1)); + player.sendMessage("Your familiar picked up and banked " + item.getAmount() + " " + item.getName() + "."); + return true; + } + if (((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().add(item)) { + player.sendMessage("Your familiar picked up " + item.getAmount() + " " + item.getName() + "."); + return true; + } else { + return false; + } + } + /** * Gets the looting player. * @param player the player. From 8a72ac52dba85bc93e2b12a0572c1531b5cc63d6 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 16:09:13 -0700 Subject: [PATCH 074/306] Changed Summoning shard cost for all pouches to 1 Shards are a pure gold sink, which we don't need. --- .../skill/summoning/SummoningPouch.java | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/SummoningPouch.java b/Server/src/main/content/global/skill/summoning/SummoningPouch.java index b91634318..90a502e6d 100644 --- a/Server/src/main/content/global/skill/summoning/SummoningPouch.java +++ b/Server/src/main/content/global/skill/summoning/SummoningPouch.java @@ -14,27 +14,27 @@ public enum SummoningPouch { /** * Represents a spirit wolf pouch. */ - SPIRIT_WOLF_POUCH(0, 12047, 1, 4.8, 6829, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2859), new Item(12183, 7)), + SPIRIT_WOLF_POUCH(0, 12047, 1, 4.8, 6829, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2859), new Item(12183, 1)), /** * Represents a dreadfowl pouch. */ - DREADFOWL_POUCH(1, 12043, 4, 9.3, 6825, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2138), new Item(12183, 8)), + DREADFOWL_POUCH(1, 12043, 4, 9.3, 6825, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2138), new Item(12183, 1)), /** * Represents a spirit spider pouch. */ - SPIRIT_SPIDER_POUCH(2, 12059, 10, 12.6, 6841, 0.2, 2, false, new Item(12158), new Item(12155), new Item(6291), new Item(12183, 8)), + SPIRIT_SPIDER_POUCH(2, 12059, 10, 12.6, 6841, 0.2, 2, false, new Item(12158), new Item(12155), new Item(6291), new Item(12183, 1)), /** * Represents a thorny snail pouch. */ - THORNY_SNAIL_POUCH(3, 12019, 13, 12.6, 6806, 0.2, 2, false, new Item(12158), new Item(12155), new Item(3363), new Item(12183, 9)), + THORNY_SNAIL_POUCH(3, 12019, 13, 12.6, 6806, 0.2, 2, false, new Item(12158), new Item(12155), new Item(3363), new Item(12183, 1)), /** * Represents a granite crab pouch. */ - GRANITE_CRAB_POUCH(4, 12009, 16, 21.6, 6796, 0.2, 2, false, new Item(12158), new Item(12155), new Item(440), new Item(12183, 7)), + GRANITE_CRAB_POUCH(4, 12009, 16, 21.6, 6796, 0.2, 2, false, new Item(12158), new Item(12155), new Item(440), new Item(12183, 1)), /** * Represents a spirit mosquito pouch. @@ -44,97 +44,97 @@ public enum SummoningPouch { /** * Represents a desrrt wyrm pouch. */ - DESERT_WYRM_POUCH(6, 12049, 18, 31.2, 6831, 0.4, 1, false, new Item(12159), new Item(12155), new Item(1783), new Item(12183, 45)), + DESERT_WYRM_POUCH(6, 12049, 18, 31.2, 6831, 0.4, 1, false, new Item(12159), new Item(12155), new Item(1783), new Item(12183, 1)), /** * Represents a spirit scorpion pouch. */ - SPIRIT_SCORPION_POUCH(7, 12055, 19, 83.2, 6837, 0.9, 2, false, new Item(12160), new Item(12155), new Item(3095), new Item(12183, 57)), + SPIRIT_SCORPION_POUCH(7, 12055, 19, 83.2, 6837, 0.9, 2, false, new Item(12160), new Item(12155), new Item(3095), new Item(12183, 1)), /** * Represents a spirit tz-kih pouch. */ - SPIRIT_TZ_KIH_POUCH(8, 12808, 22, 96.8, 7361, 1.1, 3, false, new Item(12160), new Item(12168), new Item(12155), new Item(12183, 64)), + SPIRIT_TZ_KIH_POUCH(8, 12808, 22, 96.8, 7361, 1.1, 3, false, new Item(12160), new Item(12168), new Item(12155), new Item(12183, 1)), /** * Represents an albino rat pouch. */ - ALBINO_RAT_POUCH(9, 12067, 23, 202.4, 6847, 2.3, 1, false, new Item(12163), new Item(12155), new Item(2134), new Item(12183, 75)), + ALBINO_RAT_POUCH(9, 12067, 23, 202.4, 6847, 2.3, 1, false, new Item(12163), new Item(12155), new Item(2134), new Item(12183, 1)), /** * Represents a spirit kalphite pouch. */ - SPIRIT_KALPHITE_POUCH(10, 12063, 25, 220, 6994, 2.5, 3,false, new Item(12163), new Item(12155), new Item(3138), new Item(12183, 51)), + SPIRIT_KALPHITE_POUCH(10, 12063, 25, 220, 6994, 2.5, 3,false, new Item(12163), new Item(12155), new Item(3138), new Item(12183, 1)), /** * Represents a compost mound pouch. */ - COMPOST_MOUND_POUCH(11, 12091, 28, 49.8, 6871, 0.6, 6, false, new Item(12159), new Item(12155), new Item(6032), new Item(12183, 47)), + COMPOST_MOUND_POUCH(11, 12091, 28, 49.8, 6871, 0.6, 6, false, new Item(12159), new Item(12155), new Item(6032), new Item(12183, 1)), /** * Represents a giant chinchompa pouch. */ - GIANT_CHINCHOMPA_POUCH(12, 12800, 29, 255.2, 7353, 2.9, 1, false, new Item(12163), new Item(12155), new Item(10033), new Item(12183, 84)), + GIANT_CHINCHOMPA_POUCH(12, 12800, 29, 255.2, 7353, 2.9, 1, false, new Item(12163), new Item(12155), new Item(10033), new Item(12183, 1)), /** * Represents a vampire bat pouch. */ - VAMPIRE_BAT_POUCH(13, 12053, 31, 136, 6835, 1.5, 4, false, new Item(12160), new Item(12155), new Item(3325), new Item(12183, 81)), + VAMPIRE_BAT_POUCH(13, 12053, 31, 136, 6835, 1.5, 4, false, new Item(12160), new Item(12155), new Item(3325), new Item(12183, 1)), /** * Represents a honey badger pouch. */ - HONEY_BADGER_POUCH(14, 12065, 32, 140.8, 6845, 1.6, 4, false, new Item(12160), new Item(12155), new Item(12156), new Item(12183, 84)), + HONEY_BADGER_POUCH(14, 12065, 32, 140.8, 6845, 1.6, 4, false, new Item(12160), new Item(12155), new Item(12156), new Item(12183, 1)), /** * Represents a beaver pouch. */ - BEAVER_POUCH(15, 12021, 33, 57.6, 6808, 0.7, 4, true, new Item(12159), new Item(12155), new Item(1519), new Item(12183, 72)), + BEAVER_POUCH(15, 12021, 33, 57.6, 6808, 0.7, 4, true, new Item(12159), new Item(12155), new Item(1519), new Item(12183, 1)), /** * Represents a void ravager pouch. */ - VOID_RAVAGER_POUCH(16, 12818, 34, 59.6, 7370, 0.7, 4, false, new Item(12159), new Item(12164), new Item(12155), new Item(12183, 74)), + VOID_RAVAGER_POUCH(16, 12818, 34, 59.6, 7370, 0.7, 4, false, new Item(12159), new Item(12164), new Item(12155), new Item(12183, 1)), /** * Represents a void spinner pouch. */ - VOID_SPINNER_POUCH(17, 12780, 34, 59.6, 7333, 0.7, 4, true, new Item(12163), new Item(12166), new Item(12155), new Item(12183, 74)), + VOID_SPINNER_POUCH(17, 12780, 34, 59.6, 7333, 0.7, 4, true, new Item(12163), new Item(12166), new Item(12155), new Item(12183, 1)), /** * Represents a void torcher pouch. */ - VOID_TORCHER_POUCH(18, 12798, 34, 59.6, 7351, 0.7, 4, false, new Item(12163), new Item(12167), new Item(12155), new Item(12183, 74)), + VOID_TORCHER_POUCH(18, 12798, 34, 59.6, 7351, 0.7, 4, false, new Item(12163), new Item(12167), new Item(12155), new Item(12183, 1)), /** * Represents a void shifter pouch. */ - VOID_SHIFTER_POUCH(19, 12814, 34, 59.6, 7367, 0.7, 4, false, new Item(12163), new Item(12165), new Item(12155), new Item(12183, 74)), + VOID_SHIFTER_POUCH(19, 12814, 34, 59.6, 7367, 0.7, 4, false, new Item(12163), new Item(12165), new Item(12155), new Item(12183, 1)), /** * Represents a bronze minotaur pouch. */ - BRONZE_MINOTAUR_POUCH(64, 12073, 36, 316.8, 6853, 3.6, 3, false, new Item(12163), new Item(12155), new Item(2349), new Item(12183, 102)), + BRONZE_MINOTAUR_POUCH(64, 12073, 36, 316.8, 6853, 3.6, 3, false, new Item(12163), new Item(12155), new Item(2349), new Item(12183, 1)), /** * Represents an iron minotaur pouch. */ - IRON_MINOTAUR_POUCH(65, 12075, 46, 404.8, 6855, 4.6, 9, false, new Item(12163), new Item(12155), new Item(2351), new Item(12183, 125)), + IRON_MINOTAUR_POUCH(65, 12075, 46, 404.8, 6855, 4.6, 9, false, new Item(12163), new Item(12155), new Item(2351), new Item(12183, 1)), /** * Represents a steel minotaur pouch. */ - STEEL_MINOTAUR_POUCH(66, 12077, 56, 492.8, 6857, 5.6, 9, false, new Item(12163), new Item(12155), new Item(2353), new Item(12183, 141)), + STEEL_MINOTAUR_POUCH(66, 12077, 56, 492.8, 6857, 5.6, 9, false, new Item(12163), new Item(12155), new Item(2353), new Item(12183, 1)), /** * Represents a mithril minotaur pouch. */ - MITHRIL_MINOTAUR_POUCH(67, 12079, 66, 580.8, 6859, 6.6, 9,false, new Item(12163), new Item(12155), new Item(2359), new Item(12183, 152)), + MITHRIL_MINOTAUR_POUCH(67, 12079, 66, 580.8, 6859, 6.6, 9,false, new Item(12163), new Item(12155), new Item(2359), new Item(12183, 1)), /** * Represents an adamant minotaur pouch. */ - ADAMANT_MINOTAUR_POUCH(68, 12081, 76, 668.8, 6861, 7.6, 9, false, new Item(12163), new Item(12155), new Item(2361), new Item(12183, 144)), + ADAMANT_MINOTAUR_POUCH(68, 12081, 76, 668.8, 6861, 7.6, 9, false, new Item(12163), new Item(12155), new Item(2361), new Item(12183, 1)), /** * Represents a rune minotaur pouch. @@ -144,132 +144,132 @@ public enum SummoningPouch { /** * Represents a bull ant pouch. */ - BULL_ANT_POUCH(20, 12087, 40, 52.8, 6867, 0.6, 5, false, new Item(12158), new Item(12155), new Item(6010), new Item(12183, 11)), + BULL_ANT_POUCH(20, 12087, 40, 52.8, 6867, 0.6, 5, false, new Item(12158), new Item(12155), new Item(6010), new Item(12183, 1)), /** * Represents a macaw pouch. */ - MACAW_POUCH(21, 12071, 41, 72.4, 6851, 0.8, 5, true, new Item(12159), new Item(12155), new Item(249), new Item(12183, 78)), + MACAW_POUCH(21, 12071, 41, 72.4, 6851, 0.8, 5, true, new Item(12159), new Item(12155), new Item(249), new Item(12183, 1)), /** * Represents an evil turnip pouch. */ - EVIL_TURNIP_POUCH(22, 12051, 42, 184.8, 6833, 2.1, 5, false, new Item(12160), new Item(12155), new Item(12153), new Item(12183, 104)), + EVIL_TURNIP_POUCH(22, 12051, 42, 184.8, 6833, 2.1, 5, false, new Item(12160), new Item(12155), new Item(12153), new Item(12183, 1)), /** * Represents a spirit cockatrice pouch. */ - SPIRIT_COCKATRICE_POUCH(23, 12095, 43, 75.2, 6875, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12109), new Item(12183, 88)), + SPIRIT_COCKATRICE_POUCH(23, 12095, 43, 75.2, 6875, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12109), new Item(12183, 1)), /** * Represents a spirit guthatrice pouch. */ - SPIRIT_GUTHATRICE_POUCH(24, 12097, 43, 75.2, 6877, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12111), new Item(12183, 88)), + SPIRIT_GUTHATRICE_POUCH(24, 12097, 43, 75.2, 6877, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12111), new Item(12183, 1)), /** * Represents a spirit saratrice pouch. */ - SPIRIT_SARATRICE_POUCH(25, 12099, 43, 75.2, 6879, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12113), new Item(12183, 88)), + SPIRIT_SARATRICE_POUCH(25, 12099, 43, 75.2, 6879, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12113), new Item(12183, 1)), /** * Represents a spirit zamatrice pouch. */ - SPIRIT_ZAMATRICE_POUCH(26, 12101, 43, 75.2, 6881, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12115), new Item(12183, 88)), + SPIRIT_ZAMATRICE_POUCH(26, 12101, 43, 75.2, 6881, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12115), new Item(12183, 1)), /** * Represents a spirit pengatrice pouch. */ - SPIRIT_PENGATRICE_POUCH(27, 12103, 43, 75.2, 6883, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12117), new Item(12183, 88)), + SPIRIT_PENGATRICE_POUCH(27, 12103, 43, 75.2, 6883, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12117), new Item(12183, 1)), /** * Represents a coraxatrice pouch. */ - SPIRIT_CORAXATRICE_POUCH(28, 12105, 43, 75.2, 6885, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12119), new Item(12183, 88)), + SPIRIT_CORAXATRICE_POUCH(28, 12105, 43, 75.2, 6885, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12119), new Item(12183, 1)), /** * Represents a vulatrice pouch. */ - SPIRIT_VULATRICE(29, 12107, 43, 75.2, 6887, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12121), new Item(12183, 88)), + SPIRIT_VULATRICE(29, 12107, 43, 75.2, 6887, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12121), new Item(12183, 1)), /** * Represents a pyrelord pouch. */ - PYRELORD_POUCH(30, 12816, 46, 202.4, 7377, 2.3, 5, false, new Item(12160), new Item(12155), new Item(590), new Item(12183, 111)), + PYRELORD_POUCH(30, 12816, 46, 202.4, 7377, 2.3, 5, false, new Item(12160), new Item(12155), new Item(590), new Item(12183, 1)), /** * Represents a magpie pouch. */ - MAGPIE_POUCH(31, 12041, 47, 83.2, 6824, 0.9, 5, true, new Item(12159), new Item(12155), new Item(1635), new Item(12183, 88)), + MAGPIE_POUCH(31, 12041, 47, 83.2, 6824, 0.9, 5, true, new Item(12159), new Item(12155), new Item(1635), new Item(12183, 1)), /** * Represents a bloated leech pouch. */ - BLOATED_LEECH_POUCH(32, 12061, 49, 215.2, 6843, 2.4, 5, false, new Item(12160), new Item(12155), new Item(2132), new Item(12183, 117)), + BLOATED_LEECH_POUCH(32, 12061, 49, 215.2, 6843, 2.4, 5, false, new Item(12160), new Item(12155), new Item(2132), new Item(12183, 1)), /** * Represents a spirit terrorbird pouch. */ - SPIRIT_TERRORBIRD_POUCH(33, 12007, 52, 68.4, 6794, 0.8, 6, true, new Item(12158), new Item(12155), new Item(9978), new Item(12183, 12)), + SPIRIT_TERRORBIRD_POUCH(33, 12007, 52, 68.4, 6794, 0.8, 6, true, new Item(12158), new Item(12155), new Item(9978), new Item(12183, 1)), /** * Represents an abyssal parasite pouch. */ - ABYSSAL_PARASITE_POUCH(34, true,12035, 54, 94.8, 6818, 1.1, 6, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 106)), + ABYSSAL_PARASITE_POUCH(34, true,12035, 54, 94.8, 6818, 1.1, 6, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 1)), /** * Represents a spirit jelly pouch. */ - SPIRIT_JELLY_POUCH(35, 12027, 55, 484, 6992, 5.5, 6, false, new Item(12163), new Item(12155), new Item(1937), new Item(12183, 151)), + SPIRIT_JELLY_POUCH(35, 12027, 55, 484, 6992, 5.5, 6, false, new Item(12163), new Item(12155), new Item(1937), new Item(12183, 1)), /** * Represents an ibis pouch. */ - IBIS_POUCH(36, 12531, 56, 98.8, 6991, 1.1, 6, true, new Item(12159), new Item(12155), new Item(311), new Item(12183, 109)), + IBIS_POUCH(36, 12531, 56, 98.8, 6991, 1.1, 6, true, new Item(12159), new Item(12155), new Item(311), new Item(12183, 1)), /** * Represents a spirit kyatt pouch. */ - SPIRIT_KYATT_POUCH(37, 12812, 57, 501.6, 7365, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10103), new Item(12183, 153)), + SPIRIT_KYATT_POUCH(37, 12812, 57, 501.6, 7365, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10103), new Item(12183, 1)), /** * Represents a spirit larupia pouch. */ - SPIRIT_LARUPIA_POUCH(38, 12784, 57, 501.6, 7337, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10095), new Item(12183, 155)), + SPIRIT_LARUPIA_POUCH(38, 12784, 57, 501.6, 7337, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10095), new Item(12183, 1)), /** * Represents a spirit graahk pouch. */ - SPIRIT_GRAAHK_POUCH(39, 12810, 57, 501.6, 7363, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10099), new Item(12183, 154)), + SPIRIT_GRAAHK_POUCH(39, 12810, 57, 501.6, 7363, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10099), new Item(12183, 1)), /** * Represents a karamthulhu overlord pouch. */ - KARAMTHULHU_POUCH(40, 12023, 58, 510.4, 6809, 5.8, 6, false, new Item(12163), new Item(12155), new Item(6667), new Item(12183, 144)), + KARAMTHULHU_POUCH(40, 12023, 58, 510.4, 6809, 5.8, 6, false, new Item(12163), new Item(12155), new Item(6667), new Item(12183, 1)), /** * Represents a smoke devil pouch. */ - SMOKE_DEVIL_POUCH(41, 12085, 61, 268, 6865, 3, 7, false, new Item(12160), new Item(12155), new Item(9736), new Item(12183, 141)), + SMOKE_DEVIL_POUCH(41, 12085, 61, 268, 6865, 3, 7, false, new Item(12160), new Item(12155), new Item(9736), new Item(12183, 1)), /** * Represents an abyssal lurker pouch. */ - ABYSSAL_LUKRER(42, true,12037, 62, 109.6, 6820, 1.9, 9, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 119)), + ABYSSAL_LUKRER(42, true,12037, 62, 109.6, 6820, 1.9, 9, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 1)), /** * Represents a spirit cobra pouch. */ - SPIRIT_COBRA_POUCH(43, 12015, 63, 276.8, 6802, 3.1, 6, false, new Item(12160), new Item(12155), new Item(6287), new Item(12183, 116)), + SPIRIT_COBRA_POUCH(43, 12015, 63, 276.8, 6802, 3.1, 6, false, new Item(12160), new Item(12155), new Item(6287), new Item(12183, 1)), /** * Represents a stranger plant pouch. */ - STRANGER_PLANT_POUCH(44, 12045, 64, 281.6, 6827, 3.2, 6, false, new Item(12160), new Item(12155), new Item(8431), new Item(12183, 128)), + STRANGER_PLANT_POUCH(44, 12045, 64, 281.6, 6827, 3.2, 6, false, new Item(12160), new Item(12155), new Item(8431), new Item(12183, 1)), /** * Represents a barker toad pouch. */ - BARKER_TOAD_POUCH(45, 12123, 66, 87, 6889, 1, 7, false, new Item(12158), new Item(12155), new Item(2150), new Item(12183, 11)), + BARKER_TOAD_POUCH(45, 12123, 66, 87, 6889, 1, 7, false, new Item(12158), new Item(12155), new Item(2150), new Item(12183, 1)), /** * Represents a war tortoise pouch. @@ -279,62 +279,62 @@ public enum SummoningPouch { /** * Represents a bunyip pouch. */ - BUNYIP_POUCH(47, 12029, 68, 119.2, 6813, 1.4, 7, true, new Item(12159), new Item(12155), new Item(383), new Item(12183, 110)), + BUNYIP_POUCH(47, 12029, 68, 119.2, 6813, 1.4, 7, true, new Item(12159), new Item(12155), new Item(383), new Item(12183, 1)), /** * Represents a fruit bat pouch. */ - FRUIT_BAT_POUCH(48, 12033, 69, 121.2, 6817, 1.4, 8, true, new Item(12159), new Item(12155), new Item(1963), new Item(12183, 130)), + FRUIT_BAT_POUCH(48, 12033, 69, 121.2, 6817, 1.4, 8, true, new Item(12159), new Item(12155), new Item(1963), new Item(12183, 1)), /** * Represents a ravenous locust pouch. */ - RAVENOUS_LOCUST_POUCH(49, 12820, 70, 132, 7372, 1.5, 4, false, new Item(12160), new Item(12155), new Item(1933), new Item(12183, 79)), + RAVENOUS_LOCUST_POUCH(49, 12820, 70, 132, 7372, 1.5, 4, false, new Item(12160), new Item(12155), new Item(1933), new Item(12183, 1)), /** * Represents an arctic bear pouch. */ - ARCTIC_BEAR_POUCH(50, 12057, 71, 93.2, 6839, 1.1, 8, false, new Item(12158), new Item(12155), new Item(10117), new Item(12183, 14)), + ARCTIC_BEAR_POUCH(50, 12057, 71, 93.2, 6839, 1.1, 8, false, new Item(12158), new Item(12155), new Item(10117), new Item(12183, 1)), /** * Represents a Phoenix */ - PHOENIX_POUCH(50, 14623, 72, 93.2, 8575, 1.1, 8, false, new Item(12160, 1), new Item(12183, 165), new Item(12155, 1), new Item(14616, 1)), + PHOENIX_POUCH(50, 14623, 72, 93.2, 8575, 1.1, 8, false, new Item(12160, 1), new Item(12183, 1), new Item(12155, 1), new Item(14616, 1)), /** * Represents an obsidian golem pouch. */ - OBSIDIAN_GOLEM_POUCH(51, 12792, 73, 642.4, 7345, 7.3, 8, false, new Item(12163), new Item(12155), new Item(12168), new Item(12183, 195)), + OBSIDIAN_GOLEM_POUCH(51, 12792, 73, 642.4, 7345, 7.3, 8, false, new Item(12163), new Item(12155), new Item(12168), new Item(12183, 1)), /** * Represents a granite lobster pouch. */ - GRANITE_LOBSTER_POUCH(52, 12069, 74, 325.6, 6849, 3.7, 8, false, new Item(12160), new Item(12155), new Item(6979), new Item(12183, 166)), + GRANITE_LOBSTER_POUCH(52, 12069, 74, 325.6, 6849, 3.7, 8, false, new Item(12160), new Item(12155), new Item(6979), new Item(12183, 1)), /** * Represents a praying mantis pouch. */ - PRAYING_MANTIS_POUCH(53, 12011, 75, 329.6, 6798, 3.6, 8, false, new Item(12160), new Item(12155), new Item(2460), new Item(12183, 168)), + PRAYING_MANTIS_POUCH(53, 12011, 75, 329.6, 6798, 3.6, 8, false, new Item(12160), new Item(12155), new Item(2460), new Item(12183, 1)), /** * Represents a forge regent pouch. */ - FORGE_REGENT_BEAST(54, 12782, 76, 134, 7335, 1.5, 9, false, new Item(12159), new Item(12155), new Item(10020), new Item(12183, 141)), + FORGE_REGENT_BEAST(54, 12782, 76, 134, 7335, 1.5, 9, false, new Item(12159), new Item(12155), new Item(10020), new Item(12183, 1)), /** * Represents a talon beast pouch. */ - TALON_BEAST_POUCH(55, 12794, 77, 1015.2, 7347, 3.8, 9, false, new Item(12160), new Item(12155), new Item(12162), new Item(12183, 174)), + TALON_BEAST_POUCH(55, 12794, 77, 1015.2, 7347, 3.8, 9, false, new Item(12160), new Item(12155), new Item(12162), new Item(12183, 1)), /** * Represents a giant ent pouch. */ - GIANT_ENT_POUCH(56, 12013, 78, 136.8, 6800, 1.6, 8, false, new Item(12159), new Item(5933), new Item(12155), new Item(12183, 124)), + GIANT_ENT_POUCH(56, 12013, 78, 136.8, 6800, 1.6, 8, false, new Item(12159), new Item(5933), new Item(12155), new Item(12183, 1)), /** * Represents a hydra pouch. */ - HYDRA_POUCH(60, 12025, 80, 140.8, 6811, 1.6, 9, false, new Item(12159), new Item(571), new Item(12155), new Item(12183, 128)), + HYDRA_POUCH(60, 12025, 80, 140.8, 6811, 1.6, 9, false, new Item(12159), new Item(571), new Item(12155), new Item(12183, 1)), /** * Represents a spirit dagannoth pouch. @@ -344,62 +344,62 @@ public enum SummoningPouch { /** * Represents a unicorn stallion pouch. */ - UNICORN_STALLION_POUCH(70, 12039, 88, 154.4, 6822, 1.8, 9, true, new Item(12159), new Item(237), new Item(12155), new Item(12183, 140)), + UNICORN_STALLION_POUCH(70, 12039, 88, 154.4, 6822, 1.8, 9, true, new Item(12159), new Item(237), new Item(12155), new Item(12183, 1)), /** * Represents a wolpertinger pouch. */ - WOLPERTINGER_POUCH(72, 12089, 92, 404.8, 6869, 4.5, 10, false, new Item(12160), new Item(2859), new Item(3226), new Item(12155), new Item(12183, 203)), + WOLPERTINGER_POUCH(72, 12089, 92, 404.8, 6869, 4.5, 10, false, new Item(12160), new Item(2859), new Item(3226), new Item(12155), new Item(12183, 1)), /** * Represents a pack yak pouch. */ - PACK_YAK_POUCH(75, 12093, 96, 422.4, 6873, 4.8, 10, true, new Item(12160), new Item(10818), new Item(12155), new Item(12183, 211)), + PACK_YAK_POUCH(75, 12093, 96, 422.4, 6873, 4.8, 10, true, new Item(12160), new Item(10818), new Item(12155), new Item(12183, 1)), /** * Represents a fire titan pouch. */ - FIRE_TITAN_POUCH(57, 12802, 79, 695.2, 7355, 7.9, 9, false, new Item(12163), new Item(1442), new Item(12155), new Item(12183, 198)), + FIRE_TITAN_POUCH(57, 12802, 79, 695.2, 7355, 7.9, 9, false, new Item(12163), new Item(1442), new Item(12155), new Item(12183, 1)), /** * Represents a moss titan pouch. */ - MOSS_TITAN_POUCH(58, 12804, 79, 695.2, 7357, 7.9, 9, false, new Item(12163), new Item(1440), new Item(12155), new Item(12183, 198)), + MOSS_TITAN_POUCH(58, 12804, 79, 695.2, 7357, 7.9, 9, false, new Item(12163), new Item(1440), new Item(12155), new Item(12183, 1)), /** * Represents an ice titan pouch. */ - ICE_TITAN_POUCH(59, 12806, 79, 695.2, 7359, 7.9, 9, false, new Item(12163), new Item(1438), new Item(1444), new Item(12155), new Item(12183, 198)), + ICE_TITAN_POUCH(59, 12806, 79, 695.2, 7359, 7.9, 9, false, new Item(12163), new Item(1438), new Item(1444), new Item(12155), new Item(12183, 1)), /** * Represents a lava titan pouch. */ - LAVA_TITAN_POUCH(62, 12788, 83, 730.4, 7341, 8.3, 9, false, new Item(12163), new Item(12168), new Item(12155), new Item(12183, 219)), + LAVA_TITAN_POUCH(62, 12788, 83, 730.4, 7341, 8.3, 9, false, new Item(12163), new Item(12168), new Item(12155), new Item(12183, 1)), /** * Represents a swamp titan pouch. */ - SWAMP_TITAN_POUCH(63, 12776, 85, 373.6, 7329, 4.2, 9, false, new Item(12160), new Item(10149), new Item(12155), new Item(12183, 150)), + SWAMP_TITAN_POUCH(63, 12776, 85, 373.6, 7329, 4.2, 9, false, new Item(12160), new Item(10149), new Item(12155), new Item(12183, 1)), /** * Represents a geyser titan pouch. */ - GEYSER_TITAN_POUCH(71, 12786, 89, 783.2, 7339, 8.9, 9, false, new Item(12163), new Item(1444), new Item(12155), new Item(12183, 222)), + GEYSER_TITAN_POUCH(71, 12786, 89, 783.2, 7339, 8.9, 9, false, new Item(12163), new Item(1444), new Item(12155), new Item(12183, 1)), /** * Represents an abyssal titan pouch. */ - ABYSSAL_TITAN_POUCH(73, true,12796, 93, 163.2, 7349, 1.9, 10, false, new Item(12159), new Item(12161), new Item(12155), new Item(12183, 113)), + ABYSSAL_TITAN_POUCH(73, true,12796, 93, 163.2, 7349, 1.9, 10, false, new Item(12159), new Item(12161), new Item(12155), new Item(12183, 1)), /** * Represents an iron titan pouch. */ - IRON_TITAN_POUCH(74, 12822, 95, 417.6, 7375, 4.7, 10, false, new Item(12160), new Item(1115), new Item(12155), new Item(12183, 198)), + IRON_TITAN_POUCH(74, 12822, 95, 417.6, 7375, 4.7, 10, false, new Item(12160), new Item(1115), new Item(12155), new Item(12183, 1)), /** * Represents a steel titan pouch. */ - STEEL_TITAN_POUCH(76, 12790, 99, 435.2, 7343, 4.9, 10, false, new Item(12160), new Item(1119), new Item(12155), new Item(12183, 178)), + STEEL_TITAN_POUCH(76, 12790, 99, 435.2, 7343, 4.9, 10, false, new Item(12160), new Item(1119), new Item(12155), new Item(12183, 1)), SACRED_CLAY_POUCH_1(-1, 14422, 1, 0, 8240, 0, 1, false, new Item(14182)), SACRED_CLAY_POUCH_2(-1, 14424, 20, 0, 8242, 0, 3, false, new Item(14184)), From 4eebee34c4760ce7534e76eb73030f58a217bac4 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 16:21:10 -0700 Subject: [PATCH 075/306] Removed Beast of Burden carrying restrictions --- .../content/global/skill/summoning/familiar/BurdenBeast.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/global/skill/summoning/familiar/BurdenBeast.java b/Server/src/main/content/global/skill/summoning/familiar/BurdenBeast.java index d6a3100d0..628ff5077 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/BurdenBeast.java +++ b/Server/src/main/content/global/skill/summoning/familiar/BurdenBeast.java @@ -83,6 +83,7 @@ public abstract class BurdenBeast extends Familiar { * @return {@code True} if so. */ public boolean isAllowed(Player owner, Item item) { + /* if (item.getValue() > 50000) { owner.getPacketDispatch().sendMessage("This item is too valuable to trust to this familiar."); return false; @@ -95,6 +96,7 @@ public abstract class BurdenBeast extends Familiar { owner.getPacketDispatch().sendMessage("You can't store " + item.getName().toLowerCase() + " in this familiar."); return false; } + */ if(SummoningPouch.get(this.getPouchId()).abyssal){ if(!item.getName().toLowerCase().contains("essence")) { owner.getPacketDispatch().sendMessage("You can only give unnoted essence to this familiar."); From 6195af3e7b80398a0f651d40178c4c8a9792b6b8 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 16:22:21 -0700 Subject: [PATCH 076/306] Increased Abyssal Lurker carrying capacity --- .../global/skill/summoning/familiar/AbyssalLurkerNPC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/AbyssalLurkerNPC.java b/Server/src/main/content/global/skill/summoning/familiar/AbyssalLurkerNPC.java index 9fb1effdc..b6184c4a8 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/AbyssalLurkerNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/AbyssalLurkerNPC.java @@ -28,7 +28,7 @@ public class AbyssalLurkerNPC extends BurdenBeast { * @param id The id. */ public AbyssalLurkerNPC(Player owner, int id) { - super(owner, id, 4100, 12037, 3, 7, WeaponInterface.STYLE_CAST); + super(owner, id, 4100, 12037, 3, 24, WeaponInterface.STYLE_CAST); } @Override From acfd5c90b9d16efb153d305c9d6c5f4a22df08ca Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 16:22:42 -0700 Subject: [PATCH 077/306] Increased Abyssal Parasite carrying capacity --- .../global/skill/summoning/familiar/AbyssalParasiteNPC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/AbyssalParasiteNPC.java b/Server/src/main/content/global/skill/summoning/familiar/AbyssalParasiteNPC.java index 795484722..551e2db9a 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/AbyssalParasiteNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/AbyssalParasiteNPC.java @@ -36,7 +36,7 @@ public class AbyssalParasiteNPC extends BurdenBeast { * @param id The id. */ public AbyssalParasiteNPC(Player owner, int id) { - super(owner, id, 3000, 12035, 1, 7); + super(owner, id, 3000, 12035, 1, 18); } @Override From 3fd5f60d7fb3de3ddef93c33aa6081581def7b19 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 16:23:02 -0700 Subject: [PATCH 078/306] Increased Abyssal Titan carrying capacity --- .../content/global/skill/summoning/familiar/AbyssalTitanNPC.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/AbyssalTitanNPC.kt b/Server/src/main/content/global/skill/summoning/familiar/AbyssalTitanNPC.kt index a7ed47a6d..eaeb73b45 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/AbyssalTitanNPC.kt +++ b/Server/src/main/content/global/skill/summoning/familiar/AbyssalTitanNPC.kt @@ -21,7 +21,7 @@ import org.rs09.consts.NPCs @Initializable class AbyssalTitanNPC constructor(owner: Player? = null, id: Int = NPCs.ABYSSAL_TITAN_7349) : - BurdenBeast(owner, id, 3200, Items.ABYSSAL_TITAN_POUCH_12796, 6, 7, WeaponInterface.STYLE_ACCURATE) { + BurdenBeast(owner, id, 3200, Items.ABYSSAL_TITAN_POUCH_12796, 6, 30, WeaponInterface.STYLE_ACCURATE) { override fun construct(owner: Player, id: Int): Familiar { return AbyssalTitanNPC(owner, id) } From 7113ef393d3e5c15f577608687309c8e35f49fe4 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 17:29:55 -0700 Subject: [PATCH 079/306] Added Swamp Tar to Lumbridge General Store --- Server/data/configs/shops.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/data/configs/shops.json b/Server/data/configs/shops.json index 714e32a73..fd2444578 100644 --- a/Server/data/configs/shops.json +++ b/Server/data/configs/shops.json @@ -213,7 +213,7 @@ "general_store": "true", "id": "25", "title": "Lumbridge General Store", - "stock": "{1931,30,100}-{1935,30,100}-{1735,10,100}-{1925,10,100}-{1923,10,100}-{1887,10,100}-{590,10,100}-{1755,10,100}-{2347,10,100}-{550,10,100}-{9003,10,100}" + "stock": "{1931,30,100}-{1935,30,100}-{1735,10,100}-{1925,10,100}-{1923,10,100}-{1887,10,100}-{590,10,100}-{1755,10,100}-{2347,10,100}-{550,10,100}-{9003,10,100}-{1939,1000,1}" }, { "npcs": "4716", From 81779f1fae23dd5e3f26374ed6122230c5cad00e Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 21:12:11 -0700 Subject: [PATCH 080/306] Fixing missing healing on Void Spinner Familiar --- .../global/skill/summoning/familiar/VoidFamiliarNPC.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/VoidFamiliarNPC.java b/Server/src/main/content/global/skill/summoning/familiar/VoidFamiliarNPC.java index 4f8d3fab5..817b0501c 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/VoidFamiliarNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/VoidFamiliarNPC.java @@ -195,8 +195,9 @@ public final class VoidFamiliarNPC implements Plugin { public void handleFamiliarTick() { super.handleFamiliarTick(); if (healDelay < GameWorld.getTicks()) { - getSkills().heal(1); + owner.getSkills().heal(1); healDelay = GameWorld.getTicks() + 25; + owner.graphics(Graphics.create(1507), 1); } } From f4c51dbafeb62827a8709bddd0855c266386666f Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 8 Nov 2024 21:17:27 -0700 Subject: [PATCH 081/306] Reduced Quest Point Requirements for Culinomancer shop so that all gloves are obtainable --- .../misthalin/lumbridge/handlers/CulinomancerShop.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt b/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt index e82bcce41..727743512 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt @@ -14,9 +14,9 @@ import kotlin.collections.HashMap class CulinomancerShop : LoginListener { //Enable the chest if the player has 18 quest points or more override fun login(player: Player) { - if(player.questRepository.points >= 18){ + if(player.questRepository.points >= 10){ setVarbit(player, 1850, 5) - setAttribute(player, "culino-tier", player.questRepository.points / 18) //Set this, so we can check if the player has gained a tier during server runtime + setAttribute(player, "culino-tier", player.questRepository.points / 10) //Set this, so we can check if the player has gained a tier during server runtime //Restock pulse for this player (yes, this means the chest will only restock if the player has logged in. Shop system needs work in order to do otherwise.) val restockPulse = object : Pulse(100){ //Run once a minute @@ -49,7 +49,7 @@ class CulinomancerShop : LoginListener { fun getShop(player: Player, food: Boolean): Shop { val uid = player.details.uid val points = player.questRepository.points - val tier = (points / 18) + val tier = (points / 10) if (tier != getAttribute(player, "culino-tier", 0)) //If player tier has changed { foodShops.remove(uid) //Clear the previous shops, so they can regenerate with the new tier @@ -69,7 +69,7 @@ class CulinomancerShop : LoginListener { //Generate default food stock based on an amount of total QP. private fun generateFoodStock(points: Int): Array { val stock = Array(foodStock.size) { ShopItem(0, 0) } - val maxQty = when (val qpTier = (points / 18) - 1) { + val maxQty = when (val qpTier = (points / 10) - 1) { 0, 1, 2, 3, 4 -> 1 + qpTier else -> qpTier + (qpTier + (qpTier - 5)) //5 = 10, 6 = 13, 7 = 15, etc } @@ -83,14 +83,14 @@ class CulinomancerShop : LoginListener { //Generate default gear stock based on an amount of total QP. private fun generateGearStock(points: Int): Array { val stock = Array(gearStock.size) { ShopItem(0, 0) } - val qpTier = (points / 18) + val qpTier = (points / 10) for ((index, item) in stock.withIndex()) item.itemId = gearStock[index] for (i in 0 until min(qpTier, 10)) { stock[i].amount = 30 stock[i + 10].amount = 5 } - stock[9].amount = 1 + //stock[9].amount = 1 return stock } From 13e4a0b6408df693b4b02b8096e7d54f0f226221 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 9 Nov 2024 09:08:05 -0700 Subject: [PATCH 082/306] Added code to customize logout timer. Set to 1 hour. --- .../main/core/net/packet/PacketProcessor.kt | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/net/packet/PacketProcessor.kt b/Server/src/main/core/net/packet/PacketProcessor.kt index 51e4324e9..875d3693f 100644 --- a/Server/src/main/core/net/packet/PacketProcessor.kt +++ b/Server/src/main/core/net/packet/PacketProcessor.kt @@ -307,8 +307,24 @@ object PacketProcessor { pkt.player.interfaceManager.switchWindowMode(pkt.windowMode) } is Packet.TrackingAfkTimeout -> { - //if (pkt.player.details.rights != Rights.ADMINISTRATOR) - //pkt.player.packetDispatch.sendLogout() + /* After 5 minutes idle, the client sends an afk packet every 10 seconds. + *This code counts the number of afk packets recieved, resetting the count if they are more than 100 ticks apart. + *This allows us to customize the afk logout timer + */ + if (pkt.player.details.rights != Rights.ADMINISTRATOR) { + if (GameWorld.ticks - pkt.player.getAttribute("afk:lasttick", 0) > 100) { + pkt.player.setAttribute("afk:count", 0) + } else { + pkt.player.setAttribute("afk:count", pkt.player.getAttribute("afk:count", 0) + 1) + } + pkt.player.setAttribute("afk:lasttick", GameWorld.ticks) + if (pkt.player.getAttribute("afk:count", 0) == 300) { + pkt.player.sendMessage("You have been idle for 55 minutes and will be logged out soon.") + } + if (pkt.player.getAttribute("afk:count", 0) >= 330) { + pkt.player.packetDispatch.sendLogout() + } + } } is Packet.TrackingCameraPos -> { //TODO Refactor the player monitor to be actually useful and log this From 325b8f6f2043490904fc5be23ce5501238397df7 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 9 Nov 2024 15:45:48 -0700 Subject: [PATCH 083/306] Crystal Bow and Shield no longer lose stats as they degrade --- Server/data/configs/item_configs.json | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 852a6fc39..08580edac 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -38817,7 +38817,7 @@ "name": "Crystal bow 9/10", "archery_ticket_price": "0", "id": "4215", - "bonuses": "0,0,0,0,96,0,0,0,0,0,0,0,0,0,68" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38838,7 +38838,7 @@ "name": "Crystal bow 8/10", "archery_ticket_price": "0", "id": "4216", - "bonuses": "0,0,0,0,92,0,0,0,0,0,0,0,0,0,66" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38859,7 +38859,7 @@ "name": "Crystal bow 7/10", "archery_ticket_price": "0", "id": "4217", - "bonuses": "0,0,0,0,88,0,0,0,0,0,0,0,0,0,64" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38880,7 +38880,7 @@ "name": "Crystal bow 6/10", "archery_ticket_price": "0", "id": "4218", - "bonuses": "0,0,0,0,84,0,0,0,0,0,0,0,0,0,62" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38901,7 +38901,7 @@ "name": "Crystal bow 5/10", "archery_ticket_price": "0", "id": "4219", - "bonuses": "0,0,0,0,80,0,0,0,0,0,0,0,0,0,60" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38922,7 +38922,7 @@ "name": "Crystal bow 4/10", "archery_ticket_price": "0", "id": "4220", - "bonuses": "0,0,0,0,76,0,0,0,0,0,0,0,0,0,58" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38943,7 +38943,7 @@ "name": "Crystal bow 3/10", "archery_ticket_price": "0", "id": "4221", - "bonuses": "0,0,0,0,72,0,0,0,0,0,0,0,0,0,56" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38964,7 +38964,7 @@ "name": "Crystal bow 2/10", "archery_ticket_price": "0", "id": "4222", - "bonuses": "0,0,0,0,68,0,0,0,0,0,0,0,0,0,54" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{4,70}-{16,50}", @@ -38985,7 +38985,7 @@ "name": "Crystal bow 1/10", "archery_ticket_price": "0", "id": "4223", - "bonuses": "0,0,0,0,64,0,0,0,0,0,0,0,0,0,52" + "bonuses": "0,0,0,0,100,0,0,0,0,0,0,0,0,0,70" }, { "requirements": "{1,70}-{16,50}", @@ -39028,7 +39028,7 @@ "archery_ticket_price": "0", "id": "4226", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,49,52,51,0,78,68,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39042,7 +39042,7 @@ "archery_ticket_price": "0", "id": "4227", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,47,50,49,0,76,66,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39056,7 +39056,7 @@ "archery_ticket_price": "0", "id": "4228", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,45,48,47,0,74,65,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39070,7 +39070,7 @@ "archery_ticket_price": "0", "id": "4229", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,43,46,45,0,72,63,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39084,7 +39084,7 @@ "archery_ticket_price": "0", "id": "4230", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,41,44,43,0,70,61,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39098,7 +39098,7 @@ "archery_ticket_price": "0", "id": "4231", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,39,42,41,0,68,59,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39112,7 +39112,7 @@ "archery_ticket_price": "0", "id": "4232", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,37,40,39,0,66,58,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39126,7 +39126,7 @@ "archery_ticket_price": "0", "id": "4233", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,35,38,37,0,64,56,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { @@ -39140,7 +39140,7 @@ "archery_ticket_price": "0", "id": "4234", "absorb": "6,0,12", - "bonuses": "0,0,0,-10,-10,33,36,35,0,62,54,0,0,0,0", + "bonuses": "0,0,0,-10,-10,51,54,53,0,80,70,0,0,0,0", "equipment_slot": "5" }, { From 974c44a04166a66b0cd3e258bde97dd2ce541261 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 9 Nov 2024 20:29:01 -0700 Subject: [PATCH 084/306] Remove staff check when autocasting Slayer Dart and Claws of Guthix This should have no effect on the slayer dart spell, but does allow Claws of Guthix to be autocast with the Guthix Staff and not just the Void Mace. --- .../src/main/core/game/node/entity/combat/spell/MagicSpell.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index 12059a76c..cf003c648 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -203,6 +203,7 @@ public abstract class MagicSpell implements Plugin { } if (caster instanceof Player) { CombatSpell spell = ((Player) caster).getProperties().getAutocastSpell(); + /* Snowscape custom. Removing this allows guthix staff to autocast claws of guthix. if (spell != null) { boolean slayer = ((Player) caster).getEquipment().get(3).getName().contains("layer's staff"); boolean voidKnight = ((Player) caster).getEquipment().get(3).getName().contains("knight mace"); @@ -211,6 +212,7 @@ public abstract class MagicSpell implements Plugin { return false; } } + */ } if((spellId == 12 || spellId == 30 || spellId == 56) && caster instanceof Player){ if (caster.getAttribute("entangleDelay", 0) > GameWorld.getTicks()) { From 98e8cd4592e86c6e4e2247d7851e6c888c593af8 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 9 Nov 2024 21:47:02 -0700 Subject: [PATCH 085/306] Fixed incorrect autocast animation for the three god spells Also future-proofed by adding animation for Iban's blast, even though the staff is not obtainable yet and the spell can't normally be autocast. --- .../node/entity/combat/spell/CombatSpell.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java b/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java index 3601d6849..0db21b192 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java @@ -156,10 +156,20 @@ public abstract class CombatSpell extends MagicSpell { } if (entity.getProperties().getAutocastSpell() == this && (entity instanceof Player || animation == null)) { Player p = entity.asPlayer(); - if (p.getProperties().getAutocastSpell().getSpellId() == 31) { - entity.animate(new Animation(1576)); - } else { - entity.animate(AUTOCAST_ANIMATION); + switch(p.getProperties().getAutocastSpell().getSpellId()) { + case 31: + entity.animate(new Animation(1576, Priority.HIGH)); + break; + case 41: + case 42: + case 43: + entity.animate(new Animation(811, Priority.HIGH)); + break; + case 29: + entity.animate(new Animation(708, Priority.HIGH)); + break; + default: + entity.animate(AUTOCAST_ANIMATION); } } else { if (entity instanceof NPC) { From e8afa4e529bf21bab5829d15cfbbb724262aff9c Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 15:15:10 -0700 Subject: [PATCH 086/306] Add damage scaling to Crumble Undead The spell damage scales like Magic Dart, but due to the limitation of only affecting undead enemies, deals 2 more damage. If the enemy is not undead, deals only 1 damage (set to 1 instead of 0 to prevent splashing abuse). --- .../main/core/game/node/entity/combat/spell/SpellType.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/SpellType.java b/Server/src/main/core/game/node/entity/combat/spell/SpellType.java index 828a88804..d58dd2887 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/SpellType.java +++ b/Server/src/main/core/game/node/entity/combat/spell/SpellType.java @@ -47,7 +47,11 @@ public enum SpellType { CRUMBLE_UNDEAD(1.2) { @Override public int getImpactAmount(Entity e, Entity victim, int base) { - return 15; // Hits as high as Earth blast + if (((NPC) victim).getTask() != null && ((NPC) victim).getTask().undead) { + return 12 + (e.getSkills().getLevel(Skills.MAGIC) / 10); + } + ((Player) e).sendMessage("Your spell does almost no damage, as your target is not undead."); + return 1; } }, From d21452a8bffedcd7572d4899962147c02787f090 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 17:36:38 -0700 Subject: [PATCH 087/306] Increased arrowheads and other ranged ammo produced from bars by 3x This is done with the intention to balance the value of rune arrows and bolts with the value of a rune bar (12800 if you make high-end rune gear and high alch it), as well as the value of the crystal bow (72 gp per shot). --- .../main/content/global/skill/smithing/SmithingType.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/skill/smithing/SmithingType.java b/Server/src/main/content/global/skill/smithing/SmithingType.java index fd38a6209..e4a05e640 100644 --- a/Server/src/main/content/global/skill/smithing/SmithingType.java +++ b/Server/src/main/content/global/skill/smithing/SmithingType.java @@ -32,7 +32,7 @@ public enum SmithingType { /** * Crossbow bolt */ - TYPE_CROSSBOW_BOLT(1, 50, 51, new int[] { 56, 55, 54, 53 }, 10), + TYPE_CROSSBOW_BOLT(1, 50, 51, new int[] { 56, 55, 54, 53 }, 30), /** * Sword @@ -42,7 +42,7 @@ public enum SmithingType { /** * Dart tips */ - TYPE_DART_TIP(1, 66, 67, new int[] { 72, 71, 70, 69 }, 10), + TYPE_DART_TIP(1, 66, 67, new int[] { 72, 71, 70, 69 }, 30), /** * Nails @@ -66,7 +66,7 @@ public enum SmithingType { /** * Arrow Tips */ - TYPE_ARROW_TIP(1, 106, 107, new int[] { 112, 111, 110, 109 }, 15), + TYPE_ARROW_TIP(1, 106, 107, new int[] { 112, 111, 110, 109 }, 45), /** * Scimitar @@ -86,7 +86,7 @@ public enum SmithingType { /** * Throwing Knife */ - TYPE_THROWING_KNIFE(1, 138, 139, new int[] { 144, 143, 142, 141 }, 5), + TYPE_THROWING_KNIFE(1, 138, 139, new int[] { 144, 143, 142, 141 }, 15), /** * Full helm From de4f67832b2ed7a3a7e582828134e96efa572308 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 18:45:01 -0700 Subject: [PATCH 088/306] Changed crystal equipment to recharge with rune arrows and kiteshields instead of coins New Crystal Bows require 3600 rune arrows, recharging requires 3000. New Shields cost 24 Rune Kite shields, recharging requires 20. --- .../quest/rovingelves/IslwynDialogue.java | 62 ++++++++++++------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java index b24862a1f..e1bcd2184 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java @@ -235,7 +235,7 @@ public class IslwynDialogue extends DialoguePlugin { case 33: switch (buttonId) { case 1: - interpreter.sendDialogues(1680, FacialExpression.HALF_GUILTY, "Ah, very well.", "I will sell you a new bow or shield for 900,000 coins."); + interpreter.sendDialogues(1680, FacialExpression.HALF_GUILTY, "Ah, very well.", "I will make you a new bow from 3,600 Rune Arrows", "or a shield from 24 Rune Kiteshields."); stage = 37; break; case 2: @@ -245,7 +245,7 @@ public class IslwynDialogue extends DialoguePlugin { } break; case 34: - interpreter.sendOptions("Select an Option", "Recharge seed into bow", "Recharge seed into shield"); + interpreter.sendOptions("Select an Option", "Recharge seed into bow with 3000 Rune Arrows", "Recharge seed into shield with 20 Rune Kiteshields"); stage = 35; break; case 35: @@ -266,13 +266,13 @@ public class IslwynDialogue extends DialoguePlugin { stage = 500; } int timesRecharged = player.getAttribute("rovingelves:crystal-equip-recharges", 0); - int price = crystalWeaponPrice(timesRecharged); - if (!player.getInventory().contains(995, price)) { - interpreter.sendDialogue(String.format("You don't have enough coins, you need %d.", price)); + int price = crystalBowPrice(false); + if (!player.getInventory().contains(892, price)) { + interpreter.sendDialogue(String.format("You don't have enough Rune Arrows, you need %d.", price)); stage = 500; } - if (player.getInventory().contains(995, price) && player.getInventory().contains(RovingElves.CRYSTAL_SEED.getId(), 1)) { - if (player.getInventory().remove(RovingElves.CRYSTAL_SEED) && player.getInventory().remove(new Item(995, price))) { + if (player.getInventory().contains(892, price) && player.getInventory().contains(RovingElves.CRYSTAL_SEED.getId(), 1)) { + if (player.getInventory().remove(RovingElves.CRYSTAL_SEED) && player.getInventory().remove(new Item(892, price))) { player.getInventory().add(new Item(4214, 1)); player.incrementAttribute("/save:rovingelves:crystal-equip-recharges", 1); end(); @@ -285,13 +285,13 @@ public class IslwynDialogue extends DialoguePlugin { stage = 500; } timesRecharged = player.getAttribute("rovingelves:crystal-equip-recharges", 0); - price = crystalWeaponPrice(timesRecharged); - if (!player.getInventory().contains(995, price)) { - interpreter.sendDialogue("You don't have enough coins."); + price = crystalShieldPrice(false); + if (!player.getInventory().contains(1201, price)) { + interpreter.sendDialogue(String.format("You don't have enough Rune Kiteshields, you need %d.", price)); stage = 500; } - if (player.getInventory().contains(995, price) && player.getInventory().contains(RovingElves.CRYSTAL_SEED.getId(), 1)) { - if (player.getInventory().remove(RovingElves.CRYSTAL_SEED) && player.getInventory().remove(new Item(995, price))) { + if (player.getInventory().contains(1201, price) && player.getInventory().contains(RovingElves.CRYSTAL_SEED.getId(), 1)) { + if (player.getInventory().remove(RovingElves.CRYSTAL_SEED) && player.getInventory().remove(new Item(1201, price))) { player.getInventory().add(new Item(4225, 1)); player.incrementAttribute("/save:rovingelves:crystal-equip-recharges", 1); end(); @@ -315,13 +315,13 @@ public class IslwynDialogue extends DialoguePlugin { } break; case 39: - price = crystalWeaponPrice(0); - if (!player.getInventory().contains(995, price)) { - interpreter.sendDialogue("You don't have enough coins."); + price = crystalBowPrice(true); + if (!player.getInventory().contains(892, price)) { + interpreter.sendDialogue(String.format("You don't have enough Rune Arrows, you need %d.", price)); stage = 500; } - if (player.getInventory().contains(995, price)) { - if (player.getInventory().remove(new Item(995, price))) { + if (player.getInventory().contains(892, price)) { + if (player.getInventory().remove(new Item(892, price))) { if (!player.getInventory().add(new Item(4212, 1))) { GroundItemManager.create(new Item(4212, 1), player); } @@ -330,13 +330,13 @@ public class IslwynDialogue extends DialoguePlugin { } break; case 40: - price = crystalWeaponPrice(0); - if (!player.getInventory().contains(995, price)) { - interpreter.sendDialogue("You don't have enough coins."); + price = crystalShieldPrice(true); + if (!player.getInventory().contains(1201, price)) { + interpreter.sendDialogue(String.format("You don't have enough Rune Kiteshields, you need %d.", price)); stage = 500; } - if (player.getInventory().contains(995, price)) { - if (player.getInventory().remove(new Item(995, price))) { + if (player.getInventory().contains(1201, price)) { + if (player.getInventory().remove(new Item(1201, price))) { if (!player.getInventory().add(new Item(4224, 1))) { GroundItemManager.create(new Item(4224, 1), player); } @@ -377,7 +377,21 @@ public class IslwynDialogue extends DialoguePlugin { } // 900k for the 0th recharge (or for new bows), decreasing by 180k per recharge down to 180k - public int crystalWeaponPrice(int timesRecharged) { - return Math.max(900000 - 180000 * timesRecharged, 180000); + //public int crystalWeaponPrice(int timesRecharged) { + // return Math.max(900000 - 180000 * timesRecharged, 180000); + //} + public int crystalBowPrice(boolean isNew) { + if (isNew) { + return 3600; + } else { + return 3000; + } + } + public int crystalShieldPrice(boolean isNew) { + if (isNew) { + return 24; + } else { + return 20; + } } } From 7da14bd3b8ca907e959f484b7f3af045d45ac6a4 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 18:46:47 -0700 Subject: [PATCH 089/306] Increased Crystal Equipment charges to 12,000 --- .../handlers/item/equipment/CrystalEquipmentRegister.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/equipment/CrystalEquipmentRegister.kt b/Server/src/main/content/global/handlers/item/equipment/CrystalEquipmentRegister.kt index 2bb7bb48d..4504e9dfd 100644 --- a/Server/src/main/content/global/handlers/item/equipment/CrystalEquipmentRegister.kt +++ b/Server/src/main/content/global/handlers/item/equipment/CrystalEquipmentRegister.kt @@ -7,7 +7,7 @@ class CrystalEquipmentRegister : StartupListener { val shield: Array = arrayOf(Items.NEW_CRYSTAL_SHIELD_4224, Items.CRYSTAL_SHIELD_FULL_4225, Items.CRYSTAL_SHIELD_9_10_4226, Items.CRYSTAL_SHIELD_8_10_4227, Items.CRYSTAL_SHIELD_7_10_4228, Items.CRYSTAL_SHIELD_6_10_4229, Items.CRYSTAL_SHIELD_5_10_4230, Items.CRYSTAL_SHIELD_4_10_4231, Items.CRYSTAL_SHIELD_3_10_4232, Items.CRYSTAL_SHIELD_2_10_4233, Items.CRYSTAL_SHIELD_1_10_4234, Items.CRYSTAL_SEED_4207) val bow: Array = arrayOf(Items.NEW_CRYSTAL_BOW_4212, Items.CRYSTAL_BOW_FULL_4214, Items.CRYSTAL_BOW_9_10_4215, Items.CRYSTAL_BOW_8_10_4216, Items.CRYSTAL_BOW_7_10_4217, Items.CRYSTAL_BOW_6_10_4218, Items.CRYSTAL_BOW_5_10_4219, Items.CRYSTAL_BOW_4_10_4220, Items.CRYSTAL_BOW_3_10_4221, Items.CRYSTAL_BOW_2_10_4222, Items.CRYSTAL_BOW_1_10_4223, Items.CRYSTAL_SEED_4207) override fun startup() { - EquipmentDegrader.registerSet(250, shield) - EquipmentDegrader.registerSet(250, bow) + EquipmentDegrader.registerSet(1200, shield) + EquipmentDegrader.registerSet(1200, bow) } } \ No newline at end of file From 2e65f0d186ed1798770c3ccb6e44f157d7b7ed1a Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 19:06:13 -0700 Subject: [PATCH 090/306] Changed combat spells to only consume runes 33% of the time This is part of the attempt to balance ammo production and consumption rates. --- .../core/game/node/entity/combat/spell/MagicSpell.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index cf003c648..6259add5a 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -222,12 +222,12 @@ public abstract class MagicSpell implements Plugin { } if (caster instanceof Player) { Player p = (Player) caster; - if(p.getEquipment().get(3) != null && p.getEquipment().get(3).getId() == 14726){ - if(RandomFunction.getRandom(100) < 13){ - p.sendMessage("Your staff negates the rune requirement of the spell."); + //if(p.getEquipment().get(3) != null && p.getEquipment().get(3).getId() == 14726){ + if(RandomFunction.getRandom(100) > 33){ + //p.sendMessage("Your staff negates the rune requirement of the spell."); return true; } - } + //} if (runes == null) { return true; } From 48069e2234080a10c933928080d6e6984edadeb6 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 20:47:32 -0700 Subject: [PATCH 091/306] Added Lunar Robes to Moonclan clothing shop There is no way to get the robes until the quest is implemented, so this is a temporary solution. The robes are very cheap, but they also aren't very good so it should be fine. --- Server/data/configs/shops.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/data/configs/shops.json b/Server/data/configs/shops.json index fd2444578..2f6a5ff1f 100644 --- a/Server/data/configs/shops.json +++ b/Server/data/configs/shops.json @@ -1599,7 +1599,7 @@ "general_store": "false", "id": "181", "title": "MoonClan Fine Clothes", - "stock": "{9068,10,100}-{9069,10,100}-{9070,10,100}-{9071,10,100}-{9072,10,100}-{9073,10,100}-{9074,10,100}-{1733,50,100}-{1734,500,100}" + "stock": "{9068,10,100}-{9069,10,100}-{9070,10,100}-{9071,10,100}-{9072,10,100}-{9073,10,100}-{9074,10,100}-{1733,50,100}-{1734,500,100}-{9084,10,100}-{9096,10,100}-{9097,10,100}-{9098,10,100}-{9099,10,100}-{9100,10,100}-{9101,10,100}-{9102,10,100}-{9104,10,100}" }, { "npcs": "", From da071b795d19f83f8cf296c0cf2b2d0d897ed08e Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 20:55:02 -0700 Subject: [PATCH 092/306] Normal trees now have a chance to deplete, like higher level trees This is done to make collecting normal logs for arrowshafts less click-intensive. --- .../global/skill/gather/woodcutting/WoodcuttingListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt index c73b135b6..4ca385088 100644 --- a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt +++ b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt @@ -156,7 +156,7 @@ class WoodcuttingListener : InteractionListener { //OSRS: https://oldschool.runescape.wiki/w/Woodcutting scroll down to the mechanics section //RS3 : https://runescape.wiki/w/Woodcutting scroll down to the mechanics section, and expand the tree felling chances table if (resource.getRespawnRate() > 0) { - if (RandomFunction.roll(8) || listOf(1, 2, 3, 4, 6).contains(resource.identifier.toInt())){ + if (RandomFunction.roll(8) || listOf(2, 3, 4, 6).contains(resource.identifier.toInt())){ if (resource.isFarming()) { val fPatch = forObject(node.asScenery()) if (fPatch != null) { From df3fc6c9739f9bd6e2c9ab989c0b57353f46be83 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 21:17:30 -0700 Subject: [PATCH 093/306] Increased the Herb:Tar ratio from 1:15 to 1:45 Salamanders burn through ammo, and herbs are a lot of work to come by. This increases how much ammo you get per herb by 3x. --- .../main/content/global/skill/herblore/HerbTarPulse.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/herblore/HerbTarPulse.java b/Server/src/main/content/global/skill/herblore/HerbTarPulse.java index 45793be82..a63c5f4f5 100644 --- a/Server/src/main/content/global/skill/herblore/HerbTarPulse.java +++ b/Server/src/main/content/global/skill/herblore/HerbTarPulse.java @@ -25,7 +25,7 @@ public final class HerbTarPulse extends SkillPulse { /** * Represents the swamp tar item. */ - private static final Item SWAMP_TAR = new Item(1939, 15); + private static final Item SWAMP_TAR = new Item(1939, 45); /** * Represents the tar to make. @@ -65,7 +65,7 @@ public final class HerbTarPulse extends SkillPulse { return false; } if (!player.getInventory().containsItem(SWAMP_TAR)) { - player.getPacketDispatch().sendMessage("You need at least 15 swamp tar in order to do this."); + player.getPacketDispatch().sendMessage("You need at least 45 swamp tar in order to do this."); return false; } return true; @@ -83,7 +83,7 @@ public final class HerbTarPulse extends SkillPulse { return false; } if (player.getInventory().containsItem(SWAMP_TAR) && player.getInventory().containsItem(tar.getIngredient()) && player.getInventory().remove(SWAMP_TAR) && player.getInventory().remove(tar.getIngredient())) { - final Item item = new Item(tar.getTar().getId(), 15); + final Item item = new Item(tar.getTar().getId(), 45); player.getInventory().add(item); player.getSkills().addExperience(Skills.HERBLORE, tar.getExperience(), true); player.getPacketDispatch().sendMessage("You add the " + tar.getIngredient().getName().toLowerCase().replace("clean", "").trim() + " to the swamp tar."); From fa808accd4c6ba55f92a0a0384557c37db4c69aa Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 22:09:13 -0700 Subject: [PATCH 094/306] Added requirement checks to the teleport tablets --- .../global/handlers/item/TeleTabsListener.kt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt index 4a3a0bf75..45925a4e9 100644 --- a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt +++ b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt @@ -11,6 +11,8 @@ import core.game.node.item.Item import core.game.world.map.Location import core.api.hasRequirement; +import core.cache.def.impl.ItemDefinition; + class TeleTabsListener : InteractionListener { enum class TeleTabs(val item: Int, val location: Location, val exp: Double, val requirementCheck: (Player) -> Boolean = { true }) { @@ -18,23 +20,37 @@ class TeleTabsListener : InteractionListener { player -> hasRequirement(player, "Plague City"); }), AIR_ALTAR_TELEPORT(13599, Location.create(2978, 3296, 0), 0.0), - ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0), - BLOOD_ALTAR_TELEPORT(13610, Location.create(3559, 9778, 0), 0.0), + ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0, { + player -> hasRequirement(player, "Lunar Diplomacy"); + }), + BLOOD_ALTAR_TELEPORT(13610, Location.create(3559, 9778, 0), 0.0, { + player -> hasRequirement(player, "Legacy of Seergaze"); + }), BODY_ALTAR_TELEPORT(13604, Location.create(3055, 3443, 0), 0.0), CAMELOT_TELEPORT(8010, Location.create(2757, 3477, 0), 55.5), CHAOS_ALTAR_TELEPORT(13606, Location.create(3058, 3593, 0), 0.0), - COSMIC_ALTAR_TELEPORT(13605, Location.create(2411, 4380, 0), 0.0), - DEATH_ALTAR_TELEPORT(13609, Location.create(1863, 4639, 0), 0.0), + COSMIC_ALTAR_TELEPORT(13605, Location.create(2411, 4380, 0), 0.0, { + player -> hasRequirement(player, "Lost City"); + }), + DEATH_ALTAR_TELEPORT(13609, Location.create(1863, 4639, 0), 0.0, { + player -> hasRequirement(player, "Mourning's End Part II"); + }), EARTH_ALTAR_TELEPORT(13602, Location.create(3304, 3472, 0), 0.0), FALADOR_TELEPORT(8009, Location.create(2966, 3380, 0), 47.0), FIRE_ALTAR_TELEPORT(13603, Location.create(3311, 3252, 0), 0.0), - LAW_ALTAR_TELEPORT(13608, Location.create(2857, 3378, 0), 0.0), + LAW_ALTAR_TELEPORT(13608, Location.create(2857, 3378, 0), 0.0, { + player -> if (!ItemDefinition.canEnterEntrana(player)) (player.sendMessage("The power of Saradomin prevents you from taking armour or weaponry to Entrana.") !is Unit) else true; // ugly way of doing this, but the sendMessage function returns a Unit type, so by using !is Unit it becomes false. + }), LUMBRIDGE_TELEPORT(8008, Location.create(3222, 3218, 0), 41.0), MIND_ALTAR_TELEPORT(13600, Location.create(2979, 3510, 0), 0.0), NATURE_ALTAR_TELEPORT(13607, Location.create(2868, 3013, 0), 0.0), - TELEKINETIC_GRAB(8022, Location.create(2836, 3285, 0), 0.0), + TELEKINETIC_GRAB(8022, Location.create(2836, 3285, 0), 0.0, { + player -> hasRequirement(player, "Dragon Slayer"); + }), VARROCK_TELEPORT(8007, Location.create(3212, 3423, 0), 35.00), - WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00), + WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00, { + player -> hasRequirement(player, "Watchtower"); + }), WATER_ALTAR_TELEPORT(13601, Location.create(3182, 3162, 0), 0.0); companion object { From e5e6006212b44b8cb97fc76ef9945da3f8108c12 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 10 Nov 2024 22:36:00 -0700 Subject: [PATCH 095/306] Protect from Summoning prayer now prevents NPC aggression when active --- .../core/game/node/entity/npc/agg/AggressiveHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java b/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java index c2a49842d..5ee281bb4 100644 --- a/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java +++ b/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java @@ -9,6 +9,8 @@ import core.game.node.entity.player.info.Rights; import core.game.world.GameWorld; import core.tools.RandomFunction; +import core.game.node.entity.player.link.prayer.PrayerType; + /** * Used to handle entity aggressiveness. * @author Emperor @@ -81,6 +83,9 @@ public final class AggressiveHandler { } Entity target = behavior.getLogicalTarget(entity, behavior.getPossibleTargets(entity, radius)); if (target instanceof Player) { + if (((Player) target).getPrayer().get(PrayerType.PROTECT_FROM_SUMMONING)) { + return false; + } if (target.getAttribute("ignore_aggression", false)) { return false; } From a361915281012423709b35c4d9a26fca9170d769 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 11 Nov 2024 09:57:51 -0700 Subject: [PATCH 096/306] Familiar timer now only decreases if at zero summoning points This change reduces the upkeep cost of Summoning, now you only need points or pouches, but not both. --- .../global/skill/summoning/familiar/Familiar.java | 9 +++++++-- .../global/skill/summoning/familiar/FamiliarManager.java | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java index b85c1ec16..4177e1d5c 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java +++ b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java @@ -177,7 +177,9 @@ public abstract class Familiar extends NPC implements Plugin { if (pouchId == -1) { this.pointsPerTick = 0.0; } else { - int drain = pouch.getLevelRequired() - pouch.getSummonCost() + 1; + //int drain = pouch.getLevelRequired() - pouch.getSummonCost() + 1; + // Snowscape: removing the initial drain and making it drain over the life of the familiar. Removing the +1 makes the final drain happen on the last tick of the familiar's life. That works for our new system, as the familiar timer won't start until that final tick happens. + int drain = pouch.getLevelRequired(); this.pointsPerTick = (double) drain / maximumTicks; } } @@ -223,7 +225,10 @@ public abstract class Familiar extends NPC implements Plugin { @Override public void handleTickActions() { - ticks--; + //Snowscape: only count down the familiar timer if summoning points are zero + if (owner.getSkills().getLevel(Skills.SUMMONING) == 0) { + ticks--; + } fracDrain += pointsPerTick; if (fracDrain > 1.0 && ticks > 0) { fracDrain -= 1.0; diff --git a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java index 02bb0a403..61b97126e 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java +++ b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java @@ -187,10 +187,12 @@ public final class FamiliarManager { player.getPacketDispatch().sendMessage("You need a Summoning level of " + pouch.getLevelRequired() + " to summon this familiar."); return; } + /* Snowscape: removing the drain on summon. This drain will instead be added to the gradual drain over the familiar's life. if (player.getSkills().getLevel(Skills.SUMMONING) < pouch.getSummonCost()) { player.getPacketDispatch().sendMessage("You need at least " + pouch.getSummonCost() + " Summoning points to summon this familiar."); return; } + */ final int npcId = pouch.getNpcId(); Familiar fam = !renew ? FAMILIARS.get(npcId) : familiar; if (fam == null) { @@ -208,7 +210,7 @@ public final class FamiliarManager { if (!player.getInventory().remove(item)) { return; } - player.getSkills().updateLevel(Skills.SUMMONING, -pouch.getSummonCost(), 0); + //player.getSkills().updateLevel(Skills.SUMMONING, -pouch.getSummonCost(), 0); player.getSkills().addExperience(Skills.SUMMONING, pouch.getSummonExperience()); if (!renew) { familiar = fam; From ee3a71a5d0cf3c47c25cdc0f4c5572a1db05c037 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 18:01:57 -0700 Subject: [PATCH 097/306] Allow Ancient Magick spells to work up to level 48 wilderness. --- .../core/game/world/map/zone/ZoneMonitor.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java index 65b4a0322..4be51e122 100644 --- a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java +++ b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java @@ -238,7 +238,7 @@ public final class ZoneMonitor { * @return {@code True} if so. */ public boolean teleport(int type, Node node) { - if (type != -1 && entity.isTeleBlocked() && !canTeleportByJewellery(type, node)) { + if (type != -1 && entity.isTeleBlocked() && !canTeleportByJewellery(type, node)&& !canTeleportByAncient(type)) { if (entity.isPlayer()) { entity.asPlayer().sendMessage("A magical force has stopped you from teleporting."); } @@ -278,6 +278,32 @@ public final class ZoneMonitor { return false; } + /** + * Snowscape custom allowing teleports with Ancient Magicks in >= 1 <= 30 wilderness level + * @return {@code True} if so. + */ + private boolean canTeleportByAncient(int type) { + if (type != 0) { + return false; + } + if (entity.timers.getTimer("teleblock") != null) + return false; + + if (entity.getZoneMonitor().isRestricted(ZoneRestriction.TELEPORT)) { + return false; + } + + if (entity.getLocks().isTeleportLocked()) { + if (entity.isPlayer()) { + Player p = entity.asPlayer(); + if (p.getSpellBookManager().getSpellBook() == 193 && p.getSkullManager().getLevel() >= 1 && p.getSkullManager().getLevel() <= 48) { + return true; + } + } + } + + return false; + } /** * Checks if the death should start for an entity. From f2aad1c95712f2449118b6467ea6fd553dc26ccf Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 18:05:16 -0700 Subject: [PATCH 098/306] Allow Ancient Teleports to bypass the isTeleBlocked function so that they work in the wilderness Note that they are still restricted by the checks in the ZoneMonitor file, which does include teleblock checks, as well as specific wilderness levels. --- .../main/core/game/node/entity/player/link/TeleportManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/player/link/TeleportManager.java b/Server/src/main/core/game/node/entity/player/link/TeleportManager.java index 140ecf405..147337cc5 100644 --- a/Server/src/main/core/game/node/entity/player/link/TeleportManager.java +++ b/Server/src/main/core/game/node/entity/player/link/TeleportManager.java @@ -99,7 +99,7 @@ public class TeleportManager { if (!entity.getZoneMonitor().teleport(teleportType, null)) { return false; } - if (teleportType != -1 && entity.isTeleBlocked()) { + if (teleportType != -1 && type != TeleportType.ANCIENT && entity.isTeleBlocked()) { if (entity.isPlayer()) entity.asPlayer().sendMessage("A magical force has stopped you from teleporting."); return false; From ac14e7a22e7635d955fa8dd22e001a1ced50a144 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 18:29:55 -0700 Subject: [PATCH 099/306] Remove last check preventing Ancient Magicks from working in wilderness. --- .../global/skill/magic/ancient/AncientTeleportPlugin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/global/skill/magic/ancient/AncientTeleportPlugin.java b/Server/src/main/content/global/skill/magic/ancient/AncientTeleportPlugin.java index 3944c3c7e..ec6c8999c 100644 --- a/Server/src/main/content/global/skill/magic/ancient/AncientTeleportPlugin.java +++ b/Server/src/main/content/global/skill/magic/ancient/AncientTeleportPlugin.java @@ -51,10 +51,12 @@ public final class AncientTeleportPlugin extends MagicSpell { @Override public boolean cast(Entity entity, Node target) { + /* Snowscape Custom to allow teleporting in wilderness. The teleport limitations are still checked later by the send() function, so this is not if (entity.isTeleBlocked() || !super.meetsRequirements(entity, true, false)) { entity.asPlayer().sendMessage("A magical force has stopped you from teleporting."); return false; } + */ if (entity.getTeleporter().send(location.transform(0, RandomFunction.random(3), 0), getSpellId() == 28 ? TeleportType.HOME : TeleportType.ANCIENT)) { if (!super.meetsRequirements(entity, true, true)) { entity.getTeleporter().getCurrentTeleport().stop(); From 62463576cf0b0513c494e7d6fc9e5a8d95cff4c0 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 19:14:58 -0700 Subject: [PATCH 100/306] Herb cleaning is now a pulse that cleans all the matching herbs in your inventory --- .../skill/herblore/HerbCleanListener.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt index 7ba8cfe5a..3189ba640 100644 --- a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt +++ b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt @@ -7,6 +7,9 @@ import core.game.node.entity.skill.Skills import core.game.node.item.Item import java.util.* +import core.game.system.task.Pulse + + /** * Dirty herb cleaning listener * @author Woah @@ -19,16 +22,35 @@ class HerbCleanListener : InteractionListener { val herb: Herbs = Herbs.forItem(node as Item) ?: return@on true if (getDynLevel(player, Skills.HERBLORE) < herb.level) { - sendMessage(player, "You cannot clean this herb. You need a Herblore level of " + herb.level + " to attempt this.") + sendMessage(player, "You need level " + herb.level + " Herblore to clean the " + herb.product.name.replace("Clean", "Grimy") + ".") return@on true } val exp = herb.experience + + player.pulseManager.run(object : Pulse() { + var counter = 0 + override fun pulse(): Boolean { + if (amountInInventory(player, node.asItem().id) == 0 ) + return true + if(removeItem(player, node.asItem().id)) { + addItem(player, herb.product.id) + rewardXP(player, Skills.HERBLORE, exp) + playAudio(player, 5153) + //sendMessage(player, "You clean the dirt from the " + herb.product.name.lowercase(Locale.getDefault()).replace("clean", "").trim { it <= ' ' } + " leaf.") + } + return false + } + }) + return@on true + + /* Vanilla actions, replaced by pulse above replaceSlot(player, node.asItem().slot, herb.product, node.asItem()) rewardXP(player, Skills.HERBLORE, exp) playAudio(player, 5153) sendMessage(player, "You clean the dirt from the " + herb.product.name.lowercase(Locale.getDefault()).replace("clean", "").trim { it <= ' ' } + " leaf.") return@on true + */ } } } \ No newline at end of file From 2e68ac1522d23cb605362d83333f8f5ec856fbc8 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 19:16:53 -0700 Subject: [PATCH 101/306] Fixed overwritten herb cleaning line --- .../src/main/content/global/skill/herblore/HerbCleanListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt index 3189ba640..a2cd826d1 100644 --- a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt +++ b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt @@ -22,7 +22,7 @@ class HerbCleanListener : InteractionListener { val herb: Herbs = Herbs.forItem(node as Item) ?: return@on true if (getDynLevel(player, Skills.HERBLORE) < herb.level) { - sendMessage(player, "You need level " + herb.level + " Herblore to clean the " + herb.product.name.replace("Clean", "Grimy") + ".") + sendMessage(player, "You cannot clean this herb. You need a Herblore level of " + herb.level + " to attempt this.") return@on true } From 563fcc23bc4e24eec8914d87ee8c5957699a2184 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 21:43:20 -0700 Subject: [PATCH 102/306] Farming patches now return the seeds if the plant being cleared or harvested is fully grown --- .../src/main/content/global/skill/farming/Patch.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Server/src/main/content/global/skill/farming/Patch.kt b/Server/src/main/content/global/skill/farming/Patch.kt index c9f90b4a9..3ec029a89 100644 --- a/Server/src/main/content/global/skill/farming/Patch.kt +++ b/Server/src/main/content/global/skill/farming/Patch.kt @@ -350,6 +350,19 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl } fun clear(){ + if (isGrown()) { + var seedAmount = 1 + var seedMessage = "a seed" + if (patch.type == PatchType.ALLOTMENT || plantable!! == Plantable.JUTE_SEED) { + seedAmount = 3 + seedMessage = "some seeds" + } else if (patch.type == PatchType.HOPS_PATCH) { + seedAmount = 4 + seedMessage = "some seeds" + } + addItemOrDrop(player, plantable!!.itemID, seedAmount) + sendMessage(player, "You find $seedMessage in the patch as you clear it.") + } isCheckHealth = false isDiseased = false isDead = false From 65cb778a187489e569ba734f461efc2cd5e99329 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 11 Nov 2024 22:16:17 -0700 Subject: [PATCH 103/306] Hunter traps last 10 minutes instead of 1 minute --- Server/src/main/content/global/skill/hunter/TrapWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/hunter/TrapWrapper.java b/Server/src/main/content/global/skill/hunter/TrapWrapper.java index 4cbe32987..b596d864c 100644 --- a/Server/src/main/content/global/skill/hunter/TrapWrapper.java +++ b/Server/src/main/content/global/skill/hunter/TrapWrapper.java @@ -102,7 +102,7 @@ public final class TrapWrapper { this.type = type; this.object = object; this.originalId = object.getId(); - this.ticks = GameWorld.getTicks() + (100); + this.ticks = GameWorld.getTicks() + (1000); this.instance = HunterManager.getInstance(player); this.object.getAttributes().setAttribute("trap-uid", instance.getUid()); } From d92a3f3a8e528bd7dc8b2db768daaa01eb8a808f Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 12 Nov 2024 06:24:27 -0700 Subject: [PATCH 104/306] Increase bird snare feather drops from 8 to 60 As part of the plan to make self-sufficient fletching more viable. --- .../src/main/content/global/skill/hunter/Traps.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/global/skill/hunter/Traps.java b/Server/src/main/content/global/skill/hunter/Traps.java index f2151d660..e5e30ca34 100644 --- a/Server/src/main/content/global/skill/hunter/Traps.java +++ b/Server/src/main/content/global/skill/hunter/Traps.java @@ -21,12 +21,12 @@ import static core.api.ContentAPIKt.log; */ public enum Traps { BIRD_SNARE(new TrapSetting(10006, new int[] { 19175 }, new int[] {}, "lay", 19174, Animation.create(5208), Animation.create(5207), 1), - new TrapNode(new int[] { 5073 }, 1, 34, new int[] { 19179, 19180 }, new Item[] { new Item(10088, 8), new Item(9978), new Item(526) }), - new TrapNode(new int[] { 5075 }, 5, 48, new int[] { 19183, 19184 }, new Item[] { new Item(10090, 8), new Item(9978), new Item(526) }), - new TrapNode(new int[] { 5076 }, 9, 61, new int[] { 19185, 19186 }, new Item[] { new Item(10091, 8), new Item(9978), new Item(526) }), - new TrapNode(new int[] { 5074 }, 11, 64.7, new int[] { 19181, 19182 }, new Item[] { new Item(10089, 8), new Item(9978), new Item(526) }), - new TrapNode(new int[] { 5072 }, 19, 95.2, new int[] { 19177, 19178 }, new Item[] { new Item(10087, 8), new Item(9978), new Item(526) }), - new TrapNode(new int[] { 7031 }, 39, 167, new int[] { 28931, 28930 }, new Item[] { new Item(11525, 8), new Item(9978), new Item(526) }) { + new TrapNode(new int[] { 5073 }, 1, 34, new int[] { 19179, 19180 }, new Item[] { new Item(10088, 60), new Item(9978), new Item(526) }), + new TrapNode(new int[] { 5075 }, 5, 48, new int[] { 19183, 19184 }, new Item[] { new Item(10090, 60), new Item(9978), new Item(526) }), + new TrapNode(new int[] { 5076 }, 9, 61, new int[] { 19185, 19186 }, new Item[] { new Item(10091, 60), new Item(9978), new Item(526) }), + new TrapNode(new int[] { 5074 }, 11, 64.7, new int[] { 19181, 19182 }, new Item[] { new Item(10089, 60), new Item(9978), new Item(526) }), + new TrapNode(new int[] { 5072 }, 19, 95.2, new int[] { 19177, 19178 }, new Item[] { new Item(10087, 60), new Item(9978), new Item(526) }), + new TrapNode(new int[] { 7031 }, 39, 167, new int[] { 28931, 28930 }, new Item[] { new Item(11525, 60), new Item(9978), new Item(526) }) { @Override public boolean canCatch(TrapWrapper wrapper, final NPC npc) { return false; From 9143cd5f47aa103305e2fc1861e167c0e2a69543 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 12 Nov 2024 07:52:06 -0700 Subject: [PATCH 105/306] Fixed getting slayer exp from hunting --- .../src/main/content/global/skill/slayer/SlayerManager.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/slayer/SlayerManager.kt b/Server/src/main/content/global/skill/slayer/SlayerManager.kt index 1bcf56803..f0ff71ed5 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerManager.kt +++ b/Server/src/main/content/global/skill/slayer/SlayerManager.kt @@ -13,6 +13,8 @@ import org.json.simple.JSONObject import java.util.* import org.rs09.consts.Items +import content.global.skill.hunter.HunterNPC + /** * Manages the players slayer data. * @author Ceikry @@ -102,7 +104,9 @@ class SlayerManager(val player: Player? = null) : LoginListener, PersistPlayer, val slayer = getInstance(player) val flags = slayer.flags var xp = npc.skills.maximumLifepoints.toDouble() - rewardXP(player, Skills.SLAYER, xp/3) + //Snowscape custom: grant a third of the normal slayer exp on all kills (this stacks with the exp from on-task kills) + if (npc !is HunterNPC) + rewardXP(player, Skills.SLAYER, xp/3) if (slayer.hasTask() && npc.id in slayer.task!!.npcs) { From 3035aaa7e6caaccc178aaf671505ec7d4faeea2c Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 12 Nov 2024 15:00:37 -0700 Subject: [PATCH 106/306] Implemented proper probabilities when using the Ourania altar --- .../skill/runecrafting/RuneCraftPulse.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index aff74d903..77e21b7f2 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -217,7 +217,9 @@ public final class RuneCraftPulse extends SkillPulse { player.getPacketDispatch().sendMessage("You bind the temple's power into runes."); player.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_RC, amount); for (int i = 0; i < amount; i++) { - Rune rune = null; + Rune rune = getOuraniaRune(player.getSkills().getLevel(Skills.RUNECRAFTING)); + /* Snowscape: removed this placeholder formula and implemented the real ourania probabilities. The multiplier on Orania runes is also a custom feature. + Rune rune = null; while (rune == null) { final Rune temp = Rune.values()[RandomFunction.random(Rune.values().length)]; if (player.getSkills().getLevel(Skills.RUNECRAFTING) >= temp.getLevel()) { @@ -228,6 +230,7 @@ public final class RuneCraftPulse extends SkillPulse { } } } + */ player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * 2, true); Item runeItem = new Item(rune.getRune().getId(),getMultiplier(rune)); player.getInventory().add(runeItem); @@ -396,6 +399,38 @@ public final class RuneCraftPulse extends SkillPulse { public boolean hasBindingNecklace() { return player.getEquipment().containsItem(BINDING_NECKLACE); } + + /** + * Method used to get a random rune for the Ourania altar based on runecrafting level. + * Todo: This should probably use a weighted table but I couldn't figure them out. + * @return the randomly selected rune. + */ + public static Rune getOuraniaRune(int rcLevel) { + int random = RandomFunction.random(10000); + if (rcLevel >= 99) { + if (random > 9100) { return Rune.SOUL; } else if (random > 7800) { return Rune.BLOOD; } else if (random > 6250) { return Rune.DEATH; } else if (random > 4800) { return Rune.LAW; } else if (random > 3450) { return Rune.NATURE; } else if (random > 2500) { return Rune.ASTRAL; } else if (random > 1900) { return Rune.CHAOS; } else if (random > 1400) { return Rune.COSMIC; } else if (random > 1000) { return Rune.BODY; } else if (random > 700) { return Rune.FIRE; } else if (random > 400) { return Rune.EARTH; } else if (random > 200) { return Rune.WATER; } else if (random > 100) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 90) { + if (random > 9350) { return Rune.SOUL; } else if (random > 8350) { return Rune.BLOOD; } else if (random > 6700) { return Rune.DEATH; } else if (random > 5250) { return Rune.LAW; } else if (random > 3900) { return Rune.NATURE; } else if (random > 2900) { return Rune.ASTRAL; } else if (random > 2200) { return Rune.CHAOS; } else if (random > 1600) { return Rune.COSMIC; } else if (random > 1100) { return Rune.BODY; } else if (random > 700) { return Rune.FIRE; } else if (random > 400) { return Rune.EARTH; } else if (random > 200) { return Rune.WATER; } else if (random > 100) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 80) { + if (random > 9600) { return Rune.SOUL; } else if (random > 9000) { return Rune.BLOOD; } else if (random > 7550) { return Rune.DEATH; } else if (random > 6100) { return Rune.LAW; } else if (random > 4750) { return Rune.NATURE; } else if (random > 3700) { return Rune.ASTRAL; } else if (random > 2900) { return Rune.CHAOS; } else if (random > 2200) { return Rune.COSMIC; } else if (random > 1600) { return Rune.BODY; } else if (random > 700) { return Rune.FIRE; } else if (random > 400) { return Rune.EARTH; } else if (random > 200) { return Rune.WATER; } else if (random > 100) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 70) { + if (random > 9800) { return Rune.SOUL; } else if (random > 9300) { return Rune.BLOOD; } else if (random > 8300) { return Rune.DEATH; } else if (random > 6500) { return Rune.LAW; } else if (random > 5000) { return Rune.NATURE; } else if (random > 3800) { return Rune.ASTRAL; } else if (random > 2900) { return Rune.CHAOS; } else if (random > 2200) { return Rune.COSMIC; } else if (random > 1700) { return Rune.BODY; } else if (random > 1300) { return Rune.FIRE; } else if (random > 900) { return Rune.EARTH; } else if (random > 600) { return Rune.WATER; } else if (random > 300) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 60) { + if (random > 9900) { return Rune.SOUL; } else if (random > 9700) { return Rune.BLOOD; } else if (random > 9300) { return Rune.DEATH; } else if (random > 8500) { return Rune.LAW; } else if (random > 6950) { return Rune.NATURE; } else if (random > 5550) { return Rune.ASTRAL; } else if (random > 4500) { return Rune.CHAOS; } else if (random > 3550) { return Rune.COSMIC; } else if (random > 2800) { return Rune.BODY; } else if (random > 2100) { return Rune.FIRE; } else if (random > 1500) { return Rune.EARTH; } else if (random > 950) { return Rune.WATER; } else if (random > 450) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 50) { + if (random > 9920) { return Rune.SOUL; } else if (random > 9750) { return Rune.BLOOD; } else if (random > 9400) { return Rune.DEATH; } else if (random > 8700) { return Rune.LAW; } else if (random > 7350) { return Rune.NATURE; } else if (random > 5850) { return Rune.ASTRAL; } else if (random > 4750) { return Rune.CHAOS; } else if (random > 3750) { return Rune.COSMIC; } else if (random > 3000) { return Rune.BODY; } else if (random > 2300) { return Rune.FIRE; } else if (random > 1650) { return Rune.EARTH; } else if (random > 1050) { return Rune.WATER; } else if (random > 500) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 40) { + if (random > 9960) { return Rune.SOUL; } else if (random > 9880) { return Rune.BLOOD; } else if (random > 9760) { return Rune.DEATH; } else if (random > 9500) { return Rune.LAW; } else if (random > 9000) { return Rune.NATURE; } else if (random > 8000) { return Rune.ASTRAL; } else if (random > 6000) { return Rune.CHAOS; } else if (random > 4500) { return Rune.COSMIC; } else if (random > 3500) { return Rune.BODY; } else if (random > 2700) { return Rune.FIRE; } else if (random > 1950) { return Rune.EARTH; } else if (random > 1250) { return Rune.WATER; } else if (random > 600) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 30) { + if (random > 9980) { return Rune.SOUL; } else if (random > 9940) { return Rune.BLOOD; } else if (random > 9880) { return Rune.DEATH; } else if (random > 9750) { return Rune.LAW; } else if (random > 9500) { return Rune.NATURE; } else if (random > 9000) { return Rune.ASTRAL; } else if (random > 8000) { return Rune.CHAOS; } else if (random > 6000) { return Rune.COSMIC; } else if (random > 4700) { return Rune.BODY; } else if (random > 3500) { return Rune.FIRE; } else if (random > 2400) { return Rune.EARTH; } else if (random > 1500) { return Rune.WATER; } else if (random > 700) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 20) { + if (random > 9992) { return Rune.SOUL; } else if (random > 9977) { return Rune.BLOOD; } else if (random > 9945) { return Rune.DEATH; } else if (random > 9890) { return Rune.LAW; } else if (random > 9780) { return Rune.NATURE; } else if (random > 9570) { return Rune.ASTRAL; } else if (random > 9150) { return Rune.CHAOS; } else if (random > 8350) { return Rune.COSMIC; } else if (random > 6750) { return Rune.BODY; } else if (random > 5250) { return Rune.FIRE; } else if (random > 3850) { return Rune.EARTH; } else if (random > 2500) { return Rune.WATER; } else if (random > 1200) { return Rune.MIND; } else { return Rune.AIR; } + } else if (rcLevel >= 10) { + if (random > 9997) { return Rune.SOUL; } else if (random > 9991) { return Rune.BLOOD; } else if (random > 9979) { return Rune.DEATH; } else if (random > 9955) { return Rune.LAW; } else if (random > 9915) { return Rune.NATURE; } else if (random > 9855) { return Rune.ASTRAL; } else if (random > 9775) { return Rune.CHAOS; } else if (random > 9600) { return Rune.COSMIC; } else if (random > 9000) { return Rune.BODY; } else if (random > 7800) { return Rune.FIRE; } else if (random > 5400) { return Rune.EARTH; } else if (random > 3300) { return Rune.WATER; } else if (random > 1500) { return Rune.MIND; } else { return Rune.AIR; } + } else { + if (random > 9998) { return Rune.SOUL; } else if (random > 9993) { return Rune.BLOOD; } else if (random > 9985) { return Rune.DEATH; } else if (random > 9970) { return Rune.LAW; } else if (random > 9940) { return Rune.NATURE; } else if (random > 9895) { return Rune.ASTRAL; } else if (random > 9835) { return Rune.CHAOS; } else if (random > 9750) { return Rune.COSMIC; } else if (random > 9600) { return Rune.BODY; } else if (random > 9300) { return Rune.FIRE; } else if (random > 8700) { return Rune.EARTH; } else if (random > 7500) { return Rune.WATER; } else if (random > 5000) { return Rune.MIND; } else { return Rune.AIR; } + } + } /** * Gets the altar. From e45f8fa81bafd99055fe2ec4a8bdfa945c1df57d Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 12 Nov 2024 16:00:02 -0700 Subject: [PATCH 107/306] Implemented rune multipliers on combination runes The altar you are at will now give its multiplier to the combination runes crafted. This only saves essence, the opposing rune cost is multiplied as well. (If you get 10 air runes per essence, then making mist runes at the air altar will cost 10 water runes and 1 essence to give you 10 mist runes). --- .../skill/runecrafting/RuneCraftPulse.java | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 77e21b7f2..5006b52be 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -239,9 +239,39 @@ public final class RuneCraftPulse extends SkillPulse { } } - /** - * Method used to combine runes. - */ + /** + * Method used to combine runes. Snowscape custom: you get multiple combination runes per essence (the opposite rune cost scales to match the multiplier) + */ + private final void combine() { + final Item remove = node.getName().contains("talisman") ? node : talisman != null ? talisman.getTalisman() : Talisman.forName(Rune.forItem(node).name()).getTalisman(); + boolean imbued = hasSpellImbue(); + if (!imbued ? player.getInventory().remove(remove) : imbued) { + int essenceAmt = player.getInventory().getAmount(PURE_ESSENCE); + int multiplier = getMultiplier(altar.getRune()); + final Item rune = node.getName().contains("rune") ? Rune.forItem(node).getRune() : Rune.forName(Talisman.forItem(node).name()).getRune(); + for (int i = 0; i < essenceAmt; i++) { + int runeAmt = player.getInventory().getAmount(rune); + if (runeAmt > 0 && player.getInventory().remove(new Item(PURE_ESSENCE.getId(),1))) { + if (runeAmt < multiplier) { + multiplier = runeAmt; + } + player.getInventory().remove(new Item(rune.getId(), multiplier)); + if (RandomFunction.random(2) == 1 || hasBindingNecklace()) { + player.getInventory().add(new Item(combo.getRune().getId(), multiplier)); + player.getSkills().addExperience(Skills.RUNECRAFTING, combo.getExperience(), true); + } + } + } + if (hasBindingNecklace()) { + player.getEquipment().get(EquipmentContainer.SLOT_AMULET).setCharge(player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() - 1); + if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() > 14) { + player.getEquipment().remove(BINDING_NECKLACE, true); + player.getPacketDispatch().sendMessage("Your binding necklace crumbles into dust."); + } + } + } + } + /* Original function, replaced by snowscape custom above private final void combine() { final Item remove = node.getName().contains("talisman") ? node : talisman != null ? talisman.getTalisman() : Talisman.forName(Rune.forItem(node).name()).getTalisman(); boolean imbued = hasSpellImbue(); @@ -272,7 +302,7 @@ public final class RuneCraftPulse extends SkillPulse { } } } - +*/ /** * Method used to craft tablets. Custom for Snowscape */ From 0b0542469078178e683a77e09a239930a11e20cb Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 12 Nov 2024 21:04:11 -0700 Subject: [PATCH 108/306] Changed Imp-in-a-box to act a full deposit box. One-time use. The Imp-in-a-box is broken, and I don't know how to fix it so I buffed it instead. --- .../src/main/content/global/skill/hunter/ImpBoxPlugin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Server/src/main/content/global/skill/hunter/ImpBoxPlugin.java b/Server/src/main/content/global/skill/hunter/ImpBoxPlugin.java index 800e342eb..a1cf25062 100644 --- a/Server/src/main/content/global/skill/hunter/ImpBoxPlugin.java +++ b/Server/src/main/content/global/skill/hunter/ImpBoxPlugin.java @@ -46,10 +46,16 @@ public class ImpBoxPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { switch (option) { case "bank": + int boxSlot = node.asItem().getSlot(); + player.getInventory().replace(new Item(10025), boxSlot); + player.sendMessage("You free the imp in exchange for it taking some items to your bank."); + player.getBank().openDepositBox(); + /* Snowscape Custom: the normal imp interface is broken, so we fixed/buffed it by making it act as a one-time-use deposit box instead. Component component = new Component(478); component.setPlugin(new ImpInterfaceHandler((Item) node)); player.getInterfaceManager().open(component); PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 478, 61, 91, player.getInventory(), true)); + */ break; case "talk-to": player.getDialogueInterpreter().open("imp-box"); From a6ad4f8f3b8c0f406c57b327a893747e62540db9 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 13 Nov 2024 14:10:24 -0700 Subject: [PATCH 109/306] High Alching Ring of Wealth now adds permanent unlock. --- .../skill/magic/modern/ModernListeners.kt | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 0d35ef56a..d56b8230b 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -230,6 +230,23 @@ class ModernListeners : SpellListener("modern"){ return false } + var loop = true + + val ringOfWealth = intArrayOf(14646,14644,14642,14640,14638) + if(high && ringOfWealth.contains(item.id)){ + if (getAttribute(player, "ringofwealth:unlocked", false)) { + player.sendMessage("You have already unlocked the permanent Wealth effect and can no longer ") + player.sendMessage("alchemize this ring.") + return false + } else { + player.setAttribute("/save:ringofwealth:unlocked", true) + player.sendMessage("Combining the Alchemy spell with the Wealth enchantment causes a strange ") + player.sendMessage("interaction. You are now permanently enchanted with the Wealth effect and ") + player.sendMessage("no longer need to wear the ring to get the benefit of increased rare drops.") + loop = false + } + } + if (player.pulseManager.current !is MovementPulse) { player.pulseManager.clear() } @@ -265,8 +282,12 @@ class ModernListeners : SpellListener("modern"){ //showMagicTab(player) setDelay(player, 5) } - counter++ - return false + if (loop) { + counter++ + return false + } else { + return true + } } }) return true From e7ed5b0d7ae58283824138f91d11ba7a43513f71 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 13 Nov 2024 14:23:17 -0700 Subject: [PATCH 110/306] Added check to allow permanant unlock to act as a worn ring of wealth This only affects NPC drops, not gem drops from mining. Due to this affecting the rare drop table only, this has not been tested. --- Server/src/main/core/api/ContentAPI.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 84d41d69a..daf3c8625 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -279,7 +279,16 @@ fun hasGodItem(player: Player, god: God): Boolean { */ fun shouldRemoveNothings(player: Player) : Boolean { val ring = getItemFromEquipment(player, EquipmentSlot.RING) - return ring != null && ring.id in Items.RING_OF_WEALTH_14638..Items.RING_OF_WEALTH4_14646 + if (getAttribute(player, "ringofwealth:unlocked", false)){ + player.sendMessage("Your Wealth enchantment coaxes a rare drop from your opponent.") + return true + } else if (ring != null && ring.id in Items.RING_OF_WEALTH_14638..Items.RING_OF_WEALTH4_14646) { + player.sendMessage("Your Ring of Wealth coaxes a rare drop from your opponent.") + player.sendMessage("The magic in the ring reminds you of the High Level Alchemy spell for some reason.") + return true + } else { + return false + } } /** From 964c95b572ed55c8d1f41d68bb13a64135c44da3 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 13 Nov 2024 15:21:17 -0700 Subject: [PATCH 111/306] Fixed noncombat spells getting the 33% chance to not use runes. --- .../main/core/game/node/entity/combat/spell/MagicSpell.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index 6259add5a..86b7e1260 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -201,9 +201,9 @@ public abstract class MagicSpell implements Plugin { if (!checkLevelRequirement(caster, message)) { return false; } + /* Snowscape custom. Removing this allows guthix staff to autocast claws of guthix. if (caster instanceof Player) { CombatSpell spell = ((Player) caster).getProperties().getAutocastSpell(); - /* Snowscape custom. Removing this allows guthix staff to autocast claws of guthix. if (spell != null) { boolean slayer = ((Player) caster).getEquipment().get(3).getName().contains("layer's staff"); boolean voidKnight = ((Player) caster).getEquipment().get(3).getName().contains("knight mace"); @@ -212,8 +212,8 @@ public abstract class MagicSpell implements Plugin { return false; } } - */ } + */ if((spellId == 12 || spellId == 30 || spellId == 56) && caster instanceof Player){ if (caster.getAttribute("entangleDelay", 0) > GameWorld.getTicks()) { caster.asPlayer().sendMessage("You have recently cast a binding spell."); @@ -223,7 +223,7 @@ public abstract class MagicSpell implements Plugin { if (caster instanceof Player) { Player p = (Player) caster; //if(p.getEquipment().get(3) != null && p.getEquipment().get(3).getId() == 14726){ - if(RandomFunction.getRandom(100) > 33){ + if(this instanceof CombatSpell && RandomFunction.getRandom(100) > 33){ //p.sendMessage("Your staff negates the rune requirement of the spell."); return true; } From 251934d3a9efa9027ad41782ce74714e045d3bb7 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 13 Nov 2024 20:51:24 -0700 Subject: [PATCH 112/306] Audded autolooting of coins and tokkul if wearing ring of wealth --- .../node/entity/npc/drop/NPCDropTables.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 7421228f7..2ce42e98c 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -104,6 +104,9 @@ public final class NPCDropTables { if (handleBoneCrusher(player, item)) { return; } + if (handleCurrency(player, item)) { + return; + } if (item.hasItemPlugin() && player != null) { if (!item.getPlugin().createDrop(item, player, npc, l)) { return; @@ -260,6 +263,25 @@ public final class NPCDropTables { player.getSkills().addExperience(Skills.PRAYER, item.getAmount() * bone.getExperience()); return true; } + + /** + * Snowscape custom: Automatically loot coins and tokkul if wearing a ring of wealth. + * @param player The player + * @param item The item + * @return true if successfully added items to player. + */ + private boolean handleCurrency(Player player, Item item) { + if (item.getId() == 995 || item.getId() == 6529) { + Item ring = player.getEquipment().get(12); + if (ring != null && ring.getId() >= 14638 && ring.getId() <=14646) { + if (player.getInventory().add(item)) { + player.sendMessage("Your Ring collected " + item.getAmount() + " " + item.getName() + "."); + return true; + } + } + } + return false; + } /** * Gets the ratio for stabilizing NPC combat difficulty & drop rates. From 2be5f9eac0f4c06fad1bf83e5afbdfe11d63f6e4 Mon Sep 17 00:00:00 2001 From: Sinipelto <7580610-Sinipelto@users.noreply.gitlab.com> Date: Thu, 14 Nov 2024 10:22:04 +0000 Subject: [PATCH 113/306] Fixed loss of combat tabs after recruitment drive --- .../falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt index f46d9c80d..d3494000a 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt @@ -305,6 +305,8 @@ class RecruitmentDriveListeners : InteractionListener { // Clear inventory whenever you leave the recruitment drive area entity.inventory.clear() entity.equipment.clear() + // Restore player normal tabs on leave + entity.interfaceManager.openDefaultTabs() // Teleport you out if you log out. You should do this in one sitting. if (logout) { PacketRepository.send(MinimapState::class.java, MinimapStateContext(entity, 0)) From a2eafa8bc03c9506c2f6db3c267d092bbe77a6a0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 10:44:00 +0000 Subject: [PATCH 114/306] Fixed exception on server boot related to a duplicated attempt to register dialogue for Jarvald --- .../region/fremennik/rellekka/dialogue/JarvaldDialogue.kt | 3 +-- .../region/fremennik/rellekka/handlers/RellekkaZone.java | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt index 7faafa16d..cdf685e13 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt @@ -200,7 +200,6 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun getIds(): IntArray { - // 2435 is a wrapper for 2436 - return intArrayOf(2435, NPCs.JARVALD_2436, NPCs.JARVALD_2437, NPCs.JARVALD_2438) + return intArrayOf(NPCs.JARVALD_2435, NPCs.JARVALD_2436, NPCs.JARVALD_2437, NPCs.JARVALD_2438) } } diff --git a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaZone.java b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaZone.java index 75d7c1e34..4698885bb 100644 --- a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaZone.java +++ b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaZone.java @@ -1,6 +1,5 @@ package content.region.fremennik.rellekka.handlers; -import content.region.fremennik.rellekka.dialogue.JarvaldDialogue; import content.region.fremennik.rellekka.dialogue.MariaGunnarsDialogue; import core.cache.def.impl.SceneryDefinition; import core.game.system.task.Pulse; @@ -41,7 +40,6 @@ public final class RellekkaZone extends MapZone implements Plugin { @Override public Plugin newInstance(Object arg) throws Throwable { ZoneBuilder.configure(this); - ClassScanner.definePlugin(new JarvaldDialogue()); ClassScanner.definePlugins(new RellekaOptionHandler(), new MariaGunnarsDialogue()); ClassScanner.definePlugin(new OptionHandler() { From ed41f3a228a9a2d7d9177cf22afa29ee1bfd3dd0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 11:02:26 +0000 Subject: [PATCH 115/306] Bounty Hunter music is now unlockable --- Server/data/configs/music_regions.json | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Server/data/configs/music_regions.json b/Server/data/configs/music_regions.json index 80dfcc0cb..ebfb70c82 100644 --- a/Server/data/configs/music_regions.json +++ b/Server/data/configs/music_regions.json @@ -2079,6 +2079,18 @@ "region": "12880", "id": "441" }, + { + "region": "12888", + "id": "445" + }, + { + "region": "12889", + "id": "445" + }, + { + "region": "12890", + "id": "445" + }, { "region": "12944", "id": "606" @@ -2199,6 +2211,18 @@ "region": "13142", "id": "459" }, + { + "region": "13144", + "id": "445" + }, + { + "region": "13145", + "id": "445" + }, + { + "region": "13146", + "id": "445" + }, { "region": "13199", "id": "388" @@ -2271,6 +2295,18 @@ "region": "13373", "id": "586" }, + { + "region": "13400", + "id": "445" + }, + { + "region": "13401", + "id": "445" + }, + { + "region": "13402", + "id": "445" + }, { "region": "13456", "id": "452" From 98c99e7550657a5705a869f8663c7bb4118039f5 Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 11:06:41 +0000 Subject: [PATCH 116/306] POH telescope now estimates the shooting star time based on its tier --- .../decoration/study/TelescopePlugin.kt | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/decoration/study/TelescopePlugin.kt b/Server/src/main/content/global/skill/construction/decoration/study/TelescopePlugin.kt index 6149fae5e..ea1d8c783 100644 --- a/Server/src/main/content/global/skill/construction/decoration/study/TelescopePlugin.kt +++ b/Server/src/main/content/global/skill/construction/decoration/study/TelescopePlugin.kt @@ -26,25 +26,31 @@ class TelescopePlugin : OptionHandler() { } override fun handle(player: Player?, node: Node?, option: String?): Boolean { + val obj = node?.asScenery() as Scenery val star = ShootingStarPlugin.getStar() val delay: Int = 25000 + (25000 / 3) val timeLeft = delay - star.ticks - val fakeTimeLeftBecauseFuckPlayers = TimeUnit.MILLISECONDS.toMinutes(timeLeft * 600L) + if(RandomFunction.random(0,100) % 2 == 0) 2 else -2 - val obj = node?.asScenery() as Scenery + val window = when (obj.id) { + 13657 -> 9 + 13658 -> 2 + else -> 24 + } + val fakeTimeLeft = RandomFunction.random(-window, window+1) + TimeUnit.MILLISECONDS.toMinutes(timeLeft * 600L) player?.lock() player?.animate(ANIMATION) - player?.interfaceManager?.open(Component(782)).also { player?.unlock() - Pulser.submit(object : Pulse(2, player) { - override fun pulse(): Boolean { - if (obj.isActive) { - player?.dialogueInterpreter?.sendDialogue("You see a shooting star! The star looks like it will land","in about $fakeTimeLeftBecauseFuckPlayers minutes!") + player?.interfaceManager?.open(Component(782)).also { + player?.unlock() + Pulser.submit(object : Pulse(2, player) { + override fun pulse(): Boolean { + if (obj.isActive) { + player?.dialogueInterpreter?.sendDialogue("You see a shooting star! The star looks like it will land","in about $fakeTimeLeft minutes!") + return true + } return true } - return true - } - }) - return true - } + }) + return true + } } companion object { From b0be48501b1b61a1e0cecbcb42d606dd9660b6bc Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 11:18:25 +0000 Subject: [PATCH 117/306] Made the following POH hotspots refund their non-plank items when torn down: any quest item, any guild trophy, any armor stand Refactored some construction code Removed decorations and hotspots for "Menagerie" rooms, which seem to be inauthentic Changed the following hotspots to be recursive: decoration, wall chart (study) Corrected xp for a few construction items --- .../skill/construction/BuildHotspot.java | 27 +- .../skill/construction/BuildingUtils.java | 6 +- .../global/skill/construction/Decoration.java | 1556 +++++++---------- .../decoration/questhall/MountedGlory.kt | 24 +- 4 files changed, 649 insertions(+), 964 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildHotspot.java b/Server/src/main/content/global/skill/construction/BuildHotspot.java index 32a461b9f..c5ca6c8e7 100644 --- a/Server/src/main/content/global/skill/construction/BuildHotspot.java +++ b/Server/src/main/content/global/skill/construction/BuildHotspot.java @@ -59,7 +59,7 @@ public enum BuildHotspot { DINING_BENCH_1(15300, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_MID_ANIM, Decoration.BENCH_WOODEN, Decoration.BENCH_OAK, Decoration.BENCH_CARVED_OAK, Decoration.BENCH_TEAK, Decoration.BENCH_CARVED_TEAK, Decoration.BENCH_MAHOGANY, Decoration.BENCH_GILDED), DINING_BENCH_2(15299, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_MID_ANIM, Decoration.BENCH_WOODEN, Decoration.BENCH_OAK, Decoration.BENCH_CARVED_OAK, Decoration.BENCH_TEAK, Decoration.BENCH_CARVED_TEAK, Decoration.BENCH_MAHOGANY,Decoration.BENCH_GILDED), ROPE_BELL_PULL(15304, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.ROPE_PULL, Decoration.BELL_PULL, Decoration.FANCY_BELL_PULL), - WALL_DECORATION(15303, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.OAK_DECORATION, Decoration.TEAK_DECORATION, Decoration.GILDED_DECORATION), + WALL_DECORATION(15303, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.OAK_DECORATION, Decoration.TEAK_DECORATION, Decoration.GILDED_DECORATION), /** * Low-level Work shop hotspots. @@ -67,11 +67,11 @@ public enum BuildHotspot { REPAIR(15448, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.REPAIR_BENCH, Decoration.WHETSTONE, Decoration.ARMOUR_STAND), WORKBENCH(15439, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.WORKBENCH_WOODEN, Decoration.WORKBENCH_OAK,Decoration.WORKBENCH_STEEL_FRAME, Decoration.WORKBENCH_WITH_VICE,Decoration.WORKBENCH_WITH_LATHE), CRAFTING(15441, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.CRAFTING_TABLE_1, Decoration.CRAFTING_TABLE_2,Decoration.CRAFTING_TABLE_3, Decoration.CRAFTING_TABLE_4), - TOOL1(15443, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2, Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4, Decoration.TOOL_STORE_5), - TOOL2(15444, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), - TOOL3(15445, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), - TOOL4(15446, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), - TOOL5(15447, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), + TOOL1(15443, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2, Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4, Decoration.TOOL_STORE_5), + TOOL2(15444, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), + TOOL3(15445, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), + TOOL4(15446, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), + TOOL5(15447, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.TOOL_STORE_1, Decoration.TOOL_STORE_2,Decoration.TOOL_STORE_3, Decoration.TOOL_STORE_4,Decoration.TOOL_STORE_5), HERALDRY(15450, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.PLUMING_STAND, Decoration.SHIELD_EASEL,Decoration.BANNER_EASEL), /** @@ -188,20 +188,10 @@ public enum BuildHotspot { MAP(15396, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.SMALL_MAP, Decoration.MEDIUM_MAP, Decoration.LARGE_MAP), BOOKCASE2(15397, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.WOODEN_BOOKCASE, Decoration.OAK_BOOKCASE, Decoration.MAHOGANY_BOOKCASE), - /** - * Manegerie Hotspots - */ - OBELISK(44911, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.MINI_OBELISK), - PET_FEEDER(44910, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.OAK_PET_FEEDER, Decoration.TEAK_PET_FEEDER, Decoration.MAHOGANY_PET_FEEDER), - PET_HOUSE(44909, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.OAK_PET_HOUSE, Decoration.TEAK_PET_HOUSE, Decoration.MAHOGANY_PET_HOUSE, Decoration.CONSECRATED_PET_HOUSE, Decoration.DESECRATED_PET_HOUSE, Decoration.NATURAL_PET_HOUSE), - HABITAT_1(44907, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.GARDEN_HABITAT, Decoration.JUNGLE_HABITAT, Decoration.DESERT_HABITAT, Decoration.POLAR_HABITAT, Decoration.VOLCANIC_HABITAT), - HABITAT_2(44908, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.GARDEN_HABITAT, Decoration.JUNGLE_HABITAT, Decoration.DESERT_HABITAT, Decoration.POLAR_HABITAT, Decoration.VOLCANIC_HABITAT), - - /** * Combat room hotspots. */ - WALL_DECORATION2(15297, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.OAK_DECORATION, Decoration.TEAK_DECORATION, Decoration.GILDED_DECORATION), + WALL_DECORATION2(15297, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.OAK_DECORATION, Decoration.TEAK_DECORATION, Decoration.GILDED_DECORATION), STORAGE_SPACE(15296, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.GLOVE_RACK, Decoration.WEAPONS_RACK, Decoration.EXTRA_WEAPONS_RACK), CR_RING(15277, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.BOXING_RING, Decoration.FENCING_RING, Decoration.COMBAT_RING, Decoration.NOTHING, Decoration.NOTHING2), CR_CORNER(15278, BuildHotspotType.LINKED, BuildingUtils.BUILD_MID_ANIM, Decoration.BOXING_RING, Decoration.FENCING_RING, Decoration.COMBAT_RING, Decoration.NOTHING, Decoration.NOTHING2), @@ -238,7 +228,7 @@ public enum BuildHotspot { LECTERN(15420, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.OAK_LECTERN, Decoration.EAGLE_LECTERN, Decoration.DEMON_LECTERN, Decoration.TEAK_EAGLE_LECTERN, Decoration.TEAK_DEMON_LECTERN, Decoration.MAHOGANY_EAGLE_LECTERN, Decoration.MAHOGANY_DEMON_LECTERN), CRYSTAL_BALL(15422, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.CRYSTAL_BALL, Decoration.ELEMENTAL_SPHERE, Decoration.CRYSTAL_OF_POWER), BOOKCASE3(15425, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.WOODEN_BOOKCASE, Decoration.OAK_BOOKCASE, Decoration.MAHOGANY_BOOKCASE), - WALL_CHART(15423, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_HIGH_ANIM, Decoration.ALCHEMICAL_CHART, Decoration.ASTRONOMICAL_CHART, Decoration.INFERNAL_CHART), + WALL_CHART(15423, BuildHotspotType.RECURSIVE, BuildingUtils.BUILD_HIGH_ANIM, Decoration.ALCHEMICAL_CHART, Decoration.ASTRONOMICAL_CHART, Decoration.INFERNAL_CHART), TELESCOPE(15424, BuildHotspotType.INDIVIDUAL, BuildingUtils.BUILD_MID_ANIM, Decoration.TELESCOPE1, Decoration.TELESCOPE2, Decoration.TELESCOPE3), /** @@ -394,7 +384,6 @@ public enum BuildHotspot { linkedHotspots.add(new BuildHotspot[] { PRISON, PRISON_DOOR }); linkedHotspots.add(new BuildHotspot[] { DUNGEON_DOOR_LEFT, DUNGEON_DOOR_RIGHT }); linkedHotspots.add(new BuildHotspot[] { DUNGEON_DOOR_LEFT2, DUNGEON_DOOR_RIGHT2 }); - linkedHotspots.add(new BuildHotspot[] { HABITAT_1, HABITAT_2 }); linkedHotspots.add(new BuildHotspot[] { SMALL_PLANT_1, SMALL_PLANT1 }); linkedHotspots.add(new BuildHotspot[] { SHELVES, SHELVES_2 }); } diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index 424e5aa94..02bfbd9c2 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -349,7 +349,7 @@ public final class BuildingUtils { */ public static void removeDecoration(Player player, Scenery object) { if (object.getId() == Decoration.PORTAL.getObjectId() && player.getHouseManager().getPortalAmount() <= 1) { - player.getPacketDispatch().sendMessage("You need atleast one portal, how else would you leave your house?"); + sendMessage(player, "You need at least one portal, how else would you leave your house?"); return; } Location l = object.getLocation(); @@ -369,6 +369,10 @@ public final class BuildingUtils { if (objectId == object.getId() && hotspot.getCurrentX() == l.getChunkOffsetX() && hotspot.getCurrentY() == l.getChunkOffsetY()) { player.animate(REMOVE_ANIMATION); removeDecoration(player, region, room, hotspot, object, style); + Decoration decoration = Decoration.forObjectId(object.getId()); + for (Item item : decoration.getRefundItems()) { + addItemOrDrop(player, item.getId(), item.getAmount()); + } break; } } diff --git a/Server/src/main/content/global/skill/construction/Decoration.java b/Server/src/main/content/global/skill/construction/Decoration.java index 058de5a8b..6229dff82 100644 --- a/Server/src/main/content/global/skill/construction/Decoration.java +++ b/Server/src/main/content/global/skill/construction/Decoration.java @@ -1,6 +1,4 @@ package content.global.skill.construction; - - import core.game.node.entity.player.Player; import core.game.node.item.Item; import core.game.node.scenery.Scenery; @@ -9,1071 +7,690 @@ import org.rs09.consts.Items; /** * Represents the decorations. - * @author Emperor + * @author Emperor, Player Name * */ public enum Decoration { - /** * Garden centrepiece decorations. */ - PORTAL(13405, 8168, 1, 100.0, new Item(Items.IRON_BAR_2351, 10)), - ROCK(13406, 8169, 5, 100.0, new Item(Items.LIMESTONE_BRICK_3420, 5)), - POND(13407, 8170, 10, 100.0, new Item(Items.SOFT_CLAY_1761, 10)), - IMP_STATUE(13408, 8171, 15, 150.0, new Item(Items.LIMESTONE_BRICK_3420, 5), new Item(Items.SOFT_CLAY_1761, 5)), - SMALL_OBELISK(42004, 14657, 41, 676, new Item(Items.MARBLE_BLOCK_8786, 1), new Item(Items.SPIRIT_SHARDS_12183, 1000), new Item(Items.CRIMSON_CHARM_12160, 10), new Item(Items.BLUE_CHARM_12163, 10)), - DUNGEON_ENTRANCE(13409, 8172, 70, 500.0, new Item(Items.MARBLE_BLOCK_8786)), + PORTAL (13405, 8168, 1, 100, new Item[] { new Item(Items.IRON_BAR_2351, 10) }), + ROCK (13406, 8169, 5, 100, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 5) }), + POND (13407, 8170, 10, 100, new Item[] { new Item(Items.SOFT_CLAY_1761, 10) }), + IMP_STATUE (13408, 8171, 15, 150, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 5), new Item(Items.SOFT_CLAY_1761, 5) }), + SMALL_OBELISK (42004, 14657, 41, 676, new Item[] { new Item(Items.MARBLE_BLOCK_8786), new Item(Items.SPIRIT_SHARDS_12183, 1000), new Item(Items.CRIMSON_CHARM_12160, 10), new Item(Items.BLUE_CHARM_12163, 10) }), + DUNGEON_ENTRANCE(13409, 8172, 70, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), - /** * Garden big tree decorations. */ - BIG_DEAD_TREE(13411, 8173, 5, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_DEAD_TREE_8417)), - BIG_TREE(13412, 8174, 10, 44.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_NICE_TREE_8419)), - BIG_OAK_TREE(13413, 8175, 15, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_OAK_TREE_8421)), - BIG_WILLOW_TREE(13414, 8176, 30, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_WILLOW_TREE_8423)), - BIG_MAPLE_TREE(13415, 8177, 45, 122.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MAPLE_TREE_8425)), - BIG_YEW_TREE(13416, 8178, 60, 141.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_YEW_TREE_8427)), - BIG_MAGIC_TREE(13417, 8179, 75, 223.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MAGIC_TREE_8429)), - + BIG_DEAD_TREE (13411, 8173, 5, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_DEAD_TREE_8417) }), + BIG_TREE (13412, 8174, 10, 44, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_NICE_TREE_8419) }), + BIG_OAK_TREE (13413, 8175, 15, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_OAK_TREE_8421) }), + BIG_WILLOW_TREE(13414, 8176, 30, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_WILLOW_TREE_8423) }), + BIG_MAPLE_TREE (13415, 8177, 45, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MAPLE_TREE_8425) }), + BIG_YEW_TREE (13416, 8178, 60, 141, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_YEW_TREE_8427) }), + BIG_MAGIC_TREE (13417, 8179, 75, 223, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MAGIC_TREE_8429) }), + /** * Garden tree decorations. */ - DEAD_TREE(13418, 8173, 5, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_DEAD_TREE_8417)), - TREE(13419, 8174, 10, 44.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_NICE_TREE_8419)), - OAK_TREE(13420, 8175, 15, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_OAK_TREE_8421)), - WILLOW_TREE(13421, 8176, 30, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_WILLOW_TREE_8423)), - MAPLE_TREE(13423, 8177, 45, 122.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MAPLE_TREE_8425)), - YEW_TREE(13422, 8178, 60, 141.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_YEW_TREE_8427)), - MAGIC_TREE(13424, 8179, 75, 223.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MAGIC_TREE_8429)), - + DEAD_TREE (13418, 8173, 5, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_DEAD_TREE_8417) }), + TREE (13419, 8174, 10, 44, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_NICE_TREE_8419) }), + OAK_TREE (13420, 8175, 15, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_OAK_TREE_8421) }), + WILLOW_TREE(13421, 8176, 30, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_WILLOW_TREE_8423) }), + MAPLE_TREE (13423, 8177, 45, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MAPLE_TREE_8425) }), + YEW_TREE (13422, 8178, 60, 141, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_YEW_TREE_8427) }), + MAGIC_TREE (13424, 8179, 75, 223, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MAGIC_TREE_8429) }), + /** * Garden big plant 1 decorations. */ - FERN(13425, 8186, 1, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_1_8431)), - BUSH(13426, 8187, 6, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_2_8433)), - TALL_PLANT(13427, 8188, 12, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_3_8435)), - + FERN (13425, 8186, 1, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_1_8431) }), + BUSH (13426, 8187, 6, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_2_8433) }), + TALL_PLANT(13427, 8188, 12, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_3_8435) }), + /** * Garden big plant 2 decorations. */ - SHORT_PLANT(13428, 8189, 1, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_1_8431)), - LARGE_LEAF_PLANT(13429, 8190, 6, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_2_8433)), - HUGE_PLANT(13430, 8191, 12, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_3_8435)), + SHORT_PLANT (13428, 8189, 1, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_1_8431) }), + LARGE_LEAF_PLANT(13429, 8190, 6, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_2_8433) }), + HUGE_PLANT (13430, 8191, 12, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_3_8435) }), /** * Garden small plant 1 decorations. */ - PLANT(13431, 8180, 1, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_1_8431)), - SMALL_FERN(13432, 8181, 6, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_2_8433)), - FERN_SP(13433, 8182, 12, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_3_8435)), + PLANT (13431, 8180, 1, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_1_8431) }), + SMALL_FERN(13432, 8181, 6, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_2_8433) }), + FERN_SP (13433, 8182, 12, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_3_8435) }), /** * Garden small plant 2 decorations. */ - DOCK_LEAF(13434, 8183, 1, 31.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_1_8431)), - THISTLE(13435, 8184, 6, 70.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_2_8433)), - REEDS(13436, 8185, 12, 100.0, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_PLANT_3_8435)), - + DOCK_LEAF(13434, 8183, 1, 31, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_1_8431) }), + THISTLE (13435, 8184, 6, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_2_8433) }), + REEDS (13436, 8185, 12, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_PLANT_3_8435) }), + /** * Parlour chair spot */ - CRUDE_CHAIR(13581, 8309, 1, 66.0, new Item(Items.PLANK_960, 2)), - WOODEN_CHAIR(13582, 8310, 8, 96.0, new Item(Items.PLANK_960, 3)), - ROCKING_CHAIR(13583, 8311, 14, 96.0, new Item(Items.PLANK_960, 3)), - OAK_CHAIR(13584, 8312, 19, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - OAK_ARMCHAIR(13585, 8313, 26, 180.0, new Item(Items.OAK_PLANK_8778, 3)), - TEAK_ARMCHAIR(13586, 8314, 35, 180.0, new Item(Items.TEAK_PLANK_8780, 2)), - MAHOGANY_ARMCHAIR(13587, 8315, 50, 280.0, new Item(Items.MAHOGANY_PLANK_8782, 2)), + CRUDE_CHAIR (13581, 8309, 1, 58, new Item[] { new Item(Items.PLANK_960, 2) }), + WOODEN_CHAIR (13582, 8310, 8, 87, new Item[] { new Item(Items.PLANK_960, 3) }), + ROCKING_CHAIR (13583, 8311, 14, 87, new Item[] { new Item(Items.PLANK_960, 3) }), + OAK_CHAIR (13584, 8312, 19, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + OAK_ARMCHAIR (13585, 8313, 26, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + TEAK_ARMCHAIR (13586, 8314, 35, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + MAHOGANY_ARMCHAIR(13587, 8315, 50, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), /** * Rugs rugs rugs */ - BROWN_RUG_CORNER(13588, 8316, 2, 30.0, new Item(Items.BOLT_OF_CLOTH_8790, 2)), - RED_RUG_CORNER(13591, 8317, 13, 60.0, new Item(Items.BOLT_OF_CLOTH_8790, 4)), - OPULENT_RUG_CORNER(13594, 8318, 65, 360.0, new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 1)), - - BROWN_RUG_END(13589, 8316, 2, 30.0, new Item(Items.BOLT_OF_CLOTH_8790, 2)), - RED_RUG_END(13592, 8317, 13, 60.0, new Item(Items.BOLT_OF_CLOTH_8790, 4)), - OPULENT_RUG_END(13595, 8318, 65, 360.0, new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 1)), - - BROWN_RUG_CENTER(13590, 8316, 2, 30.0, new Item(Items.BOLT_OF_CLOTH_8790, 2)), - RED_RUG_CENTER(13593, 8317, 13, 60.0, new Item(Items.BOLT_OF_CLOTH_8790, 4)), - OPULENT_RUG_CENTER(13596, 8318, 65, 360.0, new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 1)), + BROWN_RUG_CORNER (13588, 8316, 2, 30, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + RED_RUG_CORNER (13591, 8317, 13, 60, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + OPULENT_RUG_CORNER(13594, 8318, 65, 360, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784) }), + BROWN_RUG_END (13589, 8316, 2, 30, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + RED_RUG_END (13592, 8317, 13, 60, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + OPULENT_RUG_END (13595, 8318, 65, 360, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784) }), + BROWN_RUG_CENTER (13590, 8316, 2, 30, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + RED_RUG_CENTER (13593, 8317, 13, 60, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + OPULENT_RUG_CENTER(13596, 8318, 65, 360, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784) }), /** * Parlour fireplaces */ - CLAY_FIREPLACE(13609, 8325, 3, 30.0, new Item(Items.SOFT_CLAY_1761, 3)), - STONE_FIREPLACE(13611, 8326, 33, 40.0, new Item(Items.LIMESTONE_BRICK_3420, 2)), - MARBLE_FIREPLACE(13613, 8327, 63, 500.0, new Item(Items.MARBLE_BLOCK_8786, 1)), + CLAY_FIREPLACE (13609, 8325, 3, 30, new Item[] { new Item(Items.SOFT_CLAY_1761, 3) }), + STONE_FIREPLACE (13611, 8326, 33, 40, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 2) }), + MARBLE_FIREPLACE(13613, 8327, 63, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), /** * Parlour curtain spot */ - TORN_CURTAINS(13603, 8322, 2, 132.0, new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3)), - CURTAINS(13604, 8323, 18, 225.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3)), - OPULENT_CURTAINS(13605, 8324, 40, 315.0, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3)), + TORN_CURTAINS (13603, 8322, 2, 132, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3) }), + CURTAINS (13604, 8323, 18, 225, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3) }), + OPULENT_CURTAINS(13605, 8324, 40, 315, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 3) }), /** - * Parlour bookcases + * Bookcases */ - WOODEN_BOOKCASE(13597, 8319, 4, 132.0, new Item(Items.PLANK_960, 4)), - OAK_BOOKCASE(13598, 8320, 29, 225.0, new Item(Items.OAK_PLANK_8778, 3)), - MAHOGANY_BOOKCASE(13599, 8321, 40, 315.0, new Item(Items.MAHOGANY_PLANK_8782, 3)), + WOODEN_BOOKCASE (13597, 8319, 4, 115, new Item[] { new Item(Items.PLANK_960, 4) }), + OAK_BOOKCASE (13598, 8320, 29, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + MAHOGANY_BOOKCASE(13599, 8321, 40, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), - /** * Kitchen Beer Barrels * TODO: These also require cooking levels! * Basic: 1, Cider: 14, Asgarnian: 24, Greenman's: 29, D.Bitter: 39, Chef's: 54 * */ - BASIC_BEER_BARREL(13568, 8239, 7, 87.0, new Item(Items.PLANK_960, 3)), - CIDER_BARREL(13569, 8240, 12, 91.0, new Item(Items.PLANK_960, 3), new Item(Items.CIDER_5763, 8)), - ASGARNIAN_ALE_BARREL(13570, 8241, 18, 184.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.ASGARNIAN_ALE_1905, 8)), - GREENMANS_ALE_BARREL(13571, 8242, 26, 184.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.GREENMANS_ALE_1909, 8)), - DRAGON_BITTER_BARREL(13572, 8243, 36, 224.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.DRAGON_BITTER_1911, 8), new Item(Items.STEEL_BAR_2353, 2)), - CHEFS_DELIGHT_BARREL(13573, 8244, 48, 224.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.CHEFS_DELIGHT_5755, 8), new Item(Items.STEEL_BAR_2353, 2)), - - + BASIC_BEER_BARREL (13568, 8239, 7, 87, new Item[] { new Item(Items.PLANK_960, 3) }), + CIDER_BARREL (13569, 8240, 12, 91, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.CIDER_5763, 8) }), + ASGARNIAN_ALE_BARREL(13570, 8241, 18, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.ASGARNIAN_ALE_1905, 8) }), + GREENMANS_ALE_BARREL(13571, 8242, 26, 184, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.GREENMANS_ALE_1909, 8) }), + DRAGON_BITTER_BARREL(13572, 8243, 36, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.DRAGON_BITTER_1911, 8), new Item(Items.STEEL_BAR_2353, 2) }), + CHEFS_DELIGHT_BARREL(13573, 8244, 48, 224, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.CHEFS_DELIGHT_5755, 8), new Item(Items.STEEL_BAR_2353, 2) }), + /** * Kitchen Tables! */ - KITCHEN_WOODEN_TABLE(13577, 8246, 12, 87.0, new Item(Items.PLANK_960, 3)), - KITCHEN_OAK_TABLE(13578, 8247, 32, 180.0, new Item(Items.OAK_PLANK_8778, 3)), - KITCHEN_TEAK_TABLE(13579, 8248, 52, 270.0, new Item(Items.TEAK_PLANK_8780, 3)), - - + KITCHEN_WOODEN_TABLE(13577, 8246, 12, 87, new Item[] { new Item(Items.PLANK_960, 3) }), + KITCHEN_OAK_TABLE (13578, 8247, 32, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + KITCHEN_TEAK_TABLE (13579, 8248, 52, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + /** * Kitchen Stoves */ - BASIC_FIREPIT(13528, 8216, 5, 40.0, new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353, 1)), - FIREPIT_WITH_HOOK(13529, 8217, 11, 60.0, new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353, 2)), - FIREPIT_WITH_POT(13531, 8218, 17, 80.0, new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353, 3)), - SMALL_OVEN(13533, 8219, 24, 80.0, new Item(Items.STEEL_BAR_2353, 4)), - LARGE_OVEN(13536, 8220, 29, 100.0, new Item(Items.STEEL_BAR_2353, 5)), - BASIC_RANGE(13539, 8221, 34, 120.0, new Item(Items.STEEL_BAR_2353, 6)), - FANCY_RANGE(13542, 8222, 42, 160.0, new Item(Items.STEEL_BAR_2353, 8)), - + BASIC_FIREPIT (13528, 8216, 5, 40, new Item[] { new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353) }), + FIREPIT_WITH_HOOK(13529, 8217, 11, 60, new Item[] { new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353, 2) }), + FIREPIT_WITH_POT (13531, 8218, 17, 80, new Item[] { new Item(Items.SOFT_CLAY_1761, 2), new Item(Items.STEEL_BAR_2353, 3) }), + SMALL_OVEN (13533, 8219, 24, 80, new Item[] { new Item(Items.STEEL_BAR_2353, 4) }), + LARGE_OVEN (13536, 8220, 29, 100, new Item[] { new Item(Items.STEEL_BAR_2353, 5) }), + BASIC_RANGE (13539, 8221, 34, 120, new Item[] { new Item(Items.STEEL_BAR_2353, 6) }), + FANCY_RANGE (13542, 8222, 42, 160, new Item[] { new Item(Items.STEEL_BAR_2353, 8) }), + /** * Kitchen larders */ - WOODEN_LARDER(13565, 8233, 9, 228.0, new Item(Items.PLANK_960, 8)), - OAK_LARDER(13566, 8234, 33, 480.0, new Item(Items.OAK_PLANK_8778, 8)), - TEAK_LARDER(13567, 8235, 43, 750.0, new Item(Items.TEAK_PLANK_8780, 8), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - - + WOODEN_LARDER(13565, 8233, 9, 228, new Item[] { new Item(Items.PLANK_960, 8) }), + OAK_LARDER (13566, 8234, 33, 480, new Item[] { new Item(Items.OAK_PLANK_8778, 8) }), + TEAK_LARDER (13567, 8235, 43, 750, new Item[] { new Item(Items.TEAK_PLANK_8780, 8), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + /** * Kitchen shelves */ - WOODEN_SHELVES_1(13545, 8223, 6, 87.0, new Item(Items.PLANK_960, 3)), - WOODEN_SHELVES_2(13546, 8224, 12, 147.0, new Item(Items.PLANK_960, 3), new Item(Items.SOFT_CLAY_1761, 6)), - WOODEN_SHELVES_3(13547, 8225, 23, 147.0, new Item(Items.PLANK_960, 3), new Item(Items.SOFT_CLAY_1761, 6)), - OAK_SHELVES_1(13548, 8226, 34, 240.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.SOFT_CLAY_1761, 6)), - OAK_SHELVES_2(13549, 8227, 45, 240.0, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.SOFT_CLAY_1761, 6)), - TEAK_SHELVES_1(13550, 8228, 56, 330.0, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SOFT_CLAY_1761, 6)), - TEAK_SHELVES_2(13551, 8229, 67, 930.0, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SOFT_CLAY_1761, 6), new Item(Items.GOLD_LEAF_8784, 2)), - + WOODEN_SHELVES_1(13545, 8223, 6, 87, new Item[] { new Item(Items.PLANK_960, 3) }), + WOODEN_SHELVES_2(13546, 8224, 12, 147, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.SOFT_CLAY_1761, 6) }), + WOODEN_SHELVES_3(13547, 8225, 23, 147, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.SOFT_CLAY_1761, 6) }), + OAK_SHELVES_1 (13548, 8226, 34, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.SOFT_CLAY_1761, 6) }), + OAK_SHELVES_2 (13549, 8227, 45, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.SOFT_CLAY_1761, 6) }), + TEAK_SHELVES_1 (13550, 8228, 56, 330, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SOFT_CLAY_1761, 6) }), + TEAK_SHELVES_2 (13551, 8229, 67, 930, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SOFT_CLAY_1761, 6), new Item(Items.GOLD_LEAF_8784, 2) }), + /** * Kitchen sinks */ - PUMP_AND_DRAIN(13559, 8230, 7, 100.0, new Item(Items.STEEL_BAR_2353, 5)), - PUMP_AND_TUB(13561, 8231, 27, 200.0, new Item(Items.STEEL_BAR_2353, 10)), - SINK(13563, 8232, 47, 300.0, new Item(Items.STEEL_BAR_2353, 15)), - - + PUMP_AND_DRAIN(13559, 8230, 7, 100, new Item[] { new Item(Items.STEEL_BAR_2353, 5) }), + PUMP_AND_TUB (13561, 8231, 27, 200, new Item[] { new Item(Items.STEEL_BAR_2353, 10) }), + SINK (13563, 8232, 47, 300, new Item[] { new Item(Items.STEEL_BAR_2353, 15) }), + /** * Kitchen cat baskets/blankets */ - CAT_BLANKET(13574, 8236, 5, 15.0, new Item(Items.BOLT_OF_CLOTH_8790, 1)), - CAT_BASKET(13575, 8237, 19, 58.0, new Item(Items.PLANK_960, 2)), - CAST_BASKET_CUSHIONED(13576, 8238, 33, 58.0, new Item(Items.PLANK_960, 2), new Item(Items.WOOL_1737, 2)), - - + CAT_BLANKET (13574, 8236, 5, 15, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790) }), + CAT_BASKET (13575, 8237, 19, 58, new Item[] { new Item(Items.PLANK_960, 2) }), + CAST_BASKET_CUSHIONED(13576, 8238, 33, 58, new Item[] { new Item(Items.PLANK_960, 2), new Item(Items.WOOL_1737, 2) }), + /** * Dining room tables */ - DINING_TABLE_WOOD(13293, 8246, 10, 115.0, new Item(Items.PLANK_960, 4)), - DINING_TABLE_OAK(13294, 8247, 22, 240.0, new Item(Items.OAK_PLANK_8778, 4)), - DINING_TABLE_CARVED_OAK(13295, 8247, 31, 360.0, new Item(Items.OAK_PLANK_8778, 6)), - DINING_TABLE_TEAK(13296, 8248, 38, 360.0, new Item(Items.TEAK_PLANK_8780, 4)), - DINING_TABLE_CARVED_TEAK(13297, 8248, 45, 600.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - DINING_TABLE_MAHOGANY(13298, 8120, 52, 840.0, new Item(Items.MAHOGANY_PLANK_8782, 6)), - DINING_TABLE_OPULENT(13299, 8121, 72, 3100.0, new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4), - new Item(Items.GOLD_LEAF_8784, 4), new Item(Items.MARBLE_BLOCK_8786, 2)), - + DINING_TABLE_WOOD (13293, 8246, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }), + DINING_TABLE_OAK (13294, 8247, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + DINING_TABLE_CARVED_OAK (13295, 8247, 31, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }), + DINING_TABLE_TEAK (13296, 8248, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + DINING_TABLE_CARVED_TEAK(13297, 8248, 45, 600, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + DINING_TABLE_MAHOGANY (13298, 8120, 52, 840, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }), + DINING_TABLE_OPULENT (13299, 8121, 72, 3100, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4), new Item(Items.GOLD_LEAF_8784, 4), new Item(Items.MARBLE_BLOCK_8786, 2) }), /** * Dining room benches */ - BENCH_WOODEN(13300, 8108, 10, 115.0, new Item(Items.PLANK_960, 4)), - BENCH_OAK(13301, 8109, 22, 240.0, new Item(Items.OAK_PLANK_8778, 4)), - BENCH_CARVED_OAK(13302, 8110, 31, 240.0, new Item(Items.OAK_PLANK_8778, 4)), - BENCH_TEAK(13303, 8111, 38, 360.0, new Item(Items.TEAK_PLANK_8780, 4)), - BENCH_CARVED_TEAK(13304, 8112, 44, 360.0, new Item(Items.TEAK_PLANK_8780, 4)), - BENCH_MAHOGANY(13305, 8113, 52, 560.0, new Item(Items.MAHOGANY_PLANK_8782, 6)), - BENCH_GILDED(13306, 8114, 61, 1760.0, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4)), - + BENCH_WOODEN (13300, 8108, 10, 115, new Item[] { new Item(Items.PLANK_960, 4) }), + BENCH_OAK (13301, 8109, 22, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + BENCH_CARVED_OAK (13302, 8110, 31, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + BENCH_TEAK (13303, 8111, 38, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + BENCH_CARVED_TEAK(13304, 8112, 44, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + BENCH_MAHOGANY (13305, 8113, 52, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6) }), + BENCH_GILDED (13306, 8114, 61, 1760, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4) }), + /** * Dining room bell-pulls */ - ROPE_PULL(13307, 8099, 5, 15.0, new Item(Items.ROPE_954, 1), new Item(Items.OAK_PLANK_8778, 1)), - BELL_PULL(13308, 8100, 19, 58.0, new Item(Items.TEAK_PLANK_8780, 1), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - FANCY_BELL_PULL(13309, 8101, 33, 58.0, new Item(Items.TEAK_PLANK_8780, 1), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 1)), - + ROPE_PULL (13307, 8099, 5, 15, new Item[] { new Item(Items.ROPE_954), new Item(Items.OAK_PLANK_8778) }), + BELL_PULL (13308, 8100, 19, 58, new Item[] { new Item(Items.TEAK_PLANK_8780), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + FANCY_BELL_PULL(13309, 8101, 33, 58, new Item[] { new Item(Items.TEAK_PLANK_8780), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784) }), + /** * Workshop workbench */ - WORKBENCH_WOODEN(13704, 8375, 17, 145.0, new Item(Items.PLANK_960, 1)), - WORKBENCH_OAK(13705, 8376, 32, 300.0, new Item(Items.OAK_PLANK_8778, 5)), - WORKBENCH_STEEL_FRAME(13706, 8377, 46, 440.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.STEEL_BAR_2353, 4)), - WORKBENCH_WITH_VICE(13707, 8378, 62, 750.0, new Item(Items.STEEL_FRAMED_BENCH_8377, 1), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353, 1)), - WORKBENCH_WITH_LATHE(13708, 8379, 77, 1000.0, new Item(Items.OAK_WORKBENCH_8376, 1), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353, 1)), - + WORKBENCH_WOODEN (13704, 8375, 17, 143, new Item[] { new Item(Items.PLANK_960, 5) }), + WORKBENCH_OAK (13705, 8376, 32, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), + WORKBENCH_STEEL_FRAME(13706, 8377, 46, 440, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.STEEL_BAR_2353, 4) }), + WORKBENCH_WITH_VICE (13707, 8378, 62, 750, new Item[] { new Item(Items.STEEL_FRAMED_BENCH_8377), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), + WORKBENCH_WITH_LATHE (13708, 8379, 77, 1000, new Item[] { new Item(Items.OAK_WORKBENCH_8376), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), + /** * Workshop repair benches/stands */ - REPAIR_BENCH(13713, 8389, 15, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - WHETSTONE(13714, 8390, 35, 260.0, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIMESTONE_BRICK_3420, 1)), - ARMOUR_STAND(13715, 8391, 55, 500.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.LIMESTONE_BRICK_3420, 1)), - + REPAIR_BENCH(13713, 8389, 15, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + WHETSTONE (13714, 8390, 35, 260, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIMESTONE_BRICK_3420) }), + ARMOUR_STAND(13715, 8391, 55, 500, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.LIMESTONE_BRICK_3420) }), + /** * Workshop easels */ - PLUMING_STAND(13716, 8392, 16, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - SHIELD_EASEL(13717, 8393, 41, 240.0, new Item(Items.OAK_PLANK_8778, 4)), - BANNER_EASEL(13718, 8394, 66, 510.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - + PLUMING_STAND(13716, 8392, 16, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + SHIELD_EASEL (13717, 8393, 41, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + BANNER_EASEL (13718, 8394, 66, 510, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + /** * Workshop crafting tables * TODO: These are upgradable hotspots, therefore crafting table 3 would require * crafting table 2 to be already built in that spot. */ - CRAFTING_TABLE_1(13709, 8380, 16, 50.0, new Item(Items.OAK_PLANK_8778, 4)), - CRAFTING_TABLE_2(13710, 8381, 25, 100.0, new Item(Items.MOLTEN_GLASS_1775, 1)), - CRAFTING_TABLE_3(13711, 8382, 34, 175.0, new Item(Items.MOLTEN_GLASS_1775, 2)), - CRAFTING_TABLE_4(13712, 8383, 42, 240.0, new Item(Items.OAK_PLANK_8778, 2)), - + CRAFTING_TABLE_1(13709, 8380, 16, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + CRAFTING_TABLE_2(13710, 8381, 25, 1, new Item[] { new Item(Items.MOLTEN_GLASS_1775) }), + CRAFTING_TABLE_3(13711, 8382, 34, 2, new Item[] { new Item(Items.MOLTEN_GLASS_1775, 2) }), + CRAFTING_TABLE_4(13712, 8383, 42, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + /** * Workshop tool stores * These are also upgradable just like the tables above. */ - TOOL_STORE_1(13699, 8384, 15, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TOOL_STORE_2(13700, 8385, 25, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TOOL_STORE_3(13701, 8386, 35, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TOOL_STORE_4(13702, 8387, 44, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TOOL_STORE_5(13703, 8388, 55, 120.0, new Item(Items.OAK_PLANK_8778, 2)), + TOOL_STORE_1(13699, 8384, 15, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TOOL_STORE_2(13700, 8385, 25, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TOOL_STORE_3(13701, 8386, 35, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TOOL_STORE_4(13702, 8387, 44, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TOOL_STORE_5(13703, 8388, 55, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - /** * Wall-mounted decorations */ - OAK_DECORATION(13606, 8102, 16, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_DECORATION(13606, 8103, 36, 180.0, new Item(Items.TEAK_PLANK_8780, 2)), - GILDED_DECORATION(13607, 8104, 56, 1020.0, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 2)), - + OAK_DECORATION (13606, 8102, 16, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_DECORATION (13606, 8103, 36, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + GILDED_DECORATION(13607, 8104, 56, 1020, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 2) }), + /** * Staircases. */ - OAK_STAIRCASE(13497, 8249, 27, 680.0, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 4)), - TEAK_STAIRCASE(13499, 8252, 48, 980.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 4)), - SPIRAL_STAIRCASE(13503, 8258, 67, 1040.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.LIMESTONE_BRICK_3420, 7)), - MARBLE_STAIRCASE(13501, 8257, 82, 3200.0, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 5)), - MARBLE_SPIRAL(13505, 8259, 97, 4400.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.MARBLE_BLOCK_8786, 7)), - + OAK_STAIRCASE (13497, 8249, 27, 680, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 4) }), + TEAK_STAIRCASE (13499, 8252, 48, 980, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 4) }), + SPIRAL_STAIRCASE(13503, 8258, 67, 1040, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.LIMESTONE_BRICK_3420, 7) }), + MARBLE_STAIRCASE(13501, 8257, 82, 3200, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 5) }), + MARBLE_SPIRAL (13505, 8259, 97, 4400, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.MARBLE_BLOCK_8786, 7) }), + /** * Staircases going down. */ - OAK_STAIRS_DOWN(13498, 8249, 27, 680.0, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 4)), - TEAK_STAIRS_DOWN(13500, 8252, 48, 980.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 4)), - SPIRAL_STAIRS_DOWN(13504, 8258, 67, 1040.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.LIMESTONE_BRICK_3420, 7)), - MARBLE_STAIRS_DOWN(13502, 8257, 82, 3200.0, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 5)), - MARBLE_SPIRAL_DOWN(13506, 8259, 97, 4400.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.MARBLE_BLOCK_8786, 7)), - + OAK_STAIRS_DOWN (13498, 8249, 27, 680, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 4) }), + TEAK_STAIRS_DOWN (13500, 8252, 48, 980, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 4) }), + SPIRAL_STAIRS_DOWN(13504, 8258, 67, 1040, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.LIMESTONE_BRICK_3420, 7) }), + MARBLE_STAIRS_DOWN(13502, 8257, 82, 3200, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 5) }), + MARBLE_SPIRAL_DOWN(13506, 8259, 97, 4400, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.MARBLE_BLOCK_8786, 7) }), + /** * Portal room decorations. */ - TEAK_PORTAL(13636, 8328, 50, 270.0, new Item(Items.TEAK_PLANK_8780, 3)), - MAHOGANY_PORTAL(13637, 8329, 65, 420.0, new Item(Items.MAHOGANY_PLANK_8782, 3)), - MARBLE_PORTAL(13638, 8330, 80, 1500.0, new Item(Items.MARBLE_BLOCK_8786, 3)), - TELEPORT_FOCUS(13640, 8331, 50, 40, new Item(Items.LIMESTONE_BRICK_3420, 2)), - GREATER_TELEPORT_FOCUS(13641, 8332, 65, 500.0, new Item(Items.MARBLE_BLOCK_8786, 1)), - SCRYING_POOL(13639, 8333, 80, 2000.0, new Item(Items.MARBLE_BLOCK_8786, 4)), - TEAK_VARROCK_PORTAL(13615, true), - MAHOGANY_VARROCK_PORTAL(13622, true), - MARBLE_VARROCK_PORTAL(13629, true), - TEAK_LUMBRIDGE_PORTAL(13616, true), + TEAK_PORTAL (13636, 8328, 50, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + MAHOGANY_PORTAL (13637, 8329, 65, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), + MARBLE_PORTAL (13638, 8330, 80, 1500, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 3) }), + TELEPORT_FOCUS (13640, 8331, 50, 40, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 2) }), + GREATER_TELEPORT_FOCUS (13641, 8332, 65, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), + SCRYING_POOL (13639, 8333, 80, 2000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 4) }), + TEAK_VARROCK_PORTAL (13615, true), + MAHOGANY_VARROCK_PORTAL (13622, true), + MARBLE_VARROCK_PORTAL (13629, true), + TEAK_LUMBRIDGE_PORTAL (13616, true), MAHOGANY_LUMBRIDGE_PORTAL(13623, true), - MARBLE_LUMBRIDGE_PORTAL(13630, true), - TEAK_FALADOR_PORTAL(13617, true), - MAHOGANY_FALADOR_PORTAL(13624, true), - MARBLE_FALADOR_PORTAL(13631, true), - TEAK_CAMELOT_PORTAL(13618, true), - MAHOGANY_CAMELOT_PORTAL(13625, true), - MARBLE_CAMELOT_PORTAL(13632, true), - TEAK_ARDOUGNE_PORTAL(13619, true), - MAHOGANY_ARDOUGNE_PORTAL(13626, true), - MARBLE_ARDOUGNE_PORTAL(13633, true), - TEAK_YANILLE_PORTAL(13620, true), - MAHOGANY_YANILLE_PORTAL(13627, true), - MARBLE_YANILLE_PORTAL(13634, true), - TEAK_KHARYRLL_PORTAL(13621, true), - MAHOGANY_KHARYRLL_PORTAL(13628, true), - MARBLE_KHARYRLL_PORTAL(13635, true), - + MARBLE_LUMBRIDGE_PORTAL (13630, true), + TEAK_FALADOR_PORTAL (13617, true), + MAHOGANY_FALADOR_PORTAL (13624, true), + MARBLE_FALADOR_PORTAL (13631, true), + TEAK_CAMELOT_PORTAL (13618, true), + MAHOGANY_CAMELOT_PORTAL (13625, true), + MARBLE_CAMELOT_PORTAL (13632, true), + TEAK_ARDOUGNE_PORTAL (13619, true), + MAHOGANY_ARDOUGNE_PORTAL (13626, true), + MARBLE_ARDOUGNE_PORTAL (13633, true), + TEAK_YANILLE_PORTAL (13620, true), + MAHOGANY_YANILLE_PORTAL (13627, true), + MARBLE_YANILLE_PORTAL (13634, true), + TEAK_KHARYRLL_PORTAL (13621, true), + MAHOGANY_KHARYRLL_PORTAL (13628, true), + MARBLE_KHARYRLL_PORTAL (13635, true), + /** * Skill hall decorations. */ - MITHRIL_ARMOUR(13491, 8270, 28, 135.0, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MITHRIL_FULL_HELM_1159, 1), new Item(Items.MITHRIL_PLATEBODY_1121, 1), new Item(Items.MITHRIL_PLATESKIRT_1085, 1)), - ADAMANT_ARMOUR(13492, 8271, 28, 150.0, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.ADAMANT_FULL_HELM_1161, 1), new Item(Items.ADAMANT_PLATEBODY_1123, 1), new Item(Items.ADAMANT_PLATESKIRT_1091, 1)), - RUNE_ARMOUR(13493, 8272, 28, 165.0, new Item(Items.OAK_PLANK_8778, 2),new Item(Items.RUNE_FULL_HELM_1163, 1), new Item(Items.RUNE_PLATEBODY_1127, 1), new Item(Items.RUNE_PLATESKIRT_1093, 1)), - CRAWLING_HAND(13481, 8260, 38, 211.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CRAWLING_HAND_7982, 1)), - COCKATRICE_HEAD(13482, 8261, 38, 224.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.COCKATRICE_HEAD_7983, 1)), - BASILISK_HEAD(13483, 8262, 38, 243.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.BASILISK_HEAD_7984, 1)), - KURASK_HEAD(13484, 8263, 58, 357.0, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KURASK_HEAD_7985, 1)), - ABYSSAL_DEMON_HEAD(13485, 8264, 58, 389.0, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.ABYSSAL_HEAD_7986, 1)), - KBD_HEAD(13486, 8265, 78, 1103.0, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KBD_HEADS_7987, 1)), - KQ_HEAD(13487, 8266, 78, 1103.0, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KQ_HEAD_7988, 1)), - MOUNTED_BASS(13488, 8267, 36, 151.0, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.BIG_BASS_7990, 1)), - MOUNTED_SWORDFISH(13489, 8268, 56, 230.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.BIG_SWORDFISH_7992, 1)), - MOUNTED_SHARK(13490, 8269, 76, 350.0, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.BIG_SHARK_7994, 1)), - RUNE_CASE1(13507, 8095, 41, 190.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.FIRE_RUNE_554, 1), new Item(Items.AIR_RUNE_556, 1), new Item(Items.EARTH_RUNE_557, 1), new Item(Items.WATER_RUNE_555, 1)), - RUNE_CASE2(13508, 8095, 41, 212.0, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.BODY_RUNE_559, 1), new Item(Items.COSMIC_RUNE_564, 1), new Item(Items.CHAOS_RUNE_562, 1), new Item(Items.NATURE_RUNE_561, 1)), - - + MITHRIL_ARMOUR (13491, 8270, 28, 135, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MITHRIL_FULL_HELM_1159, 1), new Item(Items.MITHRIL_PLATEBODY_1121, 1), new Item(Items.MITHRIL_PLATESKIRT_1085, 1) }, new Item[] { new Item(Items.MITHRIL_FULL_HELM_1159, 1), new Item(Items.MITHRIL_PLATEBODY_1121, 1), new Item(Items.MITHRIL_PLATESKIRT_1085, 1) }), + ADAMANT_ARMOUR (13492, 8271, 28, 150, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.ADAMANT_FULL_HELM_1161, 1), new Item(Items.ADAMANT_PLATEBODY_1123, 1), new Item(Items.ADAMANT_PLATESKIRT_1091, 1) }, new Item[] { new Item(Items.ADAMANT_FULL_HELM_1161, 1), new Item(Items.ADAMANT_PLATEBODY_1123, 1), new Item(Items.ADAMANT_PLATESKIRT_1091, 1) }), + RUNE_ARMOUR (13493, 8272, 28, 165, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.RUNE_FULL_HELM_1163, 1), new Item(Items.RUNE_PLATEBODY_1127, 1), new Item(Items.RUNE_PLATESKIRT_1093, 1) }, new Item[] { new Item(Items.RUNE_FULL_HELM_1163, 1), new Item(Items.RUNE_PLATEBODY_1127, 1), new Item(Items.RUNE_PLATESKIRT_1093, 1) }), + CRAWLING_HAND (13481, 8260, 38, 211, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CRAWLING_HAND_7982) }), + COCKATRICE_HEAD (13482, 8261, 38, 224, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.COCKATRICE_HEAD_7983) }), + BASILISK_HEAD (13483, 8262, 38, 243, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.BASILISK_HEAD_7984) }), + KURASK_HEAD (13484, 8263, 58, 357, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KURASK_HEAD_7985) }), + ABYSSAL_DEMON_HEAD(13485, 8264, 58, 389, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.ABYSSAL_HEAD_7986) }), + KBD_HEAD (13486, 8265, 78, 1103, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KBD_HEADS_7987) }), + KQ_HEAD (13487, 8266, 78, 1103, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.KQ_HEAD_7988) }), + MOUNTED_BASS (13488, 8267, 36, 151, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.BIG_BASS_7990) }), + MOUNTED_SWORDFISH (13489, 8268, 56, 230, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.BIG_SWORDFISH_7992) }), + MOUNTED_SHARK (13490, 8269, 76, 350, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.BIG_SHARK_7994) }), + RUNE_CASE1 (13507, 8095, 41, 190, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.FIRE_RUNE_554, 1), new Item(Items.AIR_RUNE_556, 1), new Item(Items.EARTH_RUNE_557, 1), new Item(Items.WATER_RUNE_555, 1) }), + RUNE_CASE2 (13508, 8095, 41, 212, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.BODY_RUNE_559, 1), new Item(Items.COSMIC_RUNE_564, 1), new Item(Items.CHAOS_RUNE_562, 1), new Item(Items.NATURE_RUNE_561, 1) }), + /** * Games room decorations. */ - CLAY_STONE(13392, 8153, 39, 100.0, new Item(Items.SOFT_CLAY_1761, 10)), - LIMESTONE_STONE(13393, 8154, 59, 200.0, new Item(Items.LIMESTONE_BRICK_3420, 10)), - MARBLE_STONE(13394, 8155, 79, 2000.0, new Item(Items.MARBLE_BLOCK_8786, 4)), - HOOP_AND_STICK(13398, 8162, 30, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - DARTBOARD(13400, 8163, 54, 290.0, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.STEEL_BAR_2353, 1)), - ARCHERY_TARGET(13402, 8164, 81, 600.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.STEEL_BAR_2353, 3)), - BALANCE_1(13395, 8156, 37, 176.0, new Item(Items.FIRE_RUNE_554, 500), new Item(Items.AIR_RUNE_556, 500), new Item(Items.EARTH_RUNE_557, 500), new Item(Items.WATER_RUNE_555, 500)), - BALANCE_2(13396, 8157, 57, 252.0, new Item(Items.FIRE_RUNE_554, 1000), new Item(Items.AIR_RUNE_556, 1000), new Item(Items.EARTH_RUNE_557, 1000), new Item(Items.WATER_RUNE_555, 1000)), - BALANCE_3(13397, 8158, 77, 356.0, new Item(Items.FIRE_RUNE_554, 2000), new Item(Items.AIR_RUNE_556, 2000), new Item(Items.EARTH_RUNE_557, 2000), new Item(Items.WATER_RUNE_555, 2000)), - OAK_CHEST(13385, 8165, 34, 240.0, new Item(Items.OAK_PLANK_8778, 4)), - TEAK_CHEST(13387, 8166, 44, 660.0, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 1)), - MAHOGANY_CHEST(13389, 8167, 54, 860.0, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 1)), - JESTER(13390, 8159, 39, 360.0, new Item(Items.TEAK_PLANK_8780, 4)), - TREASURE_HUNT(13379, 8160, 49, 800.0, new Item(Items.TEAK_PLANK_8780, 8), new Item(Items.STEEL_BAR_2353, 4)), - HANGMAN(13404, 8161, 59, 1200.0, new Item(Items.TEAK_PLANK_8780, 12), new Item(Items.STEEL_BAR_2353, 6)), - - + CLAY_STONE (13392, 8153, 39, 100, new Item[] { new Item(Items.SOFT_CLAY_1761, 10) }), + LIMESTONE_STONE(13393, 8154, 59, 200, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 10) }), + MARBLE_STONE (13394, 8155, 79, 2000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 4) }), + HOOP_AND_STICK (13398, 8162, 30, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + DARTBOARD (13400, 8163, 54, 290, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.STEEL_BAR_2353) }), + ARCHERY_TARGET (13402, 8164, 81, 600, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.STEEL_BAR_2353, 3) }), + BALANCE_1 (13395, 8156, 37, 176, new Item[] { new Item(Items.FIRE_RUNE_554, 500), new Item(Items.AIR_RUNE_556, 500), new Item(Items.EARTH_RUNE_557, 500), new Item(Items.WATER_RUNE_555, 500) }), + BALANCE_2 (13396, 8157, 57, 252, new Item[] { new Item(Items.FIRE_RUNE_554, 1000), new Item(Items.AIR_RUNE_556, 1000), new Item(Items.EARTH_RUNE_557, 1000), new Item(Items.WATER_RUNE_555, 1000) }), + BALANCE_3 (13397, 8158, 77, 356, new Item[] { new Item(Items.FIRE_RUNE_554, 2000), new Item(Items.AIR_RUNE_556, 2000), new Item(Items.EARTH_RUNE_557, 2000), new Item(Items.WATER_RUNE_555, 2000) }), + OAK_CHEST (13385, 8165, 34, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + TEAK_CHEST (13387, 8166, 44, 660, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784) }), + MAHOGANY_CHEST (13389, 8167, 54, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }), + JESTER (13390, 8159, 39, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + TREASURE_HUNT (13379, 8160, 49, 800, new Item[] { new Item(Items.TEAK_PLANK_8780, 8), new Item(Items.STEEL_BAR_2353, 4) }), + HANGMAN (13404, 8161, 59, 1200, new Item[] { new Item(Items.TEAK_PLANK_8780, 12), new Item(Items.STEEL_BAR_2353, 6) }), + /** * Combat room decorations. */ - BOXING_RING(13129, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - FENCING_RING(13133, 8024, 41, 570.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - COMBAT_RING(13137, 8025, 51, 630.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - BALANCE_BEAM_LEFT(13143, 8027, 81, 1000.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5)), - BALANCE_BEAM_CENTER(13142, 8027, 81, 1000.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5)), - BALANCE_BEAM_RIGHT(13144, 8027, 81, 1000.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5)), - RANGING_PEDESTALS(13147, 8026, 71, 720.0, new Item(Items.TEAK_PLANK_8780, 8)), - MAGIC_BARRIER(13145, 8026, 71, 720.0, new Item(Items.TEAK_PLANK_8780, 8)), - NOTHING(13721, 8027, 81, 1000.0, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5)), - NOTHING2(13721, 8026, 71, 720.0, new Item(Items.TEAK_PLANK_8780, 8)), - INVISIBLE_WALL(15283, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - INVISIBLE_WALL2(15284, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - INVISIBLE_WALL3(15285, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - GLOVE_RACK(13381, 8028, 34, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - WEAPONS_RACK(13382, 8029, 44, 180.0, new Item(Items.TEAK_PLANK_8780, 2)), - EXTRA_WEAPONS_RACK(13383, 8030, 54, 440.0, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.STEEL_BAR_2353, 4)), - BOXING_MAT_CORNER(13126, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - FENCING_MAT_CORNER(13135, 8024, 41, 570.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - COMBAT_MAT_CORNER(13138, 8025, 51, 630.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - BOXING_MAT_SIDE(13128, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - FENCING_MAT_SIDE(13134, 8024, 41, 570.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - COMBAT_MAT_SIDE(13139, 8025, 51, 630.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - BOXING_MAT(13127, 8023, 32, 570.0, new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4)), - FENCING_MAT(13136, 8024, 41, 570.0, new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - COMBAT_MAT(13140, 8025, 51, 630.0, new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6)), - - + BOXING_RING (13129, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + FENCING_RING (13133, 8024, 41, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + COMBAT_RING (13137, 8025, 51, 630, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + BALANCE_BEAM_LEFT (13143, 8027, 81, 1000, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5) }), + BALANCE_BEAM_CENTER(13142, 8027, 81, 1000, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5) }), + BALANCE_BEAM_RIGHT (13144, 8027, 81, 1000, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5) }), + RANGING_PEDESTALS (13147, 8026, 71, 720, new Item[] { new Item(Items.TEAK_PLANK_8780, 8) }), + MAGIC_BARRIER (13145, 8026, 71, 720, new Item[] { new Item(Items.TEAK_PLANK_8780, 8) }), + NOTHING (13721, 8027, 81, 1000, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 5) }), + NOTHING2 (13721, 8026, 71, 720, new Item[] { new Item(Items.TEAK_PLANK_8780, 8) }), + INVISIBLE_WALL (15283, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + INVISIBLE_WALL2 (15284, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + INVISIBLE_WALL3 (15285, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + GLOVE_RACK (13381, 8028, 34, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + WEAPONS_RACK (13382, 8029, 44, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + EXTRA_WEAPONS_RACK (13383, 8030, 54, 440, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.STEEL_BAR_2353, 4) }), + BOXING_MAT_CORNER (13126, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + FENCING_MAT_CORNER (13135, 8024, 41, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + COMBAT_MAT_CORNER (13138, 8025, 51, 630, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + BOXING_MAT_SIDE (13128, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + FENCING_MAT_SIDE (13134, 8024, 41, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + COMBAT_MAT_SIDE (13139, 8025, 51, 630, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + BOXING_MAT (13127, 8023, 32, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + FENCING_MAT (13136, 8024, 41, 570, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + COMBAT_MAT (13140, 8025, 51, 630, new Item[] { new Item(Items.TEAK_PLANK_8780, 6), new Item(Items.BOLT_OF_CLOTH_8790, 6) }), + /** * Formal garden decorations */ - GAZEBO(13477, 8192, 65, 1200, new Item(Items.MAHOGANY_PLANK_8782, 8), new Item(Items.STEEL_BAR_2353, 4)), - SMALL_FOUNTAIN(13478, 8193, 71, 500, new Item(Items.MARBLE_BLOCK_8786, 1)), - LARGE_FOUNTAIN(13479, 8194, 75, 1000, new Item(Items.MARBLE_BLOCK_8786, 2)), - POSH_FOUNTAIN(13480, 8195, 81, 1500, new Item(Items.MARBLE_BLOCK_8786, 3)), - SUNFLOWER(13446, 8213, 66, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_SUNFLOWER_8457, 1)), - MARIGOLDS(13447, 8214, 71, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MARIGOLDS_8459, 1)), - ROSES(13448, 8215, 76, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_ROSES_8461, 1)), - SUNFLOWER_BIG(13443, 8213, 66, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_SUNFLOWER_8457, 1)), - MARIGOLDS_BIG(13444, 8214, 71, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_MARIGOLDS_8459, 1)), - ROSES_BIG(13445, 8215, 76, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_ROSES_8461, 1)), - ROSEMARY(13440, 8210, 66, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_ROSEMARY_8451, 1)), - DAFFODILS(13441, 8211, 71, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_DAFFODILS_8453, 1)), - BLUEBELLS(13442, 8212, 76, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_BLUEBELLS_8455, 1)), - ROSEMARY_BIG(13437, 8210, 66, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_ROSEMARY_8451, 1)), - DAFFODILS_BIG(13438, 8211, 71, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_DAFFODILS_8453, 1)), - BLUEBELLS_BIG(13439, 8212, 76, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.BAGGED_BLUEBELLS_8455, 1)), - THORNY_HEDGE1(13456, 8203, 56, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.THORNY_HEDGE_8437, 1)), - THORNY_HEDGE2(13457, 8203, 56, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.THORNY_HEDGE_8437, 1)), - THORNY_HEDGE3(13458, 8203, 56, 70, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.THORNY_HEDGE_8437, 1)), - NICE_HEDGE1(13459, 8204, 60, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.NICE_HEDGE_8439, 1)), - NICE_HEDGE2(13461, 8204, 60, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.NICE_HEDGE_8439, 1)), - NICE_HEDGE3(13460, 8204, 60, 100, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.NICE_HEDGE_8439, 1)), - SMALL_BOX_HEDGE1(13462, 8205, 64, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.SMALL_BOX_HEDGE_8441, 1)), - SMALL_BOX_HEDGE2(13464, 8205, 64, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.SMALL_BOX_HEDGE_8441, 1)), - SMALL_BOX_HEDGE3(13463, 8205, 64, 122, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.SMALL_BOX_HEDGE_8441, 1)), - TOPIARY_HEDGE1(13465, 8206, 68, 141, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TOPIARY_HEDGE_8443, 1)), - TOPIARY_HEDGE2(13467, 8206, 68, 141, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TOPIARY_HEDGE_8443, 1)), - TOPIARY_HEDGE3(13466, 8206, 68, 141, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TOPIARY_HEDGE_8443, 1)), - FANCY_HEDGE1(13468, 8207, 72, 158, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.FANCY_HEDGE_8445, 1)), - FANCY_HEDGE2(13470, 8207, 72, 158, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.FANCY_HEDGE_8445, 1)), - FANCY_HEDGE3(13469, 8207, 72, 158, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.FANCY_HEDGE_8445, 1)), - TALL_FANCY_HEDGE1(13471, 8208, 76, 223, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_FANCY_HEDGE_8447, 1)), - TALL_FANCY_HEDGE2(13473, 8208, 76, 223, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_FANCY_HEDGE_8447, 1)), - TALL_FANCY_HEDGE3(13472, 8208, 76, 223, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_FANCY_HEDGE_8447, 1)), - TALL_BOX_HEDGE1(13474, 8209, 80, 316, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_BOX_HEDGE_8449, 1)), - TALL_BOX_HEDGE2(13476, 8209, 80, 316, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_BOX_HEDGE_8449, 1)), - TALL_BOX_HEDGE3(13475, 8209, 80, 316, new int[] {BuildingUtils.WATERING_CAN}, new Item(Items.TALL_BOX_HEDGE_8449, 1)), - BOUNDARY_STONES(13449, 8196, 55, 100, new Item(Items.SOFT_CLAY_1761, 10)), - WOODEN_FENCE(13450, 8197, 59, 280, new Item(Items.PLANK_960, 10)), - STONE_WALL(13451, 8198, 63, 200, new Item(Items.LIMESTONE_BRICK_3420, 10)), - IRON_RAILINGS(13452, 8199, 67, 220, new Item(Items.IRON_BAR_2351, 10), new Item(Items.LIMESTONE_BRICK_3420, 6)), - PICKET_FENCE(13453, 8200, 71, 640, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2)), - GARDEN_FENCE(13454, 8201, 75, 940, new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 2)), - MARBLE_WALL(13455, 8202, 79, 4000, new Item(Items.MARBLE_BLOCK_8786, 10)), - - + GAZEBO (13477, 8192, 65, 1200, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 8), new Item(Items.STEEL_BAR_2353, 4) }), + SMALL_FOUNTAIN (13478, 8193, 71, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), + LARGE_FOUNTAIN (13479, 8194, 75, 1000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 2) }), + POSH_FOUNTAIN (13480, 8195, 81, 1500, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 3) }), + SUNFLOWER (13446, 8213, 66, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_SUNFLOWER_8457) }), + MARIGOLDS (13447, 8214, 71, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MARIGOLDS_8459) }), + ROSES (13448, 8215, 76, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_ROSES_8461) }), + SUNFLOWER_BIG (13443, 8213, 66, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_SUNFLOWER_8457) }), + MARIGOLDS_BIG (13444, 8214, 71, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_MARIGOLDS_8459) }), + ROSES_BIG (13445, 8215, 76, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_ROSES_8461) }), + ROSEMARY (13440, 8210, 66, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_ROSEMARY_8451) }), + DAFFODILS (13441, 8211, 71, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_DAFFODILS_8453) }), + BLUEBELLS (13442, 8212, 76, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_BLUEBELLS_8455) }), + ROSEMARY_BIG (13437, 8210, 66, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_ROSEMARY_8451) }), + DAFFODILS_BIG (13438, 8211, 71, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_DAFFODILS_8453) }), + BLUEBELLS_BIG (13439, 8212, 76, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.BAGGED_BLUEBELLS_8455) }), + THORNY_HEDGE1 (13456, 8203, 56, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.THORNY_HEDGE_8437) }), + THORNY_HEDGE2 (13457, 8203, 56, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.THORNY_HEDGE_8437) }), + THORNY_HEDGE3 (13458, 8203, 56, 70, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.THORNY_HEDGE_8437) }), + NICE_HEDGE1 (13459, 8204, 60, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.NICE_HEDGE_8439) }), + NICE_HEDGE2 (13461, 8204, 60, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.NICE_HEDGE_8439) }), + NICE_HEDGE3 (13460, 8204, 60, 100, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.NICE_HEDGE_8439) }), + SMALL_BOX_HEDGE1 (13462, 8205, 64, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.SMALL_BOX_HEDGE_8441) }), + SMALL_BOX_HEDGE2 (13464, 8205, 64, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.SMALL_BOX_HEDGE_8441) }), + SMALL_BOX_HEDGE3 (13463, 8205, 64, 122, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.SMALL_BOX_HEDGE_8441) }), + TOPIARY_HEDGE1 (13465, 8206, 68, 141, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TOPIARY_HEDGE_8443) }), + TOPIARY_HEDGE2 (13467, 8206, 68, 141, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TOPIARY_HEDGE_8443) }), + TOPIARY_HEDGE3 (13466, 8206, 68, 141, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TOPIARY_HEDGE_8443) }), + FANCY_HEDGE1 (13468, 8207, 72, 158, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.FANCY_HEDGE_8445) }), + FANCY_HEDGE2 (13470, 8207, 72, 158, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.FANCY_HEDGE_8445) }), + FANCY_HEDGE3 (13469, 8207, 72, 158, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.FANCY_HEDGE_8445) }), + TALL_FANCY_HEDGE1(13471, 8208, 76, 223, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_FANCY_HEDGE_8447) }), + TALL_FANCY_HEDGE2(13473, 8208, 76, 223, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_FANCY_HEDGE_8447) }), + TALL_FANCY_HEDGE3(13472, 8208, 76, 223, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_FANCY_HEDGE_8447) }), + TALL_BOX_HEDGE1 (13474, 8209, 80, 316, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_BOX_HEDGE_8449) }), + TALL_BOX_HEDGE2 (13476, 8209, 80, 316, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_BOX_HEDGE_8449) }), + TALL_BOX_HEDGE3 (13475, 8209, 80, 316, new int[] { BuildingUtils.WATERING_CAN }, new Item[] { new Item(Items.TALL_BOX_HEDGE_8449) }), + BOUNDARY_STONES (13449, 8196, 55, 100, new Item[] { new Item(Items.SOFT_CLAY_1761, 10) }), + WOODEN_FENCE (13450, 8197, 59, 280, new Item[] { new Item(Items.PLANK_960, 10) }), + STONE_WALL (13451, 8198, 63, 200, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 10) }), + IRON_RAILINGS (13452, 8199, 67, 220, new Item[] { new Item(Items.IRON_BAR_2351, 10), new Item(Items.LIMESTONE_BRICK_3420, 6) }), + PICKET_FENCE (13453, 8200, 71, 640, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2) }), + GARDEN_FENCE (13454, 8201, 75, 940, new Item[] { new Item(Items.TEAK_PLANK_8780, 10), new Item(Items.STEEL_BAR_2353, 2) }), + MARBLE_WALL (13455, 8202, 79, 4000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 10) }), + /** * Bedroom decorations. */ - WOODEN_BED(13148, 8031, 20, 117, new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - OAK_BED(13149, 8032, 30, 210, new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - LARGE_OAK_BED(13150, 8033, 34, 330, new Item(Items.OAK_PLANK_8778, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - TEAK_BED(13151, 8034, 40, 300, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - LARGE_TEAK_BED(13152, 8035, 45, 480, new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - FOUR_POSTER(13153, 8036, 53, 450, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - GILDED_FOUR_POSTER(13154, 8037, 60, 1330, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 2)), - OAK_CLOCK(13169, 8052, 25, 142, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.CLOCKWORK_8792, 1)), - TEAK_CLOCK(13170, 8053, 55, 202, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CLOCKWORK_8792, 1)), - GILDED_CLOCK(13171, 8054, 85, 602, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.CLOCKWORK_8792, 1), new Item(Items.GOLD_LEAF_8784, 1)), - SHAVING_STAND(13162, 8045, 21, 30, new Item(Items.PLANK_960, 1), new Item(Items.MOLTEN_GLASS_1775, 1)), - OAK_SHAVING_STAND(13163, 8046, 29, 61, new Item(Items.OAK_PLANK_8778, 1), new Item(Items.MOLTEN_GLASS_1775, 1)), - OAK_DRESSER(13164, 8047, 37, 121, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - TEAK_DRESSER(13165, 8048, 46, 181, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - FANCY_TEAK_DRESSER(13166, 8049, 56, 182, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2)), - MAHOGANY_DRESSER(13167, 8050, 64, 281, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - GILDED_DRESSER(13168, 8051, 74, 582, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.GOLD_LEAF_8784, 1)), - SHOE_BOX(13155, 8038, 20, 58, new Item(Items.PLANK_960, 2)), - OAK_DRAWERS(13156, 8039, 27, 120, new Item(Items.OAK_PLANK_8778, 2)), - OAK_WARDROBE(13157, 8040, 39, 180, new Item(Items.OAK_PLANK_8778, 3)), - TEAK_DRAWERS(13158, 8041, 51, 180, new Item(Items.TEAK_PLANK_8780, 2)), - TEAK_WARDROBE(13159, 8042, 63, 270, new Item(Items.TEAK_PLANK_8780, 3)), - MAHOGANY_WARDROBE(13160, 8043, 75, 420, new Item(Items.MAHOGANY_PLANK_8782, 2)), - GILDED_WARDROBE(13161, 8044, 87, 720, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784, 1)), - - + WOODEN_BED (13148, 8031, 20, 117, new Item[] { new Item(Items.PLANK_960, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + OAK_BED (13149, 8032, 30, 210, new Item[] { new Item(Items.OAK_PLANK_8778, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + LARGE_OAK_BED (13150, 8033, 34, 330, new Item[] { new Item(Items.OAK_PLANK_8778, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + TEAK_BED (13151, 8034, 40, 300, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + LARGE_TEAK_BED (13152, 8035, 45, 480, new Item[] { new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + FOUR_POSTER (13153, 8036, 53, 450, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + GILDED_FOUR_POSTER(13154, 8037, 60, 1330, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 2) }), + OAK_CLOCK (13169, 8052, 25, 142, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.CLOCKWORK_8792) }), + TEAK_CLOCK (13170, 8053, 55, 202, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.CLOCKWORK_8792) }), + GILDED_CLOCK (13171, 8054, 85, 602, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.CLOCKWORK_8792), new Item(Items.GOLD_LEAF_8784) }), + SHAVING_STAND (13162, 8045, 21, 30, new Item[] { new Item(Items.PLANK_960), new Item(Items.MOLTEN_GLASS_1775) }), + OAK_SHAVING_STAND (13163, 8046, 29, 61, new Item[] { new Item(Items.OAK_PLANK_8778), new Item(Items.MOLTEN_GLASS_1775) }), + OAK_DRESSER (13164, 8047, 37, 121, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775) }), + TEAK_DRESSER (13165, 8048, 46, 181, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775) }), + FANCY_TEAK_DRESSER(13166, 8049, 56, 182, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 2) }), + MAHOGANY_DRESSER (13167, 8050, 64, 281, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775) }), + GILDED_DRESSER (13168, 8051, 74, 582, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 2), new Item(Items.GOLD_LEAF_8784) }), + SHOE_BOX (13155, 8038, 20, 58, new Item[] { new Item(Items.PLANK_960, 2) }), + OAK_DRAWERS (13156, 8039, 27, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + OAK_WARDROBE (13157, 8040, 39, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + TEAK_DRAWERS (13158, 8041, 51, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + TEAK_WARDROBE (13159, 8042, 63, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + MAHOGANY_WARDROBE (13160, 8043, 75, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + GILDED_WARDROBE (13161, 8044, 87, 720, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784) }), + /** * Quest hall decorations. */ - ANTIDRAGON_SHIELD(13522, 8282, 47, 280, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ANTI_DRAGON_SHIELD_1540, 1)), - AMULET_OF_GLORY(13523, 8283, 47, 290, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.AMULET_OF_GLORY_1704, 1)), - CAPE_OF_LEGENDS(13524, 8284, 47, 300, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.CAPE_OF_LEGENDS_1052, 1)), - KING_ARTHUR(13510, 8285, 35, 211, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ARTHUR_PORTRAIT_7995, 1)), - ELENA(13511, 8286, 35, 211, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ELENA_PORTRAIT_7996, 1)), - GIANT_DWARF(13512, 8287, 35, 211, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.KELDAGRIM_PORTRAIT_7997, 1)), - MISCELLANIANS(13513, 8288, 35, 311, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.MISC_PORTRAIT_7998, 1)), - LUMBRIDGE(13517, 8289, 44, 314, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.LUMBRIDGE_PAINTING_8002, 1)), - THE_DESERT(13514, 8290, 44, 314, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.DESERT_PAINTING_7999, 1)), - MORYTANIA(13518, 8291, 44, 314, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.MORYTANIA_PAINTING_8003, 1)), - KARAMJA(13516, 8292, 65, 464, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.KARAMJA_PAINTING_8001, 1)), - ISAFDAR(13515, 8293, 65, 464, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.ISAFDAR_PAINTING_8000, 1)), - SILVERLIGHT(13519, 8279, 42, 187, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SILVERLIGHT_2402, 1)), - EXCALIBUR(13521, 8280, 42, 194, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.EXCALIBUR_35, 1)), - DARKLIGHT(13520, 8281, 42, 202, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.DARKLIGHT_6746, 1)), - SMALL_MAP(13525, 8294, 38, 211, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SMALL_MAP_8004, 1)), - MEDIUM_MAP(13526, 8295, 58, 451, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.MEDIUM_MAP_8005, 1)), - LARGE_MAP(13527, 8296, 78, 591, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.LARGE_MAP_8006, 1)), - - /** - * Menagerie Decorations - */ - //OBELISK - MINI_OBELISK(44837, 15236, 41, 676, new Item(Items.MARBLE_BLOCK_8786, 1), new Item(Items.SPIRIT_SHARDS_12183, 1000), new Item(Items.GOLD_CHARM_12158, 10), new Item(Items.GREEN_CHARM_12159, 10), new Item(Items.CRIMSON_CHARM_12160, 10), new Item(Items.BLUE_CHARM_12163, 10)) - //PET_FEEDER - , - OAK_PET_FEEDER(44834, 15233, 37, 240, new Item(Items.OAK_PLANK_8778, 4)), - TEAK_PET_FEEDER(44835, 15234, 52, 380, new Item(Items.TEAK_PLANK_8780, 4)), - MAHOGANY_PET_FEEDER(44836, 15235, 67, 880, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 1)) - //PET_HOUSE - , - OAK_PET_HOUSE(44828, 15227, 37, 240, new Item(Items.OAK_PLANK_8778, 4)), - TEAK_PET_HOUSE(44829, 15228, 52, 380, new Item(Items.TEAK_PLANK_8780, 4)), - MAHOGANY_PET_HOUSE(44830, 15229, 67, 580, new Item(Items.MAHOGANY_PLANK_8782, 4)), - CONSECRATED_PET_HOUSE(44831, 15230, 92, 1580, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.MAGIC_STONE_8788, 1)), - DESECRATED_PET_HOUSE(44832, 15231, 92, 1580, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.MAGIC_STONE_8788, 1)), - NATURAL_PET_HOUSE(44833, 15232, 92, 1580, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.MAGIC_STONE_8788, 1)) - //HABITAT_SPACE - , - GARDEN_HABITAT(new int[]{ - 4497, - 4498, - 44500, - 44501, - 44502, - 44503, - 44504, - 44505, - 44506, - 44507, - 44508, - 44509, - 44510, - 44511, - 44512, - 44513, - 44514, - 44515, - 44516, - 44517, - 44518, - 44519, - 44520, - 44521, - 44522, - 44523, - 44524, - 44525, - 44526, - 44527, - 44528, - 44529, - 44530, - 44531, - 44532, - 44533, - 44534, - 44535, - 44536, - 44537, - 44538, - 44539, - 44540, - 44541, - 44542, - 44543, - 44544, - 44545, - 44546, - 44547, - 44548, - 44549, - 44550, - 44551, - 44552, - 44553, - 44554, - 44555, - 44556, - 44557, - 44558, - 44559, - 44560, - 44561, - 44562, - 44563 }, 15222, 37, 201, new Item(Items.BAGGED_PLANT_1_8431, 1), new Item(Items.BAGGED_PLANT_2_8433, 1), new Item(Items.BAGGED_PLANT_3_8435, 1)), - JUNGLE_HABITAT(new int[] - { - 44564, - 44565, - 44566, - 44567, - 44568, - 44569, - 44570, - 44571, - 44572, - 44573, - 44574, - 44575, - 44576, - 44577, - 44578, - 44579, - 44580, - 44581, - 44582, - 44583, - 44584, - 44585, - 44586, - 44587, - 44588, - 44589, - 44590, - 44591, - 44592, - 44593, - 44594, - 44595, - 44596, - 44597, - 44598, - 44599, - 44600, - 44601, - 44602, - 44603, - 44604, - 44605, - 44606, - 44607, - 44608, - 44609, - 44610, - 44611, - 44612, - 44613, - 44614, - 44615, - 44616, - 44617, - 44618, - 44619, - 44620, - 44621, - 44622, - 44623, - 44624, - 44625, - 44626, - 44627, - 44628, - 44629 }, 15223, 47, 278, new Item(Items.BAGGED_PLANT_3_8435, 3), new Item(Items.BAGGED_WILLOW_TREE_8423, 1), new Item(Items.BUCKET_OF_WATER_1929, 5)), - DESERT_HABITAT(new int[] - { - 44630, - 44631, - 44632, - 44633, - 44634, - 44635, - 44636, - 44637, - 44638, - 44639, - 44640, - 44641, - 44642, - 44643, - 44644, - 44645, - 44646, - 44647, - 44648, - 44649, - 44650, - 44651, - 44652, - 44653, - 44654, - 44655, - 44656, - 44657, - 44658, - 44659, - 44660, - 44661, - 44662, - 44663, - 44664, - 44665, - 44666, - 44667, - 44668, - 44669, - 44670, - 44671, - 44672, - 44673, - 44674, - 44675, - 44676, - 44677, - 44678, - 44679, - 44680, - 44681, - 44682, - 44683, - 44684, - 44685, - 44686, - 44687, - 44688, - 44689, - 44690, - 44691, - 44692, - 44693, - 44694, - 44695 }, 15224, 57, 238, new Item(Items.BUCKET_OF_SAND_1783, 10), new Item(Items.LIMESTONE_BRICK_3420, 5), new Item(15237, 1)), - POLAR_HABITAT(new int[] - { - 44696, - 44697, - 44698, - 44699, - 44700, - 44701, - 44702, - 44703, - 44704, - 44705, - 44706, - 44707, - 44708, - 44709, - 44710, - 44711, - 44712, - 44713, - 44714, - 44715, - 44716, - 44717, - 44718, - 44719, - 44720, - 44721, - 44722, - 44723, - 44724, - 44725, - 44726, - 44727, - 44728, - 44729, - 44730, - 44731, - 44732, - 44733, - 44734, - 44735, - 44736, - 44737, - 44738, - 44739, - 44740, - 44741, - 44742, - 44743, - 44744, - 44745, - 44746, - 44747, - 44748, - 44749, - 44750, - 44751, - 44752, - 44753, - 44754, - 44755, - 44756, - 44757, - 44758, - 44759, - 44760, - 44761 }, 15225, 67, 373, new Item(Items.AIR_RUNE_556, 1000), new Item(Items.WATER_RUNE_555, 1000), new Item(15239, 1)), - VOLCANIC_HABITAT(new int[] - { - 44762, - 44763, - 44764, - 44765, - 44766, - 44767, - 44768, - 44769, - 44770, - 44771, - 44772, - 44773, - 44774, - 44775, - 44776, - 44777, - 44778, - 44779, - 44780, - 44781, - 44782, - 44783, - 44784, - 44785, - 44786, - 44787, - 44788, - 44789, - 44790, - 44791, - 44792, - 44793, - 44794, - 44795, - 44796, - 44797, - 44798, - 44799, - 44800, - 44801, - 44802, - 44803, - 44804, - 44805, - 44806, - 44807, - 44808, - 44809, - 44810, - 44811, - 44812, - 44813, - 44814, - 44815, - 44816, - 44817, - 44818, - 44819, - 44820, - 44821, - 44822, - 44823, - 44824, - 44825, - 44826, - 44827 }, 15226, 77, 77, new Item(Items.FIRE_RUNE_554, 1000), new Item(Items.EARTH_RUNE_557, 1000), new Item(Items.BAGGED_DEAD_TREE_8417, 1), new Item(Items.STONE_SLAB_13245, 5)), - + ANTIDRAGON_SHIELD(13522, 8282, 47, 280, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ANTI_DRAGON_SHIELD_1540) }, new Item[] { new Item(Items.ANTI_DRAGON_SHIELD_1540) }), + AMULET_OF_GLORY (13523, 8283, 47, 290, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.AMULET_OF_GLORY_1704) }, new Item[] { new Item(Items.AMULET_OF_GLORY_1704) }), + CAPE_OF_LEGENDS (13524, 8284, 47, 300, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.CAPE_OF_LEGENDS_1052) }, new Item[] { new Item(Items.CAPE_OF_LEGENDS_1052) }), + KING_ARTHUR (13510, 8285, 35, 211, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ARTHUR_PORTRAIT_7995) }), + ELENA (13511, 8286, 35, 211, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.ELENA_PORTRAIT_7996) }), + GIANT_DWARF (13512, 8287, 35, 211, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.KELDAGRIM_PORTRAIT_7997) }), + MISCELLANIANS (13513, 8288, 35, 311, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.MISC_PORTRAIT_7998) }), + LUMBRIDGE (13517, 8289, 44, 314, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.LUMBRIDGE_PAINTING_8002) }), + THE_DESERT (13514, 8290, 44, 314, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.DESERT_PAINTING_7999) }), + MORYTANIA (13518, 8291, 44, 314, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.MORYTANIA_PAINTING_8003) }), + KARAMJA (13516, 8292, 65, 464, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.KARAMJA_PAINTING_8001) }), + ISAFDAR (13515, 8293, 65, 464, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.ISAFDAR_PAINTING_8000) }), + SILVERLIGHT (13519, 8279, 42, 187, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SILVERLIGHT_2402) }, new Item[] { new Item(Items.SILVERLIGHT_2402) }), + EXCALIBUR (13521, 8280, 42, 194, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.EXCALIBUR_35) }, new Item[] { new Item(Items.EXCALIBUR_35) }), + DARKLIGHT (13520, 8281, 42, 202, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.DARKLIGHT_6746) }, new Item[] { new Item(Items.DARKLIGHT_6746) }), + SMALL_MAP (13525, 8294, 38, 211, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.SMALL_MAP_8004) }), + MEDIUM_MAP (13526, 8295, 58, 451, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.MEDIUM_MAP_8005) }), + LARGE_MAP (13527, 8296, 78, 591, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.LARGE_MAP_8006) }), /** * Study decorations. */ - GLOBE(13649, 8341, 41, 180, new Item(Items.OAK_PLANK_8778, 3)), - ORNAMENTAL_GLOBE(13650, 8342, 50, 270, new Item(Items.TEAK_PLANK_8780, 3)), - LUNAR_GLOBE(13651, 8343, 59, 570, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.GOLD_LEAF_8784, 1)), - CELESTIAL_GLOBE(13652, 8344, 68, 570, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.GOLD_LEAF_8784, 1)), - ARMILLARY_SPHERE(13653, 8345, 77, 960, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784, 2), new Item(Items.STEEL_BAR_2353, 4)), - SMALL_ORREY(13654, 8346, 86, 1320, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 3)), - LARGE_ORREY(13655, 8347, 95, 1420, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 5)), - OAK_LECTERN(13642, 8334, 40, 60, new Item(Items.OAK_PLANK_8778, 1)), - EAGLE_LECTERN(13643, 8335, 47, 120, new Item(Items.OAK_PLANK_8778, 2)), - DEMON_LECTERN(13644, 8336, 47, 120, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_EAGLE_LECTERN(13645, 8337, 57, 180, new Item(Items.TEAK_PLANK_8780, 2)), - TEAK_DEMON_LECTERN(13646, 8338, 57, 180, new Item(Items.TEAK_PLANK_8780, 2)), - MAHOGANY_EAGLE_LECTERN(13647, 8339, 67, 580, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784, 1)), - MAHOGANY_DEMON_LECTERN(13648, 8340, 67, 580, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784, 1)), - CRYSTAL_BALL(13659, 8351, 42, 280, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.UNPOWERED_ORB_567, 1)), - ELEMENTAL_SPHERE(13660, 8352, 54, 580, new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.UNPOWERED_ORB_567, 1), new Item(Items.GOLD_LEAF_8784, 1)), - CRYSTAL_OF_POWER(13661, 8353, 66, 890, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.UNPOWERED_ORB_567, 1), new Item(Items.GOLD_LEAF_8784, 2)), - ALCHEMICAL_CHART(13662, 8354, 43, 30, new Item(Items.BOLT_OF_CLOTH_8790, 2)), - ASTRONOMICAL_CHART(13663, 8355, 63, 45, new Item(Items.BOLT_OF_CLOTH_8790, 3)), - INFERNAL_CHART(13664, 8356, 83, 60, new Item(Items.BOLT_OF_CLOTH_8790, 4)), - TELESCOPE1(13656, 8348, 44, 121, new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - TELESCOPE2(13657, 8349, 64, 181, new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - TELESCOPE3(13658, 8350, 84, 580, new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775, 1)), - + GLOBE (13649, 8341, 41, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + ORNAMENTAL_GLOBE (13650, 8342, 50, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + LUNAR_GLOBE (13651, 8343, 59, 570, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.GOLD_LEAF_8784) }), + CELESTIAL_GLOBE (13652, 8344, 68, 570, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.GOLD_LEAF_8784) }), + ARMILLARY_SPHERE (13653, 8345, 77, 960, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784, 2), new Item(Items.STEEL_BAR_2353, 4) }), + SMALL_ORREY (13654, 8346, 86, 1320, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 3) }), + LARGE_ORREY (13655, 8347, 95, 1420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 5) }), + OAK_LECTERN (13642, 8334, 40, 60, new Item[] { new Item(Items.OAK_PLANK_8778) }), + EAGLE_LECTERN (13643, 8335, 47, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + DEMON_LECTERN (13644, 8336, 47, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_EAGLE_LECTERN (13645, 8337, 57, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + TEAK_DEMON_LECTERN (13646, 8338, 57, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + MAHOGANY_EAGLE_LECTERN(13647, 8339, 67, 580, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784) }), + MAHOGANY_DEMON_LECTERN(13648, 8340, 67, 580, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.GOLD_LEAF_8784) }), + CRYSTAL_BALL (13659, 8351, 42, 280, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.UNPOWERED_ORB_567) }), + ELEMENTAL_SPHERE (13660, 8352, 54, 580, new Item[] { new Item(Items.TEAK_PLANK_8780, 3), new Item(Items.UNPOWERED_ORB_567), new Item(Items.GOLD_LEAF_8784) }), + CRYSTAL_OF_POWER (13661, 8353, 66, 890, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.UNPOWERED_ORB_567), new Item(Items.GOLD_LEAF_8784, 2) }), + ALCHEMICAL_CHART (13662, 8354, 43, 30, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + ASTRONOMICAL_CHART (13663, 8355, 63, 45, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 3) }), + INFERNAL_CHART (13664, 8356, 83, 60, new Item[] { new Item(Items.BOLT_OF_CLOTH_8790, 4) }), + TELESCOPE1 (13656, 8348, 44, 121, new Item[] { new Item(Items.OAK_PLANK_8778, 2), new Item(Items.MOLTEN_GLASS_1775) }), + TELESCOPE2 (13657, 8349, 64, 181, new Item[] { new Item(Items.TEAK_PLANK_8780, 2), new Item(Items.MOLTEN_GLASS_1775) }), + TELESCOPE3 (13658, 8350, 84, 580, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2), new Item(Items.MOLTEN_GLASS_1775) }), + /** * Costume room decorations. */ - OAK_TREASURE_CHEST(18804, 9839, 48, 120, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_TREASURE_CHEST(18806, 9840, 66, 180, new Item(Items.TEAK_PLANK_8780, 2)), - MAHOGANY_TREASURE_CHEST(18808, 9841, 84, 280, new Item(Items.MAHOGANY_PLANK_8782, 2)), - OAK_ARMOUR_CASE(18778, 9826, 46, 180, new Item(Items.OAK_PLANK_8778, 3)), - TEAK_ARMOUR_CASE(18780, 9827, 64, 270, new Item(Items.TEAK_PLANK_8780, 3)), - MGANY_ARMOUR_CASE(18782, 9828, 82, 420, new Item(Items.MAHOGANY_PLANK_8782, 3)), - OAK_MAGIC_WARDROBE(18784, 9829, 42, 240, new Item(Items.OAK_PLANK_8778, 4)), - C_OAK_MAGIC_WARDROBE(18786, 9830, 51, 360, new Item(Items.OAK_PLANK_8778, 6)), - TEAK_MAGIC_WARDROBE(18788, 9831, 60, 360, new Item(Items.TEAK_PLANK_8780, 4)), - C_TEAK_MAGIC_WARDROBE(18790, 9832, 69, 540, new Item(Items.TEAK_PLANK_8780, 6)), - MGANY_MAGIC_WARDROBE(18792, 9833, 78, 560, new Item(Items.MAHOGANY_PLANK_8782, 4)), - GILDED_MAGIC_WARDROBE(18794, 9834, 87, 860, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 1)), - MARBLE_MAGIC_WARDROBE(18796, 9835, 96, 500, new Item(Items.MARBLE_BLOCK_8786, 1)), - OAK_CAPE_RACK(18766, 9817, 54, 240, new Item(Items.OAK_PLANK_8778, 4)), - TEAK_CAPE_RACK(18767, 9818, 63, 360, new Item(Items.TEAK_PLANK_8780, 4)), - MGANY_CAPE_RACK(18768, 9819, 72, 560, new Item(Items.MAHOGANY_PLANK_8782, 4)), - GILDED_CAPE_RACK(18769, 9820, 81, 860, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 1)), - MARBLE_CAPE_RACK(18770, 9821, 90, 500, new Item(Items.MARBLE_BLOCK_8786, 1)), - MAGIC_CAPE_RACK(18771, 9822, 99, 1000, new Item(Items.MAGIC_STONE_8788, 1)), - OAK_TOY_BOX(18798, 9836, 50, 120, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_TOY_BOX(18800, 9837, 68, 180, new Item(Items.TEAK_PLANK_8780, 2)), - MAHOGANY_TOY_BOX(18802, 9838, 86, 280, new Item(Items.MAHOGANY_PLANK_8782, 2)), - OAK_COSTUME_BOX(18772, 9823, 44, 120, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_COSTUME_BOX(18774, 9824, 62, 180, new Item(Items.TEAK_PLANK_8780, 2)), - MAHOGANY_COSTUME_BOX(18776, 9825, 80, 280, new Item(Items.MAHOGANY_PLANK_8782, 2)), - + OAK_TREASURE_CHEST (18804, 9839, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_TREASURE_CHEST (18806, 9840, 66, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + MAHOGANY_TREASURE_CHEST(18808, 9841, 84, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + OAK_ARMOUR_CASE (18778, 9826, 46, 180, new Item[] { new Item(Items.OAK_PLANK_8778, 3) }), + TEAK_ARMOUR_CASE (18780, 9827, 64, 270, new Item[] { new Item(Items.TEAK_PLANK_8780, 3) }), + MGANY_ARMOUR_CASE (18782, 9828, 82, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), + OAK_MAGIC_WARDROBE (18784, 9829, 42, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + C_OAK_MAGIC_WARDROBE (18786, 9830, 51, 360, new Item[] { new Item(Items.OAK_PLANK_8778, 6) }), + TEAK_MAGIC_WARDROBE (18788, 9831, 60, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + C_TEAK_MAGIC_WARDROBE (18790, 9832, 69, 540, new Item[] { new Item(Items.TEAK_PLANK_8780, 6) }), + MGANY_MAGIC_WARDROBE (18792, 9833, 78, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }), + GILDED_MAGIC_WARDROBE (18794, 9834, 87, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }), + MARBLE_MAGIC_WARDROBE (18796, 9835, 96, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), + OAK_CAPE_RACK (18766, 9817, 54, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + TEAK_CAPE_RACK (18767, 9818, 63, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + MGANY_CAPE_RACK (18768, 9819, 72, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }), + GILDED_CAPE_RACK (18769, 9820, 81, 860, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784) }), + MARBLE_CAPE_RACK (18770, 9821, 90, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), + MAGIC_CAPE_RACK (18771, 9822, 99, 1000, new Item[] { new Item(Items.MAGIC_STONE_8788) }), + OAK_TOY_BOX (18798, 9836, 50, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_TOY_BOX (18800, 9837, 68, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + MAHOGANY_TOY_BOX (18802, 9838, 86, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + OAK_COSTUME_BOX (18772, 9823, 44, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_COSTUME_BOX (18774, 9824, 62, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + MAHOGANY_COSTUME_BOX (18776, 9825, 80, 280, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 2) }), + /** * Chapel decorations. */ - OAK_ALTAR(13179, 8062, 45, 240, new Item(Items.OAK_PLANK_8778, 4)), - TEAK_ALTAR(13182, 8063, 50, 360, new Item(Items.TEAK_PLANK_8780, 4)), - CLOTH_ALTAR(13185, 8064, 56, 390, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - MAHOGANY_ALTAR(13188, 8065, 60, 590, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - LIMESTONE_ALTAR(13191, 8066, 64, 910, new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.LIMESTONE_BRICK_3420, 2)), - MARBLE_ALTAR(13194, 8067, 70, 1030, new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.BOLT_OF_CLOTH_8790, 2)), - GILDED_ALTAR(13197, 8068, 75, 2230, new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 4)), - SMALL_STATUE(13271, 8082, 49, 40, new Item(Items.LIMESTONE_BRICK_3420, 2)), - MEDIUM_STATUE(13272, 8083, 69, 500, new Item(Items.MARBLE_BLOCK_8786, 1)), - LARGE_STATUE(13282, 8084, 89, 1500, new Item(Items.MARBLE_BLOCK_8786, 3)), - WINDCHIMES(13214, 8079, 49, 323, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.STEEL_BAR_2353, 4)), - BELLS(13215, 8080, 58, 480, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.STEEL_BAR_2353, 6)), - ORGAN(13216, 8081, 69, 680, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.STEEL_BAR_2353, 6)), - SARADOMIN_SYMBOL(13172, 8055, 48, 120, new Item(Items.OAK_PLANK_8778, 2)), - ZAMORAK_SYMBOL(13173, 8056, 48, 120, new Item(Items.OAK_PLANK_8778, 2)), - GUTHIX_SYMBOL(13174, 8057, 48, 120, new Item(Items.OAK_PLANK_8778, 2)), - SARADOMIN_ICON(13175, 8058, 59, 960, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2)), - ZAMORAK_ICON(13176, 8059, 59, 960, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2)), - GUTHIX_ICON(13177, 8060, 59, 960, new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2)), - ICON_OF_BOB(13178, 8061, 71, 1160, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 2)), - STEEL_TORCHES(13202, 8070, 45, 80, new Item(Items.STEEL_BAR_2353, 2)), - WOODEN_TORCHES(13200, 8069, 49, 58, new Item(Items.PLANK_960, 2)), - STEEL_CANDLESTICKS(13204, 8071, 53, 124, new Item(Items.STEEL_BAR_2353, 6), new Item(Items.CANDLE_36, 6)), - GOLD_CANDLESTICKS(13206, 8072, 57, 46, new Item(Items.GOLD_BAR_2357, 6), new Item(Items.CANDLE_36, 6)), - INCENSE_BURNERS(13208, 8073, 61, 280, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.STEEL_BAR_2353, 2)), - MAHOGANY_BURNERS(13210, 8074, 65, 600, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.STEEL_BAR_2353, 2)), - MARBLE_BURNERS(13212, 8075, 69, 1600, new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.STEEL_BAR_2353, 2)), - SHUTTERED_WINDOW(new int[] { 13253, 13226, 13235, 13244, 13217, 13262 }, 8076, 49, 228, new Item(Items.PLANK_960, 8)), - DECORATIVE_WINDOW(new int[] { 13254, 13227, 13236, 13245, 13218, 13263 }, 8077, 69, 200, new Item(Items.MOLTEN_GLASS_1775, 8)), - STAINED_GLASS(new int[] { 13255, 13228, 13237, 13246, 13219, 13264 }, 8078, 89, 400, new Item(Items.MOLTEN_GLASS_1775, 16)), + OAK_ALTAR (13179, 8062, 45, 240, new Item[] { new Item(Items.OAK_PLANK_8778, 4) }), + TEAK_ALTAR (13182, 8063, 50, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + CLOTH_ALTAR (13185, 8064, 56, 390, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + MAHOGANY_ALTAR (13188, 8065, 60, 590, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + LIMESTONE_ALTAR (13191, 8066, 64, 910, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 6), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.LIMESTONE_BRICK_3420, 2) }), + MARBLE_ALTAR (13194, 8067, 70, 1030, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.BOLT_OF_CLOTH_8790, 2) }), + GILDED_ALTAR (13197, 8068, 75, 2230, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.BOLT_OF_CLOTH_8790, 2), new Item(Items.GOLD_LEAF_8784, 4) }), + SMALL_STATUE (13271, 8082, 49, 40, new Item[] { new Item(Items.LIMESTONE_BRICK_3420, 2) }), + MEDIUM_STATUE (13272, 8083, 69, 500, new Item[] { new Item(Items.MARBLE_BLOCK_8786) }), + LARGE_STATUE (13282, 8084, 89, 1500, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 3) }), + WINDCHIMES (13214, 8079, 49, 323, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.STEEL_BAR_2353, 4) }), + BELLS (13215, 8080, 58, 480, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.STEEL_BAR_2353, 6) }), + ORGAN (13216, 8081, 69, 680, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.STEEL_BAR_2353, 6) }), + SARADOMIN_SYMBOL (13172, 8055, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + ZAMORAK_SYMBOL (13173, 8056, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + GUTHIX_SYMBOL (13174, 8057, 48, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + SARADOMIN_ICON (13175, 8058, 59, 960, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2) }), + ZAMORAK_ICON (13176, 8059, 59, 960, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2) }), + GUTHIX_ICON (13177, 8060, 59, 960, new Item[] { new Item(Items.TEAK_PLANK_8780, 4), new Item(Items.GOLD_LEAF_8784, 2) }), + ICON_OF_BOB (13178, 8061, 71, 1160, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 2) }), + STEEL_TORCHES (13202, 8070, 45, 80, new Item[] { new Item(Items.STEEL_BAR_2353, 2) }), + WOODEN_TORCHES (13200, 8069, 49, 58, new Item[] { new Item(Items.PLANK_960, 2) }), + STEEL_CANDLESTICKS(13204, 8071, 53, 124, new Item[] { new Item(Items.STEEL_BAR_2353, 6), new Item(Items.CANDLE_36, 6) }), + GOLD_CANDLESTICKS (13206, 8072, 57, 46, new Item[] { new Item(Items.GOLD_BAR_2357, 6), new Item(Items.CANDLE_36, 6) }), + INCENSE_BURNERS (13208, 8073, 61, 280, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.STEEL_BAR_2353, 2) }), + MAHOGANY_BURNERS (13210, 8074, 65, 600, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.STEEL_BAR_2353, 2) }), + MARBLE_BURNERS (13212, 8075, 69, 1600, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.STEEL_BAR_2353, 2) }), + SHUTTERED_WINDOW (new int[] { 13253, 13226, 13235, 13244, 13217, 13262 }, 8076, 49, 228, new Item[] { new Item(Items.PLANK_960, 8) }), + DECORATIVE_WINDOW (new int[] { 13254, 13227, 13236, 13245, 13218, 13263 }, 8077, 69, 200, new Item[] { new Item(Items.MOLTEN_GLASS_1775, 8) }), + STAINED_GLASS (new int[] { 13255, 13228, 13237, 13246, 13219, 13264 }, 8078, 89, 400, new Item[] { new Item(Items.MOLTEN_GLASS_1775, 16) }), /** * Throne room */ - OAK_THRONE(13665, 8357, 60, 800, new Item(Items.OAK_PLANK_8778, 5), new Item(Items.MARBLE_BLOCK_8786, 1)), - TEAK_THRONE(13666, 8358, 67, 1450, new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.MARBLE_BLOCK_8786, 2)), - MAHOGANY_THRONE(13667, 8359, 74, 2200, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 3)), - GILDED_THRONE(13668, 8360, 81, 1700, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.GOLD_LEAF_8784, 3)), - SKELETON_THRONE(13669, 8361, 88, 7003, new Item(Items.MAGIC_STONE_8788, 5), new Item(Items.MARBLE_BLOCK_8786, 4), new Item(Items.BONES_526, 5), new Item(Items.SKULL_964, 2)), - CRYSTAL_THRONE(13670, 8362, 95, 15000, new Item(Items.MAGIC_STONE_8788, 15)), - DEMONIC_THRONE(13671, 8363, 99, 25000, new Item(Items.MAGIC_STONE_8788, 25)), - OAK_LEVER(13672, 8364, 68, 300, new Item(Items.OAK_PLANK_8778, 5)), - TEAK_LEVER(13673, 8365, 78, 450, new Item(Items.TEAK_PLANK_8780, 5)), - MAHOGANY_LEVER(13674, 8366, 88, 700, new Item(Items.MAHOGANY_PLANK_8782, 5)), - FLOOR_DECORATION(new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8370, 61, 700, new Item(Items.MAHOGANY_PLANK_8782, 5)), - STEEL_CAGE(new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8371, 68, 1100, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.STEEL_BAR_2353, 20)), - FLOOR_TRAP(new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8372, 74, 770, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.CLOCKWORK_8792, 10)), - MAGIC_CIRCLE(new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8373, 82, 2700, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MAGIC_STONE_8788, 2)), - MAGIC_CAGE(new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8374, 89, 4700, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MAGIC_STONE_8788, 4)), - OAK_TRAPDOOR(13675, 8367, 68, 300, new Item(Items.OAK_PLANK_8778, 5)), - TEAK_TRAPDOOR(13676, 8368, 78, 450, new Item(Items.TEAK_PLANK_8780, 5)), - MAHOGANY_TRAPDOOR(13677, 8369, 88, 700, new Item(Items.MAHOGANY_PLANK_8782, 5)), - CARVED_TEAK_BENCH(13694, 8112, 44, 360, new Item(Items.TEAK_PLANK_8780, 4)), - MAHOGANY_BENCH(13695, 8113, 52, 560, new Item(Items.MAHOGANY_PLANK_8782, 4)), - GILDED_BENCH(13696, 8114, 61, 1760, new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4)), - OAK_DECO(13798, 8102, 16, 120.0, new Item(Items.OAK_PLANK_8778, 2)), - TEAK_DECO(13814, 8103, 36, 180.0, new Item(Items.TEAK_PLANK_8780, 2)), - GILDED_DECO(13782, 8104, 56, 1020.0, new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 2)), - ROUND_SHIELD(13734, 8105, 66, 120, new Item(Items.OAK_PLANK_8778, 2)), - SQUARE_SHIELD(13766, 8106, 76, 360, new Item(Items.TEAK_PLANK_8780, 4)), - KITE_SHIELD(13750, 8107, 86, 420, new Item(Items.MAHOGANY_PLANK_8782, 3)), - + OAK_THRONE (13665, 8357, 60, 800, new Item[] { new Item(Items.OAK_PLANK_8778, 5), new Item(Items.MARBLE_BLOCK_8786) }), + TEAK_THRONE (13666, 8358, 67, 1450, new Item[] { new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.MARBLE_BLOCK_8786, 2) }), + MAHOGANY_THRONE (13667, 8359, 74, 2200, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 3) }), + GILDED_THRONE (13668, 8360, 81, 1700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MARBLE_BLOCK_8786, 2), new Item(Items.GOLD_LEAF_8784, 3) }), + SKELETON_THRONE (13669, 8361, 88, 7003, new Item[] { new Item(Items.MAGIC_STONE_8788, 5), new Item(Items.MARBLE_BLOCK_8786, 4), new Item(Items.BONES_526, 5), new Item(Items.SKULL_964, 2) }), + CRYSTAL_THRONE (13670, 8362, 95, 15000, new Item[] { new Item(Items.MAGIC_STONE_8788, 15) }), + DEMONIC_THRONE (13671, 8363, 99, 25000, new Item[] { new Item(Items.MAGIC_STONE_8788, 25) }), + OAK_LEVER (13672, 8364, 68, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), + TEAK_LEVER (13673, 8365, 78, 450, new Item[] { new Item(Items.TEAK_PLANK_8780, 5) }), + MAHOGANY_LEVER (13674, 8366, 88, 700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5) }), + FLOOR_DECORATION (new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8370, 61, 700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5) }), + STEEL_CAGE (new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8371, 68, 1100, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.STEEL_BAR_2353, 20) }), + FLOOR_TRAP (new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8372, 74, 770, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.CLOCKWORK_8792, 10) }), + MAGIC_CIRCLE (new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8373, 82, 2700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MAGIC_STONE_8788, 2) }), + MAGIC_CAGE (new int[] { 13689, 13686, 13687, 13688, 13684, 13685 }, 8374, 89, 4700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.MAGIC_STONE_8788, 4) }), + OAK_TRAPDOOR (13675, 8367, 68, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), + TEAK_TRAPDOOR (13676, 8368, 78, 450, new Item[] { new Item(Items.TEAK_PLANK_8780, 5) }), + MAHOGANY_TRAPDOOR(13677, 8369, 88, 700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5) }), + CARVED_TEAK_BENCH(13694, 8112, 44, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + MAHOGANY_BENCH (13695, 8113, 52, 560, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4) }), + GILDED_BENCH (13696, 8114, 61, 1760, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 4), new Item(Items.GOLD_LEAF_8784, 4) }), + OAK_DECO (13798, 8102, 16, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + TEAK_DECO (13814, 8103, 36, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + GILDED_DECO (13782, 8104, 56, 1020, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 2) }), + ROUND_SHIELD (13734, 8105, 66, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), + SQUARE_SHIELD (13766, 8106, 76, 360, new Item[] { new Item(Items.TEAK_PLANK_8780, 4) }), + KITE_SHIELD (13750, 8107, 86, 420, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3) }), + /** * Oubliette */ - SPIKES_MID(13334, 8302, 65, 623, new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000)), - SPIKES_SIDE(13335, 8302, 65, 623, new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000)), - SPIKES_CORNER(13336, 8302, 65, 623, new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000)), - SPIKES_FL(13338, 8302, 65, 623, new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000)), - TENTACLE_MID(13331, 8303, 71, 326, new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000)), - TENTACLE_SIDE(13332, 8303, 71, 326, new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000)), - TENTACLE_CORNER(13333, 8303, 71, 326, new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000)), - TENTACLE_FL(13338, 8303, 71, 326, new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000)), - FP_FLOOR_MID(13371, 8304, 77, 357, new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000)), - FP_FLOOR_SIDE(13371, 8304, 77, 357, new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000)), - FP_FLOOR_CORNER(13371, 8304, 77, 357, new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000)), - FLAME_PIT(13337, 8304, 77, 357, new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000)), - ROCNAR_FLOOR_MID(13371, 8305, 83, 387, new Item(Items.COINS_995, 150000)), - ROCNAR_FLOOR_SIDE(13371, 8305, 83, 387, new Item(Items.COINS_995, 150000)), - ROCNAR_FLOOR_CORNER(13371, 8305, 83, 387, new Item(Items.COINS_995, 150000)), - ROCNAR(13373, 8305, 83, 387, new Item(Items.COINS_995, 150000)), - ROCNAR_FL(13338, 8305, 83, 387, new Item(Items.COINS_995, 150000)), - OAK_CAGE(13313, 8297, 65, 640, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2)), - OAK_CAGE_DOOR(13314, 8297, 65, 640, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2)), - OAK_STEEL_CAGE(13316, 8298, 70, 800, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10)), - OAK_STEEL_CAGE_DOOR(13317, 8298, 70, 800, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10)), - STEEL_CAGE_OU(13319, 8299, 75, 400, new Item(Items.STEEL_BAR_2353, 20)), - STEEL_CAGE_DOOR(13320, 8299, 75, 400, new Item(Items.STEEL_BAR_2353, 20)), - SPIKED_CAGE(13322, 8300, 80, 500, new Item(Items.STEEL_BAR_2353, 25)), - SPIKED_CAGE_DOOR(13323, 8300, 80, 500, new Item(Items.STEEL_BAR_2353, 25)), - BONE_CAGE(13325, 8301, 85, 603, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.BONES_526, 10)), - BONE_CAGE_DOOR(13326, 8301, 85, 603, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.BONES_526, 10)), - SKELETON_GUARD(13366, 8131, 70, 223, new Item(Items.COINS_995, 50000)), - GUARD_DOG(13367, 8132, 74, 273, new Item(Items.COINS_995, 75000)), - HOBGOBLIN(13368, 8133, 78, 316, new Item(Items.COINS_995, 100000)), - BABY_RED_DRAGON(13372, 8134, 82, 387, new Item(Items.COINS_995, 150000)), - HUGE_SPIDER(13370, 8135, 86, 447, new Item(Items.COINS_995, 200000)), - TROLL(13369, 8136, 90, 1000, new Item(Items.COINS_995, 1000000)), - HELLHOUND(2715, 8137, 94, 2236, new Item(Items.COINS_995, 5000000)), - OAK_LADDER(13328, 8306, 68, 300, new Item(Items.OAK_PLANK_8778, 5)), - TEAK_LADDER(13329, 8307, 78, 450, new Item(Items.TEAK_PLANK_8780, 5)), - MAHOGANY_LADDER(13330, 8308, 88, 700, new Item(Items.MAHOGANY_PLANK_8782, 5)), - DECORATIVE_BLOOD(13312, 8125, 72, 4, new Item(Items.RED_DYE_1763, 4)), - DECORATIVE_PIPE(13311, 8126, 83, 120, new Item(Items.STEEL_BAR_2353, 6)), - HANGING_SKELETON(13310, 8127, 94, 3, new Item(Items.SKULL_964, 2), new Item(Items.BONES_526, 6)), - CANDLE(13342, 8128, 72, 243, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_CANDLE_33, 4)), - TORCH(13341, 8129, 84, 244, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_TORCH_594, 4)), - SKULL_TORCH(13343, 8130, 94, 246, new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_TORCH_594, 4), new Item(Items.SKULL_964, 4)), - + SPIKES_MID (13334, 8302, 65, 623, new Item[] { new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000) }), + SPIKES_SIDE (13335, 8302, 65, 623, new Item[] { new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000) }), + SPIKES_CORNER (13336, 8302, 65, 623, new Item[] { new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000) }), + SPIKES_FL (13338, 8302, 65, 623, new Item[] { new Item(Items.STEEL_BAR_2353, 20), new Item(Items.COINS_995, 50000) }), + TENTACLE_MID (13331, 8303, 71, 326, new Item[] { new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000) }), + TENTACLE_SIDE (13332, 8303, 71, 326, new Item[] { new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000) }), + TENTACLE_CORNER (13333, 8303, 71, 326, new Item[] { new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000) }), + TENTACLE_FL (13338, 8303, 71, 326, new Item[] { new Item(Items.BUCKET_OF_WATER_1929, 20), new Item(Items.COINS_995, 100000) }), + FP_FLOOR_MID (13371, 8304, 77, 357, new Item[] { new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000) }), + FP_FLOOR_SIDE (13371, 8304, 77, 357, new Item[] { new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000) }), + FP_FLOOR_CORNER (13371, 8304, 77, 357, new Item[] { new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000) }), + FLAME_PIT (13337, 8304, 77, 357, new Item[] { new Item(Items.TINDERBOX_590, 20), new Item(Items.COINS_995, 125000) }), + ROCNAR_FLOOR_MID (13371, 8305, 83, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + ROCNAR_FLOOR_SIDE (13371, 8305, 83, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + ROCNAR_FLOOR_CORNER(13371, 8305, 83, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + ROCNAR (13373, 8305, 83, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + ROCNAR_FL (13338, 8305, 83, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + OAK_CAGE (13313, 8297, 65, 640, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2) }), + OAK_CAGE_DOOR (13314, 8297, 65, 640, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 2) }), + OAK_STEEL_CAGE (13316, 8298, 70, 800, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10) }), + OAK_STEEL_CAGE_DOOR(13317, 8298, 70, 800, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10) }), + STEEL_CAGE_OU (13319, 8299, 75, 400, new Item[] { new Item(Items.STEEL_BAR_2353, 20) }), + STEEL_CAGE_DOOR (13320, 8299, 75, 400, new Item[] { new Item(Items.STEEL_BAR_2353, 20) }), + SPIKED_CAGE (13322, 8300, 80, 500, new Item[] { new Item(Items.STEEL_BAR_2353, 25) }), + SPIKED_CAGE_DOOR (13323, 8300, 80, 500, new Item[] { new Item(Items.STEEL_BAR_2353, 25) }), + BONE_CAGE (13325, 8301, 85, 603, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.BONES_526, 10) }), + BONE_CAGE_DOOR (13326, 8301, 85, 603, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.BONES_526, 10) }), + SKELETON_GUARD (13366, 8131, 70, 223, new Item[] { new Item(Items.COINS_995, 50000) }), + GUARD_DOG (13367, 8132, 74, 273, new Item[] { new Item(Items.COINS_995, 75000) }), + HOBGOBLIN (13368, 8133, 78, 316, new Item[] { new Item(Items.COINS_995, 100000) }), + BABY_RED_DRAGON (13372, 8134, 82, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + HUGE_SPIDER (13370, 8135, 86, 447, new Item[] { new Item(Items.COINS_995, 200000) }), + TROLL (13369, 8136, 90, 1000, new Item[] { new Item(Items.COINS_995, 1000000) }), + HELLHOUND (2715, 8137, 94, 2236, new Item[] { new Item(Items.COINS_995, 5000000) }), + OAK_LADDER (13328, 8306, 68, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), + TEAK_LADDER (13329, 8307, 78, 450, new Item[] { new Item(Items.TEAK_PLANK_8780, 5) }), + MAHOGANY_LADDER (13330, 8308, 88, 700, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5) }), + DECORATIVE_BLOOD (13312, 8125, 72, 4, new Item[] { new Item(Items.RED_DYE_1763, 4) }), + DECORATIVE_PIPE (13311, 8126, 83, 120, new Item[] { new Item(Items.STEEL_BAR_2353, 6) }), + HANGING_SKELETON (13310, 8127, 94, 3, new Item[] { new Item(Items.SKULL_964, 2), new Item(Items.BONES_526, 6) }), + CANDLE (13342, 8128, 72, 243, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_CANDLE_33, 4) }), + TORCH (13341, 8129, 84, 244, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_TORCH_594, 4) }), + SKULL_TORCH (13343, 8130, 94, 246, new Item[] { new Item(Items.OAK_PLANK_8778, 4), new Item(Items.LIT_TORCH_594, 4), new Item(Items.SKULL_964, 4) }), + /** * Dungeon corridor, junction, stairs & pit */ - OAK_DOOR_LEFT(13344, 8122, 74, 600, new Item(Items.OAK_PLANK_8778, 10)), - OAK_DOOR_RIGHT(13345, 8122, 74, 600, new Item(Items.OAK_PLANK_8778, 10)), - STEEL_DOOR_LEFT(13346, 8123, 84, 800, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10)), - STEEL_DOOR_RIGHT(13347, 8123, 84, 800, new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10)), - MARBLE_DOOR_LEFT(13348, 8124, 94, 2000, new Item(Items.MARBLE_BLOCK_8786, 4)), - MARBLE_DOOR_RIGHT(13349, 8124, 94, 2000, new Item(Items.MARBLE_BLOCK_8786, 4)), - SPIKE_TRAP(13356, 8143, 72, 223, new Item(Items.COINS_995, 50000)), - MAN_TRAP(13357, 8144, 76, 273, new Item(Items.COINS_995, 75000)), - TANGLE_TRAP(13358, 8145, 80, 316, new Item(Items.COINS_995, 100000)), - MARBLE_TRAP(13359, 8146, 84, 387, new Item(Items.COINS_995, 150000)), - TELEPORT_TRAP(13360, 8147, 88, 447, new Item(Items.COINS_995, 200000)), - - /* objID, int, lvl, exp, materials */ - PIT_DOG(39260, 18791, 70, 200, new Item(Items.COINS_995, 40000)), - PIT_OGRE(39261, 18792, 73, 234, new Item(Items.COINS_995, 55000)), - PIT_ROCK_PROTECTOR(39262, 18793, 79, 300, new Item(Items.COINS_995, 90000)), - PIT_SCABARITE(39263, 18794, 84, 387, new Item(Items.COINS_995, 150000)), - PIT_BLACK_DEMON(39264, 18795, 89, 547, new Item(Items.COINS_995, 300000)), - PIT_IRON_DRAGON(39265, 18796, 97, 2738, new Item(Items.COINS_995, 7500000)), + OAK_DOOR_LEFT (13344, 8122, 74, 600, new Item[] { new Item(Items.OAK_PLANK_8778, 10) }), + OAK_DOOR_RIGHT (13345, 8122, 74, 600, new Item[] { new Item(Items.OAK_PLANK_8778, 10) }), + STEEL_DOOR_LEFT (13346, 8123, 84, 800, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10) }), + STEEL_DOOR_RIGHT (13347, 8123, 84, 800, new Item[] { new Item(Items.OAK_PLANK_8778, 10), new Item(Items.STEEL_BAR_2353, 10) }), + MARBLE_DOOR_LEFT (13348, 8124, 94, 2000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 4) }), + MARBLE_DOOR_RIGHT (13349, 8124, 94, 2000, new Item[] { new Item(Items.MARBLE_BLOCK_8786, 4) }), + SPIKE_TRAP (13356, 8143, 72, 223, new Item[] { new Item(Items.COINS_995, 50000) }), + MAN_TRAP (13357, 8144, 76, 273, new Item[] { new Item(Items.COINS_995, 75000) }), + TANGLE_TRAP (13358, 8145, 80, 316, new Item[] { new Item(Items.COINS_995, 100000) }), + MARBLE_TRAP (13359, 8146, 84, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + TELEPORT_TRAP (13360, 8147, 88, 447, new Item[] { new Item(Items.COINS_995, 200000) }), + PIT_DOG (39260, 18791, 70, 200, new Item[] { new Item(Items.COINS_995, 40000) }), + PIT_OGRE (39261, 18792, 73, 234, new Item[] { new Item(Items.COINS_995, 55000) }), + PIT_ROCK_PROTECTOR(39262, 18793, 79, 300, new Item[] { new Item(Items.COINS_995, 90000) }), + PIT_SCABARITE (39263, 18794, 84, 387, new Item[] { new Item(Items.COINS_995, 150000) }), + PIT_BLACK_DEMON (39264, 18795, 89, 547, new Item[] { new Item(Items.COINS_995, 300000) }), + PIT_IRON_DRAGON (39265, 18796, 97, 2738, new Item[] { new Item(Items.COINS_995, 7500000) }), /** * Treasure room */ - DEMON(13378, 8138, 75, 707, new Item(Items.COINS_995, 500000)), - KALPHITE_SOLDIER(13374, 8139, 80, 866, new Item(Items.COINS_995, 750000)), - TOK_XIL(13377, 8140, 85, 2236, new Item(Items.COINS_995, 5000000)), - DAGANNOTH(13376, 8141, 90, 2738, new Item(Items.COINS_995, 7500000)), - STEEL_DRAGON(13375, 8142, 95, 3162, new Item(Items.COINS_995, 1000000)), - WOODEN_CRATE(13283, 8148, 75, 143, new Item(Items.PLANK_960, 5)), - OAK_T_CHEST(13285, 8149, 79, 340, new Item(Items.OAK_PLANK_8778, 5), new Item(Items.STEEL_BAR_2353, 2)), - TEAK_T_CHEST(13287, 8150, 83, 530, new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.STEEL_BAR_2353, 4)), - MGANY_T_CHEST(13289, 8151, 87, 1000, new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.GOLD_LEAF_8784, 1)), - MAGIC_CHEST(13291, 8152, 91, 1000, new Item(Items.MAGIC_STONE_8788, 1)), - + DEMON (13378, 8138, 75, 707, new Item[] { new Item(Items.COINS_995, 500000) }), + KALPHITE_SOLDIER (13374, 8139, 80, 866, new Item[] { new Item(Items.COINS_995, 750000) }), + TOK_XIL (13377, 8140, 85, 2236, new Item[] { new Item(Items.COINS_995, 5000000) }), + DAGANNOTH (13376, 8141, 90, 2738, new Item[] { new Item(Items.COINS_995, 7500000) }), + STEEL_DRAGON (13375, 8142, 95, 3162, new Item[] { new Item(Items.COINS_995, 1000000) }), + WOODEN_CRATE (13283, 8148, 75, 143, new Item[] { new Item(Items.PLANK_960, 5) }), + OAK_T_CHEST (13285, 8149, 79, 340, new Item[] { new Item(Items.OAK_PLANK_8778, 5), new Item(Items.STEEL_BAR_2353, 2) }), + TEAK_T_CHEST (13287, 8150, 83, 530, new Item[] { new Item(Items.TEAK_PLANK_8780, 5), new Item(Items.STEEL_BAR_2353, 4) }), + MGANY_T_CHEST (13289, 8151, 87, 1000, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 5), new Item(Items.GOLD_LEAF_8784) }), + MAGIC_CHEST (13291, 8152, 91, 1000, new Item[] { new Item(Items.MAGIC_STONE_8788) }), + /** * Style related decoration. */ - BASIC_WOOD_WINDOW(13099, -1, 1, 0.0), - BASIC_STONE_WINDOW(13091, -1, 1, 0.0), - WHITEWASHED_STONE_WINDOW(13005, -1, 1, 0.0), - FREMENNIK_WINDOW(13112, -1, 1, 0.0), - TROPICAL_WOOD_WINDOW(10816, -1, 1, 0.0), - FANCY_STONE_WINDOW(13117, -1, 1, 0.0), - + BASIC_WOOD_WINDOW (13099, -1, 1, 0), + BASIC_STONE_WINDOW (13091, -1, 1, 0), + WHITEWASHED_STONE_WINDOW (13005, -1, 1, 0), + FREMENNIK_WINDOW (13112, -1, 1, 0), + TROPICAL_WOOD_WINDOW (10816, -1, 1, 0), + FANCY_STONE_WINDOW (13117, -1, 1, 0), ; + /** * The object id. */ private final int objectId; - + /** * The item id for the interface. */ @@ -1083,17 +700,22 @@ public enum Decoration { * The level requirement. */ private final int level; - + /** * The experience gained for building this decoration. */ - private final double experience; - + private final int experience; + /** * The item required. */ private final Item[] items; - + + /** + * The items that will be refunded. + */ + private final Item[] refundItems; + /** * The tools required. */ @@ -1103,33 +725,72 @@ public enum Decoration { * The object ids depending on styling. */ private final int[] objectIds; - + /** * If this node should be invisible to user build options */ private boolean invisibleNode; - + /** - * Constructs a new {@code Portal} {@code Object}. + * Constructs a new object, no items, no tools, no refund items. * @param objectId The object id. * @param interfaceItem The item id for the building interface. * @param level The level required. * @param experience The experience gained. - * @param items The items required. */ - private Decoration(int objectId, int interfaceItem, int level, double experience, Item... items) { - this(objectId, interfaceItem, level, experience, new int[] { 2347, 8794 }, items); + Decoration(int objectId, int interfaceItem, int level, int experience) { + this(objectId, interfaceItem, level, experience, new int[] { Items.HAMMER_2347, Items.SAW_8794 }, new Item[] {}, new Item[] {}); } - + /** - * Constructs a new {@code Portal} {@code Object}. + * Constructs a new object, no tools, no refund items. * @param objectId The object id. * @param interfaceItem The item id for the building interface. * @param level The level required. * @param experience The experience gained. * @param items The items required. */ - private Decoration(int objectId, int interfaceItem, int level, double experience, int[] tools, Item... items) { + Decoration(int objectId, int interfaceItem, int level, int experience, Item[] items) { + this(objectId, interfaceItem, level, experience, new int[] { Items.HAMMER_2347, Items.SAW_8794 }, items, new Item[] {}); + } + + /** + * Constructs a new object, no refund items. + * @param objectId The object id. + * @param interfaceItem The item id for the building interface. + * @param level The level required. + * @param experience The experience gained. + * @param tools The tools needed. + * @param items The items required. + */ + Decoration(int objectId, int interfaceItem, int level, int experience, int[] tools, Item[] items) { + this(objectId, interfaceItem, level, experience, tools, items, new Item[] {}); + } + + /** + * Constructs a new object, no tools. + * @param objectId The object id. + * @param interfaceItem The item id for the building interface. + * @param level The level required. + * @param experience The experience gained. + * @param items The items required. + * @param refundItems The items to be refunded when the item is removed. + */ + Decoration(int objectId, int interfaceItem, int level, int experience, Item[] items, Item[] refundItems) { + this(objectId, interfaceItem, level, experience, new int[] { Items.HAMMER_2347, Items.SAW_8794 }, items, refundItems); + } + + /** + * Constructs a new object. + * @param objectId The object id. + * @param interfaceItem The item id for the building interface. + * @param level The level required. + * @param experience The experience gained. + * @param tools The tools needed. + * @param items The items required. + * @param refundItems The items to be refunded when the item is removed. + */ + Decoration(int objectId, int interfaceItem, int level, int experience, int[] tools, Item[] items, Item[] refundItems) { this.objectId = objectId; this.objectIds = null; this.interfaceItem = interfaceItem; @@ -1137,39 +798,54 @@ public enum Decoration { this.experience = experience; this.tools = tools; this.items = items; + this.refundItems = refundItems; } - + /** * Decoration * @param objectId * @param invisibleNode */ - private Decoration(int objectId, boolean invisibleNode) { + Decoration(int objectId, boolean invisibleNode) { this(objectId, -1, -1, -1); this.invisibleNode = true; } - + /** - * Constructs a new {@code Portal} {@code Object}. + * Constructs a new object, no tools, no refund items. * @param objectIds The object id. * @param interfaceItem The item id for the building interface. * @param level The level required. * @param experience The experience gained. * @param items The items required. */ - private Decoration(int[] objectIds, int interfaceItem, int level, double experience, Item... items) { - this(objectIds, interfaceItem, level, experience, new int[] { 2347, 8794 }, items); + Decoration(int[] objectIds, int interfaceItem, int level, int experience, Item[] items) { + this(objectIds, interfaceItem, level, experience, new int[] { Items.HAMMER_2347, Items.SAW_8794 }, items, new Item[] {}); } - /** - * Constructs a new {@code Portal} {@code Object}. + * Constructs a new object no refund items. * @param objectIds The object id. * @param interfaceItem The item id for the building interface. * @param level The level required. * @param experience The experience gained. + * @param tools The tools needed. * @param items The items required. */ - private Decoration(int[] objectIds, int interfaceItem, int level, double experience, int[] tools, Item... items) { + Decoration(int[] objectIds, int interfaceItem, int level, int experience, int[] tools, Item[] items) { + this(objectIds, interfaceItem, level, experience, tools, items, new Item[] {}); + } + + /** + * Constructs a new object. + * @param objectIds The object id. + * @param interfaceItem The item id for the building interface. + * @param level The level required. + * @param experience The experience gained. + * @param tools The tools needed. + * @param items The items required. + * @param refundItems The items to be refunded when the item is removed. + */ + Decoration(int[] objectIds, int interfaceItem, int level, int experience, int[] tools, Item[] items, Item[] refundItems) { this.objectId = objectIds[0]; this.objectIds = objectIds; this.interfaceItem = interfaceItem; @@ -1177,6 +853,7 @@ public enum Decoration { this.experience = experience; this.tools = tools; this.items = items; + this.refundItems = refundItems; } /** @@ -1203,7 +880,7 @@ public enum Decoration { } return null; } - + /** * Gets a decoration for the given object id * @param objectId - the object id of the built object @@ -1217,7 +894,7 @@ public enum Decoration { } return null; } - + public static Decoration forName(String name) { for (Decoration d : Decoration.values()) { if (d.name().equals(name)) { @@ -1239,7 +916,7 @@ public enum Decoration { } return 0; } - + /** * Gets the objectId. * @param style The current housing style. @@ -1251,7 +928,7 @@ public enum Decoration { } return objectId; } - + /** * Gets the objectId. * @return The objectId. @@ -1272,7 +949,7 @@ public enum Decoration { * Gets the experience. * @return The experience. */ - public double getExperience() { + public int getExperience() { return experience; } @@ -1284,6 +961,14 @@ public enum Decoration { return items; } + /** + * Gets the refund items. + * @return The refund items. + */ + public Item[] getRefundItems() { + return refundItems; + } + /** * Gets the tools. * @return The tools. @@ -1308,10 +993,11 @@ public enum Decoration { return objectIds; } + /** + * If this node should be invisible to user build options + * @return true if so. + */ public boolean isInvisibleNode() { return invisibleNode; } - - - } diff --git a/Server/src/main/content/global/skill/construction/decoration/questhall/MountedGlory.kt b/Server/src/main/content/global/skill/construction/decoration/questhall/MountedGlory.kt index 4f7ddb15b..47051e46f 100644 --- a/Server/src/main/content/global/skill/construction/decoration/questhall/MountedGlory.kt +++ b/Server/src/main/content/global/skill/construction/decoration/questhall/MountedGlory.kt @@ -4,8 +4,10 @@ import core.api.playGlobalAudio import core.api.teleport import core.game.interaction.IntType import core.game.interaction.InteractionListener +import core.game.node.Node import core.game.node.entity.player.Player import core.game.node.item.Item +import core.game.node.scenery.Scenery import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.update.flag.context.Animation @@ -27,27 +29,31 @@ class MountedGlory : InteractionListener { ) override fun defineListeners() { - on(MOUNTED_GLORY, IntType.SCENERY, "Edgeville") { player, _ -> - mountedGloryTeleport(player,0) + on(MOUNTED_GLORY, IntType.SCENERY, "Edgeville") { player, `object` -> + mountedGloryAction(player, `object`, 0) return@on true } - on(MOUNTED_GLORY, IntType.SCENERY, "Karamja") { player, _ -> - mountedGloryTeleport(player,1) + on(MOUNTED_GLORY, IntType.SCENERY, "Karamja") { player, `object` -> + mountedGloryAction(player, `object`, 1) return@on true } - on(MOUNTED_GLORY, IntType.SCENERY, "Draynor Village") { player, _ -> - mountedGloryTeleport(player,2) + on(MOUNTED_GLORY, IntType.SCENERY, "Draynor Village") { player, `object` -> + mountedGloryAction(player, `object`, 2) return@on true } - on(MOUNTED_GLORY, IntType.SCENERY, "Al Kharid") { player, _ -> - mountedGloryTeleport(player,3) + on(MOUNTED_GLORY, IntType.SCENERY, "Al Kharid") { player, `object` -> + mountedGloryAction(player, `object`, 3) return@on true } } - private fun mountedGloryTeleport(player : Player, int : Int) { + private fun mountedGloryAction(player : Player, `object` : Node, int : Int) { + if (player.houseManager.isBuildingMode) { + player.dialogueInterpreter.open("con:removedec", `object` as Scenery) + return + } if (!player.zoneMonitor.teleport(1, Item(Items.AMULET_OF_GLORY_1704))) { return } From 53dc16977452012dd1ff4806d8889a68e3f43637 Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 11:36:09 +0000 Subject: [PATCH 118/306] Corporeal beast authenticity improvements Dark core will no longer jump to players in safe area Adjusted maximum attack hits Protect from magic now blocks the big dart attack by 40% Now resummons the dark core when it dies Made the dark core respawn mechanics more authentic Dark core now drops ashes --- Server/data/configs/drop_tables.json | 14 ++ .../handlers/CorporealBeastNPC.java | 138 ++++++++++-------- .../handlers/DarkEnergyCoreNPC.java | 27 ++-- .../node/entity/combat/MultiSwingHandler.kt | 2 +- 4 files changed, 106 insertions(+), 75 deletions(-) diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 1a8525af4..8aff52d67 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -58878,5 +58878,19 @@ "maxAmount": "1" } ] + }, + { + "default": [ + { + "minAmount": "1", + "weight": "1.0", + "id": "592", + "maxAmount": "1" + } + ], + "charm": [], + "ids": "8127", + "description": "Dark energy core", + "main": [] } ] \ No newline at end of file diff --git a/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java b/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java index ea1849876..67ad9c876 100644 --- a/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java +++ b/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java @@ -2,15 +2,11 @@ package content.region.wilderness.handlers; import content.data.BossKillCounter; import core.game.node.entity.Entity; -import core.game.node.entity.combat.BattleState; -import core.game.node.entity.combat.CombatStyle; -import core.game.node.entity.combat.CombatSwingHandler; +import core.game.node.entity.combat.*; import core.game.node.entity.combat.ImpactHandler.HitsplatType; -import core.game.node.entity.combat.MultiSwingHandler; import core.game.node.entity.combat.equipment.SwitchAttack; import core.game.node.entity.combat.equipment.Weapon; import core.game.node.entity.impl.Projectile; -import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.npc.NPC; import core.game.node.entity.npc.NPCBehavior; import core.game.node.entity.player.Player; @@ -22,7 +18,6 @@ import core.game.world.map.RegionManager; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; -import core.plugin.Plugin; import core.tools.RandomFunction; import org.rs09.consts.NPCs; @@ -32,7 +27,6 @@ import java.util.List; /** * Handles the Corporeal beast NPC. * @author Emperor - * */ @Initializable public final class CorporealBeastNPC extends NPCBehavior { @@ -41,19 +35,24 @@ public final class CorporealBeastNPC extends NPCBehavior { * The combat handler. */ private final MultiSwingHandler combatHandler = new CombatHandler(); - + /** * The dark energy core NPC. */ public NPC darkEnergyCore; - + + /** + * Whether to force a dark core spawn roll on our next swing (only done if we just got hit >= 32 damage). + */ + public boolean forceCoreRoll = false; + /** * Constructs a new {@code CorporealBeastNPC} {@code Object}. */ public CorporealBeastNPC() { - super(new int[]{NPCs.CORPOREAL_BEAST_8133}); + super(new int[] { NPCs.CORPOREAL_BEAST_8133 }); } - + @Override public void onCreation(NPC self) { self.configureBossData(); @@ -64,27 +63,31 @@ public final class CorporealBeastNPC extends NPCBehavior { return combatHandler; } - @Override - public void beforeDamageReceived(NPC self, Entity attacker, BattleState state) { - if(state.getStyle() == CombatStyle.MELEE || state.getStyle() == CombatStyle.RANGE) { - Weapon w = state.getWeapon(); - String name = w != null ? w.getName() : ""; - if(w == null || name.toLowerCase().indexOf("spear") == -1) { - if(state.getEstimatedHit() > 0) { - state.setEstimatedHit(state.getEstimatedHit()/2); - } - if(state.getSecondaryHit() > 0) { - state.setSecondaryHit(state.getSecondaryHit()/2); - } - } - } - if(state.getEstimatedHit() > 100) { - state.setEstimatedHit(100); - } - if(state.getSecondaryHit() > 100) { - state.setSecondaryHit(100); - } - } + @Override + public void beforeDamageReceived(NPC self, Entity attacker, BattleState state) { + if (state.getStyle() == CombatStyle.MELEE || state.getStyle() == CombatStyle.RANGE) { + Weapon w = state.getWeapon(); + String name = w != null ? w.getName() : ""; + if (w == null || name.toLowerCase().indexOf("spear") == -1) { + if (state.getEstimatedHit() > 0) { + state.setEstimatedHit(state.getEstimatedHit() / 2); + } + if (state.getSecondaryHit() > 0) { + state.setSecondaryHit(state.getSecondaryHit() / 2); + } + } + } + if (state.getEstimatedHit() >= 32) { + CorporealBeastNPC corp = (CorporealBeastNPC) self.behavior; + corp.forceCoreRoll = true; + } + if (state.getEstimatedHit() > 100) { + state.setEstimatedHit(100); + } + if (state.getSecondaryHit() > 100) { + state.setSecondaryHit(100); + } + } @Override public void onDeathFinished(NPC self, Entity killer) { @@ -94,41 +97,46 @@ public final class CorporealBeastNPC extends NPCBehavior { darkEnergyCore = null; } } - + /** * Handles the Corporeal beast's combat. * @author Emperor - * */ static class CombatHandler extends MultiSwingHandler { - /** * Constructs a new {@code CombatHandler} {@code Object}. */ public CombatHandler() { super( - //Melee (crush) - new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(10057)).setMaximumHit(52), - //Melee (slash) - new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(10058)).setMaximumHit(51), - //Magic (drain skill) - new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1823, 60, 36, 41, 46)).setMaximumHit(55), - //Magic (location based) - new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1824, 60, 36, 41, 46)).setMaximumHit(42), - //Magic (hit through prayer) - new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1825, 60, 36, 41, 46)).setMaximumHit(66) - ); + //Melee (crush) + new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(10057)).setMaximumHit(51), + //Melee (slash) + new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(10058)).setMaximumHit(51), + //Magic (drain skill, blocked by prayer) + new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1823, 60, 36, 41, 46)).setMaximumHit(55), + //Magic (location-based, hits through prayer) + new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1824, 60, 36, 41, 46)).setMaximumHit(42), + //Magic (hits through prayer) + new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(10410), null, null, Projectile.create(null, null, 1825, 60, 36, 41, 46)).setMaximumHit(65) + ); } @Override public int swing(Entity entity, Entity victim, BattleState state) { - spawnDarkCore(entity, (CorporealBeastNPC)((NPC) entity).behavior, victim); + // If we're below the right HP threshold, roll a chance to spawn the dark core + CorporealBeastNPC corp = (CorporealBeastNPC) ((NPC) entity).behavior; + double thresh = entity.getSkills().getMaximumLifepoints() * (0.3 + (entity.getViewport().getCurrentPlane().getPlayers().size() * 0.05)); + if (corp.forceCoreRoll || entity.getSkills().getLifepoints() < thresh) { + rollDarkCore(entity, corp, victim); + corp.forceCoreRoll = false; + } + // If we can stomp, do that for our turn if (doStompAttack(entity)) { entity.getProperties().getCombatPulse().setNextAttack(entity.getProperties().getAttackSpeed()); return -1; } - //Location based attack. + // Location-based attack. if (super.getNext().getProjectile() != null && super.getNext().getProjectile().getProjectileId() == 1824) { setCurrent(getNext()); CombatStyle style = getCurrent().getStyle(); @@ -142,18 +150,17 @@ public final class CorporealBeastNPC extends NPCBehavior { } return super.swing(entity, victim, state); } - + /** - * Spawns a dark core. + * Rolls a 1/8 chance to spawn a dark core. * @param npc The corporeal beast NPC. * @param victim The victim. */ - private void spawnDarkCore(Entity corp, final CorporealBeastNPC npc, Entity victim) { - if (npc.darkEnergyCore != null && npc.darkEnergyCore.isActive()) { + private void rollDarkCore(Entity corp, final CorporealBeastNPC npc, Entity victim) { + if (npc.darkEnergyCore != null && npc.darkEnergyCore.isActive() && !DeathTask.isDead(npc.darkEnergyCore)) { return; } - double max = corp.getSkills().getMaximumLifepoints() * (0.3 + (corp.getViewport().getCurrentPlane().getPlayers().size() * 0.05)); - if (corp.getSkills().getLifepoints() > max) { + if (!RandomFunction.roll(8)) { return; } Location l = RegionManager.getTeleportLocation(victim.getLocation(), 3); @@ -163,8 +170,8 @@ public final class CorporealBeastNPC extends NPCBehavior { GameWorld.getPulser().submit(new Pulse(2, corp) { @Override public boolean pulse() { - if (npc.darkEnergyCore == null) - return true; + if (npc.darkEnergyCore == null) + return true; npc.darkEnergyCore.init(); return true; } @@ -184,6 +191,7 @@ public final class CorporealBeastNPC extends NPCBehavior { boolean secondStage = false; List players = RegionManager.getLocalPlayers(entity); Location[] locations = null; + @Override public boolean pulse() { if (!secondStage) { @@ -215,11 +223,14 @@ public final class CorporealBeastNPC extends NPCBehavior { locations = null; return true; } + private void hit(Player p) { - int max = p.hasProtectionPrayer(CombatStyle.MAGIC) ? 13 : 42; int hit = 0; if (isAccurateImpact(entity, p)) { - hit = RandomFunction.random(max); + hit = RandomFunction.random(42); + if (p.hasProtectionPrayer(CombatStyle.MAGIC)) { + hit = (int) (hit * 0.6); + } } p.getImpactHandler().handleImpact(entity, hit, CombatStyle.MAGIC); } @@ -252,7 +263,7 @@ public final class CorporealBeastNPC extends NPCBehavior { } return false; } - + @Override public void adjustBattleState(Entity entity, Entity victim, BattleState state) { super.adjustBattleState(entity, victim, state); @@ -262,10 +273,9 @@ public final class CorporealBeastNPC extends NPCBehavior { int skill = random == 0 ? Skills.PRAYER : random == 1 ? Skills.MAGIC : Skills.SUMMONING; int drain = 1 + RandomFunction.random(6); if ((skill == Skills.PRAYER ? victim.getSkills().getPrayerPoints() : victim.getSkills().getLevel(skill)) < 1) { - victim.getImpactHandler().manualHit(entity, drain, HitsplatType.NORMAL,2); + victim.getImpactHandler().manualHit(entity, drain, HitsplatType.NORMAL, 2); ((Player) victim).getPacketDispatch().sendMessage("Your Hitpoints have been slightly drained!"); - } - else { + } else { if (skill == Skills.PRAYER) { victim.getSkills().decrementPrayerPoints(drain); } else { @@ -278,11 +288,13 @@ public final class CorporealBeastNPC extends NPCBehavior { } } } - + @Override protected int getFormattedHit(Entity entity, Entity victim, BattleState state, int hit) { if (getCurrent().getProjectile() == null || getCurrent().getProjectile().getProjectileId() != 1825) { hit = (int) entity.getFormattedHit(state, hit); + } else if (victim.hasProtectionPrayer(CombatStyle.MAGIC)) { + hit = (int) (hit * 0.6); } return formatHit(victim, hit); } diff --git a/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java b/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java index bcc8930cd..0695955ba 100644 --- a/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java +++ b/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java @@ -9,6 +9,8 @@ import core.game.node.entity.player.Player; import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; +import core.game.world.map.path.Path; +import core.game.world.map.path.Pathfinder; import core.plugin.Initializable; import core.tools.RandomFunction; @@ -16,8 +18,7 @@ import static core.api.ContentAPIKt.*; /** * Handles the Dark Energy Core NPC. - * @author Emperor - * + * @author Emperor, Player Name */ @Initializable public final class DarkEnergyCoreNPC extends AbstractNPC { @@ -31,21 +32,22 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { * The amount of ticks. */ private int ticks = 0; - + /** * The amount of failed attacks. */ private int fails = 0; - + /** * Constructs a new {@code DarkEnergyCoreNPC} {@code Object}. */ public DarkEnergyCoreNPC() { this(8127, null); } - + /** * Constructs a new {@code DarkEnergyCoreNPC} {@code Object}. + * * @param id The NPC id. * @param location The location. */ @@ -59,14 +61,15 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { if (objects.length > 0) { core.master = (NPC) objects[0]; } + core.setRespawn(false); return core; } - + @Override public boolean canStartCombat(Entity victim) { return false; //No combat needed. } - + @Override public void handleTickActions() { ticks++; @@ -91,8 +94,11 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { if (jump) { Entity victim = master.getProperties().getCombatPulse().getVictim(); if (++fails >= 3 && victim != null && victim.getViewport().getCurrentPlane() == getViewport().getCurrentPlane()) { - jump(victim.getLocation()); - fails = 0; + Path path = Pathfinder.find(getLocation(), victim.getLocation(), 1); + if (path.isSuccessful() || !path.isMoveNear()) { + jump(victim.getLocation()); + fails = 0; + } } } else { fails = 0; @@ -119,7 +125,6 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { @Override public int[] getIds() { - return new int[] { 8127 }; + return new int[]{8127}; } - } diff --git a/Server/src/main/core/game/node/entity/combat/MultiSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MultiSwingHandler.kt index 41ac8dca3..d283f3aff 100644 --- a/Server/src/main/core/game/node/entity/combat/MultiSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MultiSwingHandler.kt @@ -8,7 +8,7 @@ import core.tools.RandomFunction /** * Handles combat swings with switching combat styles. * @author Emperor - * @author Ceirky, Kotlin conversion + * @author Ceikry, Kotlin conversion */ open class MultiSwingHandler(meleeDistance: Boolean, vararg attacks: SwitchAttack) : CombatSwingHandler(CombatStyle.RANGE) { /** From 1da53c448d824f0b66d180a69e7262e9e16bcbf8 Mon Sep 17 00:00:00 2001 From: GregF Date: Thu, 14 Nov 2024 11:51:34 +0000 Subject: [PATCH 119/306] Rewrote dream spell Fixed healing rate of dream Added sound to dream spell --- .../global/skill/magic/lunar/DreamSpell.java | 104 ------------------ .../skill/magic/lunar/LunarListeners.kt | 43 +++++++- .../game/node/entity/combat/CombatPulse.kt | 1 + 3 files changed, 38 insertions(+), 110 deletions(-) delete mode 100644 Server/src/main/content/global/skill/magic/lunar/DreamSpell.java diff --git a/Server/src/main/content/global/skill/magic/lunar/DreamSpell.java b/Server/src/main/content/global/skill/magic/lunar/DreamSpell.java deleted file mode 100644 index e35542f0a..000000000 --- a/Server/src/main/content/global/skill/magic/lunar/DreamSpell.java +++ /dev/null @@ -1,104 +0,0 @@ -package content.global.skill.magic.lunar; - -import core.game.node.entity.combat.spell.MagicSpell; -import core.game.node.entity.combat.spell.Runes; -import core.game.node.entity.skill.Skills; -import core.game.node.Node; -import core.game.node.entity.Entity; -import core.game.node.entity.combat.spell.SpellType; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.SpellBookManager.SpellBook; -import core.game.node.item.Item; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; -import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the dream magic spell. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class DreamSpell extends MagicSpell { - - /** - * Represents the starting animation. - */ - private static final Animation START = Animation.create(6295); - - /** - * Represents the dreaming animation. - */ - private static final Animation DREAMING = Animation.create(6296); - - /** - * Represents the end animation. - */ - private static final Animation END = Animation.create(6297); - - /** - * Represents the graphics of this spell. - */ - private static final Graphics GRAPHIC = new Graphics(1056); - - /** - * Constructs a new {@code CureOtherSpell} {@code Object}. - */ - public DreamSpell() { - super(SpellBook.LUNAR, 79, 82, null, null, null, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.ASTRAL_RUNE.getId(), 2), new Item(Runes.BODY_RUNE.getId(), 5) }); - } - - @Override - public Plugin newInstance(SpellType arg) throws Throwable { - SpellBook.LUNAR.register(10, this); - return this; - } - - @Override - public boolean cast(Entity entity, Node target) { - final Player p = (Player) entity; - if (p.getSkills().getLifepoints() == p.getSkills().getStaticLevel(Skills.HITPOINTS)) { - p.getPacketDispatch().sendMessage("You have no need to cast this spell since your hitpoints are already full."); - return false; - } - if (!meetsRequirements(entity, true, true)) { - return false; - } - p.animate(START); - p.lock(); - GameWorld.getPulser().submit(new Pulse(4, p) { - @Override - public boolean pulse() { - p.animate(DREAMING); - p.graphics(GRAPHIC); - p.unlock(); - return true; - } - - }); - p.getPulseManager().run(new Pulse(18, p) { - @Override - public boolean pulse() { - p.graphics(GRAPHIC); - p.getSkills().heal(1); - if (p.getSkills().getLifepoints() == p.getSkills().getStaticLevel(Skills.HITPOINTS)) { - stop(); - return true; - } - return false; - } - - @Override - public void stop() { - super.stop(); - p.graphics(new Graphics(-1)); - p.animate(END); - } - }); - return true; - } - -} diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 40e27939a..1a89b9f85 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -9,6 +9,7 @@ import content.global.skill.magic.spellconsts.Lunar import core.api.* import core.game.component.CloseEvent import core.game.component.Component +import core.game.interaction.QueueStrength import core.game.node.Node import core.game.node.entity.combat.ImpactHandler import core.game.node.entity.npc.NPC @@ -169,9 +170,10 @@ class LunarListeners : SpellListener("lunar"), Commands { } // Level 79 - /** - * Dream - */ + onCast(Lunar.DREAM, NONE) { player, _ -> + requires(player, 79, arrayOf(Item(Items.ASTRAL_RUNE_9075, 2), Item(Items.BODY_RUNE_559, 5), Item(Items.COSMIC_RUNE_564, 1))) + dream(player) + } // Level 80 onCast(Lunar.STRING_JEWELLERY, NONE) { player, _ -> @@ -576,9 +578,38 @@ class LunarListeners : SpellListener("lunar"), Commands { } // Level 79 - /** - * Dream - */ + private fun dream(player: Player) { + if(player.skills.lifepoints >= getStatLevel(player, Skills.HITPOINTS)) { + sendMessage(player, "You have no need to cast this spell since your hitpoints are already full.") + return + } + + animate(player, Animations.LUNAR_SPELLBOOK_DREAM_START_6295) + delayEntity(player, 4) + queueScript(player, 4, QueueStrength.WEAK) { stage: Int -> + when(stage) { + 0 -> { + animate(player, Animations.LUNAR_SPELLBOOK_DREAM_MID_6296) + sendGraphics(Graphics.LUNAR_SPELLBOOK_DREAM_1056, player.location) + playAudio(player, Sounds.LUNAR_SLEEP_3619) + return@queueScript delayScript(player, 5) + } + else -> { + sendGraphics(Graphics.LUNAR_SPELLBOOK_DREAM_1056, player.location) + // This heals 2 HP every min. Naturally you heal 1 for a total of 3 + // The script steps every 5 ticks and we want 50 ticks before a heal + if (stage.mod(10) == 0){ + heal(player, 1) + if(player.skills.lifepoints >= getStatLevel(player, Skills.HITPOINTS)) { + animate(player, Animations.LUNAR_SPELLBOOK_DREAM_END_6297) + return@queueScript stopExecuting(player) + } + } + return@queueScript delayScript(player, 5) + } + } + } + } private fun stringJewellery(player: Player) { val playerJewellery = ArrayDeque() diff --git a/Server/src/main/core/game/node/entity/combat/CombatPulse.kt b/Server/src/main/core/game/node/entity/combat/CombatPulse.kt index 03670d3f0..7e0475e3d 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatPulse.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatPulse.kt @@ -296,6 +296,7 @@ class CombatPulse( } setVictim(victim) entity.onAttack(victim as Entity?) + victim.scripts.removeWeakScripts() if (!isAttacking) entity.pulseManager.run(this) From 7a6adda9979d97cd255e9a160c5c622e7e7d335e Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 11:56:16 +0000 Subject: [PATCH 120/306] Authenticity improvements to runecrafting pouches. Due to changes in degrade counters, they will degrade within the next 1 or 2 fills after this update; this is a one-time event. Resolve (or prevent) this by repairing via the dark mage --- .../global/skill/runecrafting/PouchManager.kt | 160 ++++++++++-------- .../skill/runecrafting/RunePouchPlugin.kt | 24 +-- .../runecrafting/abyss/DarkMageDialogue.java | 19 ++- 3 files changed, 107 insertions(+), 96 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt index 52aba0d4b..087478bfc 100644 --- a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt +++ b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt @@ -1,5 +1,6 @@ package content.global.skill.runecrafting +import core.api.* import core.game.container.Container import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills @@ -7,109 +8,131 @@ import core.game.node.item.Item import org.json.simple.JSONArray import org.json.simple.JSONObject import org.rs09.consts.Items -import core.tools.colorize /** * A class for managing rune pouches. * @param player the player this manager instance belongs to. - * @author Ceikry + * @author Ceikry, Player Name */ class PouchManager(val player: Player) { - val pouches = mapOf( - Items.SMALL_POUCH_5509 to RCPouch(3,1), - Items.MEDIUM_POUCH_5510 to RCPouch(6,25), - Items.LARGE_POUCH_5512 to RCPouch(9,50), - Items.GIANT_POUCH_5514 to RCPouch(12,75) + Items.SMALL_POUCH_5509 to RCPouch(3, 3, 1), + Items.MEDIUM_POUCH_5510 to RCPouch(6, 264, 25), + Items.LARGE_POUCH_5512 to RCPouch(9, 186, 50), + Items.GIANT_POUCH_5514 to RCPouch(12,140, 75) ) /** * Method to add essence to a pouch - * @param pouchId the id of the pouch we are adding to + * @param itemId the item ID of the pouch we are adding to * @param amount the amount of essence to add * @param essence the ID of the essence item we are trying to add - * @author Ceikry + * @author Ceikry, Player Name */ - fun addToPouch(pouchId: Int, amount: Int, essence: Int){ - if(!checkRequirement(pouchId)){ - player.sendMessage(colorize("%RYou lack the required level to use this pouch.")) + fun addToPouch(itemId: Int, amount: Int, essence: Int) { + val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId + if (!checkRequirement(pouchId)) { + sendMessage(player, "You lack the required level to use this pouch.") return } var amt = amount val pouch = pouches[pouchId] - val otherEssence = when(essence){ + val otherEssence = when(essence) { Items.RUNE_ESSENCE_1436 -> Items.PURE_ESSENCE_7936 Items.PURE_ESSENCE_7936 -> Items.RUNE_ESSENCE_1436 else -> 0 } pouch ?: return - if(amount > pouch.container.freeSlots()){ + if (amount > pouch.container.freeSlots()) { amt = pouch.container.freeSlots() } - if(amt == 0){ - player.sendMessage("This pouch is already full.") + if (amt == pouch.container.freeSlots()) { + sendMessage(player, "Your pouch is full.") //https://www.youtube.com/watch?v=wbYtRwODKTo } - if(pouch.container.contains(otherEssence,1)){ - player.sendMessage("You can only store one type of essence in each pouch.") + if (pouch.container.contains(otherEssence,1)) { + sendMessage(player, "You can only store one type of essence in each pouch.") return } - player.inventory.remove(Item(essence,amt)) - pouch.container.add(Item(essence,amt)) - } + var disappeared = false + if (itemId != Items.SMALL_POUCH_5509) { + pouch.charges -= amt + } + if (pouch.charges <= 0) { + pouch.currentCap -= when (pouchId) { + Items.MEDIUM_POUCH_5510 -> 1 + Items.LARGE_POUCH_5512 -> 2 + Items.GIANT_POUCH_5514 -> 3 + else /*small pouch*/ -> 0 + } + if (pouch.currentCap <= 0) { + // The pouch will disappear: https://runescape.wiki/w/Runecrafting_pouches?oldid=708494, https://oldschool.runescape.wiki/w/Essence_pouch + // "Degraded pouches will continue to degrade and lose essence capacity until they disappear or are repaired." implies that this is the end result of a gradual decay process + if (removeItem(player, itemId)) { + disappeared = true + sendMessage(player, "Your pouch has degraded completely.") + // Reset the pouch for when the player obtains a new one + pouch.currentCap = pouch.capacity + pouch.charges = pouch.maxCharges + pouch.remakeContainer() + } + } else { + if (!isDecayedPouch(itemId)) { + val slot = player.inventory.getSlot(Item(itemId)) + replaceSlot(player, slot, Item(itemId + 1)) + } + sendMessage(player, "Your pouch has decayed through use.") //https://www.youtube.com/watch?v=FUcPYrgPUlQ + pouch.charges = 9 * pouch.currentCap //implied by multiple contemporaneous sources, quantified only by https://oldschool.runescape.wiki/w/Large_pouch + pouch.remakeContainer() + if (amt > pouch.currentCap) { + amt = pouch.currentCap + } + } + } + val essItem = Item(essence, amt) + if (!disappeared && removeItem(player, essItem)) { + pouch.container.add(essItem) + } + } /** * Method to withdraw rune essence from a pouch. - * @param pouchId the item ID of the pouch to withdraw from - * @author Ceikry + * @param itemId the item ID of the pouch to withdraw from + * @author Ceikry, Player Name */ - fun withdrawFromPouch(pouchId: Int){ + fun withdrawFromPouch(itemId: Int) { + val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId val pouch = pouches[pouchId] pouch ?: return - val playerFree = player.inventory.freeSlots() + val playerFree = freeSlots(player) var amount = pouch.currentCap - pouch.container.freeSlots() - if (amount > playerFree) amount = playerFree - player.debug("$amount") - if(amount == 0) return - val essence = Item(pouch.container.get(0).id,amount) - pouch.container.remove(essence) - pouch.container.shift() - player.inventory.add(essence) - if(pouch.charges-- <= 0){ - pouch.currentCap -= when(pouchId){ - 5510 -> 1 - 5512 -> 2 - 5514 -> 3 - else -> 0 - } - if(pouch.currentCap <= 0){ - player.inventory.remove(Item(pouchId)) - player.inventory.add(Item(pouchId + 1)) - player.sendMessage(colorize("%RYour ${Item(pouchId).name} has degraded completely.")) - } - pouch.remakeContainer() - pouch.charges = 10 - if(pouchId != 5509) { - player.sendMessage(colorize("%RYour ${Item(pouchId).name.toLowerCase()} has degraded slightly from use.")) + if (amount > playerFree) { + amount = playerFree + } else { + sendMessage(player, "Your pouch has no essence left in it.") //https://www.youtube.com/watch?v=wbYtRwODKTo + if (amount == 0) { + return } } - + val essence = Item(pouch.container.get(0).id, amount) + pouch.container.remove(essence) + pouch.container.shift() + addItem(player, essence.id, essence.amount) } - /** * Method to save pouches to a root JSONObject * @param root the JSONObject we are adding the "pouches" JSONArray to * @author Ceikry */ - fun save(root: JSONObject){ + fun save(root: JSONObject) { val pouches = JSONArray() - for(i in this.pouches){ + for(i in this.pouches) { val pouch = JSONObject() pouch.put("id",i.key.toString()) val items = JSONArray() - for(item in i.value.container.toArray()){ + for(item in i.value.container.toArray()) { item ?: continue val it = JSONObject() it.put("itemId",item.id.toString()) @@ -124,14 +147,13 @@ class PouchManager(val player: Player) { root.put("pouches",pouches) } - /** * Method to parse save data from a JSONArray * @param data the JSONArray that contains the data to parse * @author Ceikry */ - fun parse(data: JSONArray){ - for(e in data){ + fun parse(data: JSONArray) { + for (e in data){ val pouch = e as JSONObject val id = pouch["id"].toString().toInt() val p = pouches[id] @@ -141,7 +163,7 @@ class PouchManager(val player: Player) { p.charges = charges p.currentCap = currentCap p.remakeContainer() - for(i in pouch["container"] as JSONArray){ + for (i in pouch["container"] as JSONArray) { val it = i as JSONObject it["itemId"] ?: continue val item = it["itemId"].toString().toInt() @@ -151,33 +173,31 @@ class PouchManager(val player: Player) { } } - /** * Method for checking the level requirement for a given pouch. * @param pouchId the item ID of the pouch to check * @author Ceikry */ - fun checkRequirement(pouchId: Int): Boolean{ + fun checkRequirement(pouchId: Int): Boolean { val p = pouches[pouchId] p ?: return false return player.skills.getLevel(Skills.RUNECRAFTING) >= p.levelRequirement } - /** * Method for sending the player a message about how much space is left in a pouch - * @param pouchId the item ID of the pouch to check - * @author Ceikry + * @param itemId the item ID of the pouch to check + * @author Ceikry, Player Name */ - fun checkAmount(pouchId: Int){ + fun checkAmount(itemId: Int) { + val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId val p = pouches[pouchId] p ?: return player.sendMessage("This pouch has space for ${p.container.freeSlots()} more essence.") } - - fun isDecayedPouch(pouchId: Int): Boolean{ - if(pouchId == 5510) return false + fun isDecayedPouch(pouchId: Int): Boolean { + if (pouchId == Items.MEDIUM_POUCH_5510) return false return pouches[pouchId - 1] != null } @@ -185,12 +205,12 @@ class PouchManager(val player: Player) { * A class that represents a runecrafting pouch. * @author Ceikry */ - class RCPouch(val capacity: Int, val levelRequirement: Int){ + class RCPouch(val capacity: Int, val maxCharges: Int, val levelRequirement: Int) { var container = Container(capacity) var currentCap = capacity - var charges = 10 - fun remakeContainer(){ + var charges = maxCharges + fun remakeContainer() { this.container = Container(currentCap) } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/runecrafting/RunePouchPlugin.kt b/Server/src/main/content/global/skill/runecrafting/RunePouchPlugin.kt index 41779cf1f..599ca05b0 100644 --- a/Server/src/main/content/global/skill/runecrafting/RunePouchPlugin.kt +++ b/Server/src/main/content/global/skill/runecrafting/RunePouchPlugin.kt @@ -11,7 +11,7 @@ import core.tools.colorize /** * Handles the rune pouches. - * @author Ceikry + * @author Ceikry, Player Name */ class RunePouchPlugin : OptionHandler() { @Throws(Throwable::class) @@ -37,21 +37,11 @@ class RunePouchPlugin : OptionHandler() { if(preferenceFlag == 0) rEssAmt else pEssAmt ) - - if(player.pouchManager.isDecayedPouch(node.id)){ - player.debug("E2") - when(option) { //Handling for IF the pouch has already completely decayed - "drop" -> player.dialogueInterpreter.open(9878,Item(node.id)) - else -> player.sendMessage(colorize("%RThis pouch has completely decayed and needs to be repaired.")) - } - } else { - player.debug("E") - when (option) { //Normal handling - "fill" -> player.pouchManager.addToPouch(node.id, essence.amount, essence.id) - "empty" -> player.pouchManager.withdrawFromPouch(node.id) - "check" -> player.pouchManager.checkAmount(node.id) - "drop" -> player.dialogueInterpreter.open(9878,Item(node.id)) - } + when (option) { + "fill" -> player.pouchManager.addToPouch(node.id, essence.amount, essence.id) + "empty" -> player.pouchManager.withdrawFromPouch(node.id) + "check" -> player.pouchManager.checkAmount(node.id) + "drop" -> player.dialogueInterpreter.open(9878,Item(node.id)) } return true } @@ -59,4 +49,4 @@ class RunePouchPlugin : OptionHandler() { override fun isWalk(): Boolean { return false } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java b/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java index b7297429e..0348f19c8 100644 --- a/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java +++ b/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java @@ -4,6 +4,7 @@ import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import org.rs09.consts.Items; /** * Handles the dark mages dialogue. @@ -140,18 +141,18 @@ public final class DarkMageDialogue extends DialoguePlugin { private boolean repair() { player.pouchManager.getPouches().forEach((id, pouch) -> { pouch.setCurrentCap(pouch.getCapacity()); - pouch.setCharges(10); - Item essence = null; - if(!pouch.getContainer().isEmpty()){ - int ess = pouch.getContainer().get(0).getId(); - int amount = pouch.getContainer().getAmount(ess); - essence = new Item(ess,amount); + pouch.setCharges(pouch.getMaxCharges()); + Item essItem = null; + if (!pouch.getContainer().isEmpty()) { + int essence = pouch.getContainer().get(0).getId(); + int amount = pouch.getContainer().getAmount(essence); + essItem = new Item(essence, amount); } pouch.remakeContainer(); - if(essence != null){ - pouch.getContainer().add(essence); + if (essItem != null) { + pouch.getContainer().add(essItem); } - if(id != 5509) { + if (id != Items.SMALL_POUCH_5509) { if (player.getInventory().contains(id + 1, 1)) { player.getInventory().remove(new Item(id + 1, 1)); player.getInventory().add(new Item(id, 1)); From 1a67932351fc1de787e55b6f8ae2c48503f43cac Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Thu, 14 Nov 2024 12:02:37 +0000 Subject: [PATCH 121/306] Implemented Pillory random event (this event occurs while pick-pocketing) --- .../main/content/global/ame/RandomEvents.kt | 2 + .../ame/events/pillory/PilloryInterface.kt | 220 ++++++++++++++++++ .../global/ame/events/pillory/PilloryNPC.kt | 50 ++++ .../seers/handlers/SeersCageUnlockPlugin.java | 30 --- 4 files changed, 272 insertions(+), 30 deletions(-) create mode 100644 Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt create mode 100644 Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt delete mode 100644 Server/src/main/content/region/kandarin/seers/handlers/SeersCageUnlockPlugin.java diff --git a/Server/src/main/content/global/ame/RandomEvents.kt b/Server/src/main/content/global/ame/RandomEvents.kt index 7e07d744a..13d7390ea 100644 --- a/Server/src/main/content/global/ame/RandomEvents.kt +++ b/Server/src/main/content/global/ame/RandomEvents.kt @@ -9,6 +9,7 @@ import content.global.ame.events.evilbob.EvilBobNPC import content.global.ame.events.evilchicken.EvilChickenNPC import content.global.ame.events.freakyforester.FreakyForesterNPC import content.global.ame.events.genie.GenieNPC +import content.global.ame.events.pillory.PilloryNPC import content.global.ame.events.rickturpentine.RickTurpentineNPC import content.global.ame.events.rivertroll.RiverTrollRENPC import content.global.ame.events.rockgolem.RockGolemRENPC @@ -52,6 +53,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n RICK_TURPENTINE(npc = RickTurpentineNPC(), loot = CERTER.loot), SURPRISE_EXAM(npc = MysteriousOldManNPC(), type = "sexam"), FREAKY_FORESTER(npc = FreakyForesterNPC(), skillIds = intArrayOf(Skills.WOODCUTTING)), + PILLORY(npc = PilloryNPC(), skillIds = intArrayOf(Skills.THIEVING)), TREE_SPIRIT(npc = TreeSpiritRENPC(), skillIds = intArrayOf(Skills.WOODCUTTING)), RIVER_TROLL(RiverTrollRENPC(), skillIds = intArrayOf(Skills.FISHING)), ROCK_GOLEM(RockGolemRENPC(), skillIds = intArrayOf(Skills.MINING)), diff --git a/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt new file mode 100644 index 000000000..55e54a0fb --- /dev/null +++ b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt @@ -0,0 +1,220 @@ +package content.global.ame.events.pillory + +import content.global.ame.RandomEvents +import core.api.* +import core.game.dialogue.FacialExpression +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.game.interaction.InterfaceListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery +import org.rs09.consts.Sounds + +/** + * Pillory Unlocking Interface PILLORY_189 + * + * https://www.youtube.com/watch?v=caWn7pE2mkE + * https://www.youtube.com/watch?v=TMVR5cZZwZ0 + * https://www.youtube.com/watch?v=Ym9LCDP-Q74 + * https://www.youtube.com/watch?v=_vn0QZTtI6U (Failure) + * https://www.youtube.com/watch?v=zmXDikQIua4 + * + * Child IDs + * 4 - Rotating Lock Model + * 5 6 7 - Swinging Keys Models + * 8 9 10 - Buttons for the Swinging Keys Models + * 11 12 13 14 15 16 - Padlocks at the Top + * 17 18 19 20 21 22 - Padlocks stars? Model 15272, Anim 4135 + * + * Model IDs + * Using the amazeballs ::listifmodels + * 9749, 9750, 9751, 9752 - Swinging Keys Models + * 9753, 9754, 9755, 9756 - Rotating Lock Models + * 9757 9758 locked unlock + */ +class PilloryInterface : InterfaceListener, InteractionListener, MapArea { + companion object { + const val PILLORY_LOCK_INTERFACE = 189 + const val PILLORY_ATRRIBUTE_RETURN_LOC = "/save:original-loc" + const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys" + const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock" + const val PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct" + const val PILLORY_ATRRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct" + + val LOCATIONS = arrayOf( + // Varrock Cages + Location(3226, 3407, 0), + Location(3228, 3407, 0), + Location(3230, 3407, 0), + // Seers Village Cages + Location(2681, 3489, 0), + Location(2683, 3489, 0), + Location(2685, 3489, 0), + // Yannile Cages + Location(2604, 3105, 0), + Location(2606, 3105, 0), + Location(2608, 3105, 0), + ) + + fun initPillory(player: Player) { + setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) + setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.") + } + + fun randomPillory(player: Player) { + // Shuffle all 4 kinds of keys in, pick 3 for the keys, pick 1 from the 3 as the lock. + val keys = (0..3).toIntArray().let{ keys -> keys.shuffle(); return@let keys } + val lock = intArrayOf(keys[1], keys[2], keys[3]).random() // Last 3 as there are 4 keys. key[0] is fallback. + + setAttribute(player, PILLORY_ATTRIBUTE_EVENT_KEYS, keys) + setAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, lock) + + player.packetDispatch.sendModelOnInterface(9753 + lock, PILLORY_LOCK_INTERFACE, 4, 0) + player.packetDispatch.sendModelOnInterface(9749 + keys[1], PILLORY_LOCK_INTERFACE, 5, 0) + player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0) + player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0) + + val numberToGetCorrect = getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) + val correctCount = getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + for (i in 1.. 6) { + // Set if lock is red or green. + if (i <= correctCount) { + player.packetDispatch.sendModelOnInterface(9758, PILLORY_LOCK_INTERFACE, 10 + i, 0) + } else { + player.packetDispatch.sendModelOnInterface(9757, PILLORY_LOCK_INTERFACE, 10 + i, 0) + } + // Set if hide or show lock. + player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 10 + i, i > numberToGetCorrect) + } + } + + fun selectedKey(player: Player, buttonID: Int) { + val keys = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_KEYS, intArrayOf(0, 0, 0)) + val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1) + if (keys[buttonID] == lock) { + // CORRECT ANSWER + setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + 1) + if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, -1)) { + player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!") + sendMessage(player, "You've escaped!") + removeAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT) + removeAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER) + closeInterface(player) + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + lock(player, 6) + sendGraphics(Graphics(1576, 0, 0), player.location) + animate(player,8939) + playAudio(player, Sounds.TELEPORT_ALL_200) + return@queueScript delayScript(player, 3) + } + 1 -> { + val loot = RandomEvents.CERTER.loot!!.roll(player)[0] + addItemOrDrop(player, loot.id, loot.amount) + teleport(player, getAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + sendGraphics(Graphics(1577, 0, 0), player.location) + animate(player,8941) + removeAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC) + closeInterface(player) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + return + } + randomPillory(player) + player.dialogueInterpreter.sendPlainMessage( + true, + "", + "Correct!", + "" + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + " down, " + + (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)) + " to go!") + // Animation for the star, but it doesn't work. + player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1), false) + sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1)) + } else { + // WRONG ANSWER + player.dialogueInterpreter.close() + player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.") + if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) { + setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1) + } + setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + closeInterface(player) + } + } + } + + override fun defineInterfaceListeners() { + on(PILLORY_LOCK_INTERFACE){ player, component, opcode, buttonID, slot, itemID -> + when (buttonID) { + 8 -> selectedKey(player, 1) + 9 -> selectedKey(player, 2) + 10 -> selectedKey(player, 3) + } + return@on true + } + + onOpen(PILLORY_LOCK_INTERFACE){ player, component -> + return@onOpen true + } + } + + override fun defineListeners() { + on(Scenery.CAGE_6836, IntType.SCENERY, "unlock") { player, node -> + if (player.location in LOCATIONS) { // When you aren't inside. + randomPillory(player) + openInterface(player, PILLORY_LOCK_INTERFACE) + player.dialogueInterpreter.sendPlainMessage(true, "", "Pick the swinging key that matches the", "hole in the spinning lock.") + } else { + sendMessage(player, "You can't unlock the pillory, you'll let all the prisoners out!") + } + return@on true + } + } + + override fun defineAreaBorders(): Array { + return arrayOf( + // Varrock Cages + ZoneBorders(3226, 3407, 3226, 3407), + ZoneBorders(3228, 3407, 3228, 3407), + ZoneBorders(3230, 3407, 3230, 3407), + // Seers Village Cages + ZoneBorders(2681, 3489, 2681, 3489), + ZoneBorders(2683, 3489, 2683, 3489), + ZoneBorders(2685, 3489, 2685, 3489), + // Yannile Cages + ZoneBorders(2604, 3105, 2604, 3105), + ZoneBorders(2606, 3105, 2606, 3105), + ZoneBorders(2608, 3105, 2608, 3105), + ) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12) + } + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + entity.interfaceManager.restoreTabs() + } + } + + +} \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt b/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt new file mode 100644 index 000000000..055c684dd --- /dev/null +++ b/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt @@ -0,0 +1,50 @@ +package content.global.ame.events.pillory + +import content.global.ame.RandomEventNPC +import core.api.* +import core.api.utils.WeightBasedTable +import core.game.interaction.QueueStrength +import core.game.node.entity.npc.NPC +import core.game.system.timer.impl.AntiMacro +import core.game.world.map.Location +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.NPCs +import org.rs09.consts.Sounds + +// "::revent [-p] player name [-e event name]" +class PilloryNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.PILLORY_GUARD_2791) { + + override fun init() { + super.init() + sendChat("${player.username}, you're under arrest!") + face(player) + player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.") + queueScript(player, 4, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + lock(player, 6) + sendGraphics(Graphics(1576, 0, 0), player.location) + animate(player,8939) + playAudio(player, Sounds.TELEPORT_ALL_200) + return@queueScript delayScript(player, 3) + } + 1 -> { + if (getAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, null) == null) { + setAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, player.location) + } + PilloryInterface.initPillory(player) + teleport(player, PilloryInterface.LOCATIONS.random()) // 9 random spots! + AntiMacro.terminateEventNpc(player) + sendGraphics(Graphics(1577, 0, 0), player.location) + animate(player,8941) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + override fun talkTo(npc: NPC) { + //player.dialogueInterpreter.open(FreakyForesterDialogue(),npc) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/seers/handlers/SeersCageUnlockPlugin.java b/Server/src/main/content/region/kandarin/seers/handlers/SeersCageUnlockPlugin.java deleted file mode 100644 index 8f0f09929..000000000 --- a/Server/src/main/content/region/kandarin/seers/handlers/SeersCageUnlockPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -package content.region.kandarin.seers.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the plugin used to unlock the sheers cage. - * @author 'Vexia - * @versio 1.0 - */ -@Initializable -public final class SeersCageUnlockPlugin extends OptionHandler { - - @Override - public boolean handle(Player player, Node node, String option) { - player.getPacketDispatch().sendMessage("You can't unlock the pillory, you'll let all the prisoners out!"); - return true; - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(6836).getHandlers().put("option:unlock", this); - return this; - } - -} From 9054e36288027e9fbecd233e2985488aa101543d Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 14 Nov 2024 12:05:46 +0000 Subject: [PATCH 122/306] King Bolren now gives back lost gnome amulets --- .../scorpioncatcher/SCThormacDialogue.kt | 4 +- .../kandarin/quest/tree/KingBolrenDialogue.kt | 11 ++++-- .../quest/familycrest/DimintheisDialogue.kt | 2 +- Server/src/main/core/api/ContentAPI.kt | 38 ++++++++++++++++--- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt index 0d7a378ab..d144c7650 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt @@ -87,9 +87,9 @@ class SCThormacDialogue(val questStage: Int) : DialogueFile() { WAITING_FOR_SCORPIONS -> { - if (!hasAnItem(player!!, Items.SCORPION_CAGE_456, Items.SCORPION_CAGE_457, Items.SCORPION_CAGE_458, + if (!hasAnItem(player!!, arrayOf(Items.SCORPION_CAGE_456, Items.SCORPION_CAGE_457, Items.SCORPION_CAGE_458, Items.SCORPION_CAGE_459, Items.SCORPION_CAGE_460, Items.SCORPION_CAGE_461, - Items.SCORPION_CAGE_462).exists()){ + Items.SCORPION_CAGE_462), false).exists()){ playerl(FacialExpression.SAD, "I've lost my cage.").also { stage = GIVE_ANOTHER_CAGE } } else{ diff --git a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt index 169f6b016..a84f22118 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt @@ -187,10 +187,15 @@ class KingBolrenDialogue : DialogueFile() { } isQuestComplete(player!!, questName) -> { when(stage) { - 0 -> playerl("Hello Bolren.").also { stage++ } - 1 -> npcl("Thank you for your help traveler.").also { stage = END_DIALOGUE } + 0 -> playerl("Hello again Bolren.").also { stage++ } + 1 -> npcl("Well hello, it's good to see you again.").also { stage = if (hasAnItem(player!!, Items.GNOME_AMULET_589).container != null) END_DIALOGUE else 2 } + 2 -> playerl("I've lost my amulet.").also { stage++ } + 3 -> npcl("Oh dear. Here, take another. We are truly indebted to you.").also { + addItemOrDrop(player!!, Items.GNOME_AMULET_589) + stage = END_DIALOGUE + } } } } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt index 746f1ebfd..3263df6cb 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt @@ -30,7 +30,7 @@ class DimintheisDialogue(player: Player? = null): core.game.dialogue.DialoguePlu return true } - val hasGauntlets = hasAnItem(player, Items.COOKING_GAUNTLETS_775, Items.GOLDSMITH_GAUNTLETS_776, Items.CHAOS_GAUNTLETS_777, Items.FAMILY_GAUNTLETS_778).container != null + val hasGauntlets = hasAnItem(player, arrayOf(Items.COOKING_GAUNTLETS_775, Items.GOLDSMITH_GAUNTLETS_776, Items.CHAOS_GAUNTLETS_777, Items.FAMILY_GAUNTLETS_778), true).container != null if (questComplete && hasGauntlets) { npc("Thank you for saving our family honour, ", diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 84d41d69a..c0f395b69 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -247,14 +247,40 @@ class ContainerisedItem(val container: core.game.container.Container?, val itemI } /** - * Check if player has any of the specified item IDs equipped, in inventory, or in banks - * Returns a ContainerisedItem containing the container and the item ID if found, otherwise ContainerisedItem(null, -1) if not found + * Check if player has the specified item ID equipped, in inventory, or in their bank + * @param id The item ID to check + * @return A ContainerisedItem containing the container and the item ID if found, otherwise ContainerisedItem(null, -1) if not found */ -fun hasAnItem(player: Player, vararg ids: Int): ContainerisedItem { - for (searchSpace in arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary)) { +fun hasAnItem(player: Player, id: Int): ContainerisedItem { + return hasAnItem(player, arrayOf(id), false) +} + +/** + * Check if player has the specified item ID equipped, in inventory, or in their bank + * @param id The item ID to check + * @param checkSecondBank Whether to check the player's second bank. + * @return A ContainerisedItem containing the container and the item ID if found, otherwise ContainerisedItem(null, -1) if not found + */ +fun hasAnItem(player: Player, id: Int, checkSecondBank: Boolean): ContainerisedItem { + return hasAnItem(player, arrayOf(id), checkSecondBank) +} + +/** + * Check if player has any of the specified item IDs equipped, in inventory, or in their bank + * @param ids An array of item IDs to check + * @param checkSecondBank Whether to check the player's second bank. + * @return A ContainerisedItem containing the container and the item ID if found, otherwise ContainerisedItem(null, -1) if not found + */ +fun hasAnItem(player: Player, ids: Array, checkSecondBank: Boolean): ContainerisedItem { + val searchSpace = if (checkSecondBank) { + arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary) + } else { + arrayOf(player.inventory, player.equipment, player.bankPrimary) + } + for (container in searchSpace) { for (id in ids) { - if (searchSpace.containItems(id)) { - return ContainerisedItem(searchSpace, id) + if (container.containItems(id)) { + return ContainerisedItem(container, id) } } } From e216a6366ff871e44531de252e4d475e8e3a2f22 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Thu, 14 Nov 2024 12:08:21 +0000 Subject: [PATCH 123/306] Use the system update countdown for the daily restart --- Server/src/main/core/worker/MajorUpdateWorker.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Server/src/main/core/worker/MajorUpdateWorker.kt b/Server/src/main/core/worker/MajorUpdateWorker.kt index cdebab943..29d48faa8 100644 --- a/Server/src/main/core/worker/MajorUpdateWorker.kt +++ b/Server/src/main/core/worker/MajorUpdateWorker.kt @@ -66,12 +66,18 @@ class MajorUpdateWorker { ServerStore.clearDailyEntries() if (ServerConstants.DAILY_RESTART) { + for (player in Repository.players.filter { !it.isArtificial }) { + player.packetDispatch.sendSystemUpdate(500) + } Repository.sendNews(colorize("%RSERVER GOING DOWN FOR DAILY RESTART IN 5 MINUTES!")) ServerConstants.DAILY_RESTART = false submitWorldPulse(object : Pulse(100) { var counter = 0 override fun pulse(): Boolean { counter++ + for (player in Repository.players.filter { !it.isArtificial }) { + player.packetDispatch.sendSystemUpdate((5 - counter) * 100) + } if (counter == 5) { exitProcess(0) } From 7d79c9a82ab9efb20c7f099abb27a562cf82ce9f Mon Sep 17 00:00:00 2001 From: GregF Date: Thu, 14 Nov 2024 12:14:31 +0000 Subject: [PATCH 124/306] Construction can now be used to fix the ladder to the wilderness beacon --- .../allfiredup/AFURepairClimbHandler.kt | 75 +++++++++++++++---- .../main/core/game/requirement/Requirement.kt | 3 +- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt b/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt index ac6017994..e64b93b67 100644 --- a/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt +++ b/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt @@ -26,27 +26,74 @@ class AFURepairClimbHandler : InteractionListener { override fun defineListeners() { on(repairIDs, IntType.SCENERY, "repair"){ player, _ -> - var rco: RepairClimbObject = RepairClimbObject.GWD - for(ent in RepairClimbObject.values()) if(ent.destinationDown?.withinDistance(player.location,2) == true || ent.destinationUp?.withinDistance(player.location,2) == true) rco = ent - repair(player,rco) - return@on true + if (hasRequirement(player, "All Fired Up")){ + val rco: RepairClimbObject? = getClimbingObject(player) + repair(player,rco!!) + return@on true + } + return@on false } on(climbIDs, IntType.SCENERY, "climb"){ player, node -> - var rco: RepairClimbObject = RepairClimbObject.GWD - for(ent in RepairClimbObject.values()) if(ent.destinationDown?.withinDistance(player.location,2) == true || ent.destinationUp?.withinDistance(player.location,2) == true) rco = ent - climb(player,rco,node.location) + val rco: RepairClimbObject? = getClimbingObject(player) + climb(player,rco!!,node.location) return@on true } } + private fun getClimbingObject(player: Player): RepairClimbObject?{ + for(ent in RepairClimbObject.values()) + if(ent.destinationDown?.withinDistance(player.location,2) == true || + ent.destinationUp?.withinDistance(player.location,2) == true){ + return ent + } + return null + } + private fun repair(player: Player,rco: RepairClimbObject){ + if (rco == RepairClimbObject.TEMPLE){ + // You can do this 2 different ways + val hasSmithingLevel = getDynLevel(player, Skills.SMITHING) >= 70 + val hasConstructionLevel = getDynLevel(player, Skills.CONSTRUCTION) >= 59 + + if (!hasConstructionLevel && !hasSmithingLevel){ + sendDialogue(player, "You need level 70 smithing or 59 construction for this.") + return + } + + val hasHammer = inInventory(player, Items.HAMMER_2347) + val hasSmithingItems = hasHammer && inInventory(player, Items.IRON_BAR_2351, 2) + val hasConstructionItems = hasHammer && inInventory(player, Items.PLANK_960, 2) + + if (hasSmithingLevel && hasSmithingItems){ + if (removeItem(player,Item(Items.IRON_BAR_2351, 2))) { + setVarbit(player, rco.varbit, 1, true) + return + } + } + // Only check this if the smithing repair didn't work + if (hasConstructionLevel && hasConstructionItems){ + val nails = NailType.get(player, 4) + if (nails != null){ + if (removeItem(player, Item(Items.PLANK_960, 2)) && removeItem(player, Item(nails.itemId, 4))) { + setVarbit(player, rco.varbit, 1, true) + return + } + } + } + + var msg = "You need " + msg += if (hasSmithingLevel) "a hammer and 2 iron bars" else "" + msg += if (hasSmithingLevel && hasConstructionLevel) " or " else "" + msg += if (hasConstructionLevel) "a hammer, 2 planks and 4 nails for this." else " for this." + sendDialogue(player, msg) + return + } val skill = rco.levelRequirement?.first ?: 0 val level = rco.levelRequirement?.second ?: 0 if(player.skills.getLevel(skill) < level){ player.dialogueInterpreter.sendDialogue("You need level $level ${Skills.SKILL_NAME[skill]} for this.") - return } var requiresNeedle = false @@ -64,10 +111,7 @@ class AFURepairClimbHandler : InteractionListener { requiresNeedle = true arrayOf(Item(Items.JUTE_FIBRE_5931,3)) } - - RepairClimbObject.TEMPLE -> { - arrayOf(Item(Items.IRON_BAR_2351,2)) - } + else -> return } if(requiresNeedle){ @@ -75,7 +119,7 @@ class AFURepairClimbHandler : InteractionListener { player.inventory.remove(*requiredItems) if (Random().nextBoolean()) player.inventory.remove(Item(Items.NEEDLE_1733)) } else { - player.dialogueInterpreter.sendDialogue("You need a needle and ${requiredItems.map { "${it.amount} ${it.name.toLowerCase()}s" }.toString().replace("[","").replace("]","")} for this.") + player.dialogueInterpreter.sendDialogue("You need a needle and ${requiredItems.map { "${it.amount} ${it.name.lowercase()}s" }.toString().replace("[","").replace("]","")} for this.") return } } else { @@ -89,11 +133,10 @@ class AFURepairClimbHandler : InteractionListener { } player.inventory.remove(*requiredItems) } else { - player.dialogueInterpreter.sendDialogue("You need a hammer and ${requiredItems.map { "${it.amount} ${it.name.toLowerCase()}s" }.toString().replace("[","").replace("]","")} for this.") + player.dialogueInterpreter.sendDialogue("You need a hammer and ${requiredItems.map { "${it.amount} ${it.name.lowercase()}s" }.toString().replace("[","").replace("]","")} for this.") return } } - setVarbit(player, rco.varbit, 1, true) } @@ -105,7 +148,7 @@ class AFURepairClimbHandler : InteractionListener { DEATH_PLATEAU(5161,Location.create(2949, 3623, 0),Location.create(2954, 3623, 0), Pair(Skills.CONSTRUCTION,42)), BURTHORPE(5160,Location.create(2941, 3563, 0),Location.create(2934, 3563, 0),Pair(Skills.SMITHING,56)), GWD(5163,null,null,Pair(Skills.CRAFTING,60)), - TEMPLE(5164,Location.create(2949, 3835, 0),Location.create(2956, 3835, 0),Pair(Skills.SMITHING,64)); + TEMPLE(5164,Location.create(2949, 3835, 0),Location.create(2956, 3835, 0),Pair(0,0)); // This needs to be handled specially so don't have levels here fun getOtherLocation(player: Player): Location?{ if(player.location == destinationDown) return destinationUp diff --git a/Server/src/main/core/game/requirement/Requirement.kt b/Server/src/main/core/game/requirement/Requirement.kt index 0cbd1c508..da5a94a71 100644 --- a/Server/src/main/core/game/requirement/Requirement.kt +++ b/Server/src/main/core/game/requirement/Requirement.kt @@ -195,5 +195,6 @@ enum class QuestRequirements (val questName: String, vararg val requirements: Re 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)) + 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)), + ALL_FIRED_UP ("All Fired Up", QuestReq(PRIEST), SkillReq(Skills.FIREMAKING, 43)) } From 79c69e3d43ce66e6ed21bc40f3cf2ca5acdf5753 Mon Sep 17 00:00:00 2001 From: Ryan <2804894-ryannathans@users.noreply.gitlab.com> Date: Thu, 14 Nov 2024 12:42:48 +0000 Subject: [PATCH 125/306] Changed timestamp in logs to ISO standard datetime format --- Server/src/main/core/tools/SystemLogger.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/tools/SystemLogger.kt b/Server/src/main/core/tools/SystemLogger.kt index eb65de9ea..dc5b96560 100644 --- a/Server/src/main/core/tools/SystemLogger.kt +++ b/Server/src/main/core/tools/SystemLogger.kt @@ -19,7 +19,7 @@ import java.util.* object SystemLogger { val t = Terminal() val errT = t.forStdErr() - val formatter = SimpleDateFormat("HH:mm:ss") + val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX") private fun getTime(): String{ return "[" + formatter.format(Date(System.currentTimeMillis())) +"]" From 02a36f7bf791414f9319738f90e99262339fbb4f Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 15 Nov 2024 12:37:47 -0700 Subject: [PATCH 126/306] Removed gloves of silence requirement for auto-pickpocketing --- .../global/skill/thieving/ThievingListeners.kt | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt index a236ca291..8068d35eb 100644 --- a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt +++ b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt @@ -68,9 +68,8 @@ class ThievingListeners : InteractionListener { return@on true } - //Custom portion. If the player has gloves of silence, only proceed every other tick - val glovesOfSilence = player.equipment.contains(Items.GLOVES_OF_SILENCE_10075,1) - if (!glovesOfSilence || GameWorld.ticks % 2 == 0) { + //Custom portion. Repeat pickpocket, only proceed every other tick + if (GameWorld.ticks % 2 == 0) { player.animator.animate(PICKPOCKET_ANIM) val lootTable = pickpocketRoll(player, pickpocketData.low, pickpocketData.high, pickpocketData.table) @@ -87,17 +86,14 @@ class ThievingListeners : InteractionListener { node.asNpc().face(null) } else { playAudio(player, Sounds.PICK_2581) - if (!glovesOfSilence) { - player.lock(2) - } + //player.lock(2) lootTable.forEach { player.inventory.add(it) } player.skills.addExperience(Skills.THIEVING,pickpocketData.experience) } } - // if wearing gloves of silence, pickpocket again. - if (glovesOfSilence) { - InteractionListeners.run(node.id, IntType.NPC,"Pickpocket",player,node) - } + //pickpocket again. + InteractionListeners.run(node.id, IntType.NPC,"Pickpocket",player,node) + return@on true } } From 6845a3740f6ddfd7fbb75b709728020087ff4c2f Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 16 Nov 2024 09:47:46 -0700 Subject: [PATCH 127/306] Rebalanced prayer point drain rates (almost everything except protection prayers drains far less) - Protection prayers are now all equal at 10 points per minute - the 5%, 10%, and 15% bonus prayers now drain 1, 2, and 3 points per minute, respectively. Having all of them active at once is now a lower drain than Chivalry. -- The attack and strength versions drain half of that, since you need two of them active. - Chivalry and Piety now also boost magic and ranged at the same rate as attack, and have had their drain slightly lowered. (7.5 and 10 points per minute) --- .../entity/player/link/prayer/PrayerType.java | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Server/src/main/core/game/node/entity/player/link/prayer/PrayerType.java b/Server/src/main/core/game/node/entity/player/link/prayer/PrayerType.java index e8fba525e..5b8b3e8a1 100644 --- a/Server/src/main/core/game/node/entity/player/link/prayer/PrayerType.java +++ b/Server/src/main/core/game/node/entity/player/link/prayer/PrayerType.java @@ -22,33 +22,33 @@ import static core.api.ContentAPIKt.*; * @author jamix77 */ public enum PrayerType { - THICK_SKIN(1, 12, 83, 5, PrayerCategory.BABY_BLUE, Sounds.THICK_SKIN_2690, new SkillBonus(Skills.DEFENCE, 0.05)), - BURST_OF_STRENGTH(4, 12, 84, 7, PrayerCategory.GREEN, Sounds.STRENGTH_BURST_2688, new SkillBonus(Skills.STRENGTH, 0.05)), - CLARITY_OF_THOUGHT(7, 12, 85, 9, PrayerCategory.PINK, Sounds.CLARITY_2664, new SkillBonus(Skills.ATTACK, 0.05)), - SHARP_EYE(8, 12, 862, 11, PrayerCategory.LIME_GREEN, Sounds.SHARP_EYE_2685, new SkillBonus(Skills.RANGE, 0.05)), - MYSTIC_WILL(9, 12, 863, 13, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_WILL_2670, new SkillBonus(Skills.MAGIC, 0.05)), - ROCK_SKIN(10, 6, 86, 15, PrayerCategory.BABY_BLUE, Sounds.ROCK_SKIN_2684, new SkillBonus(Skills.DEFENCE, 0.1)), - SUPERHUMAN_STRENGTH(13, 6, 87, 17, PrayerCategory.GREEN, Sounds.SUPERHUMAN_STRENGTH_2689, new SkillBonus(Skills.STRENGTH, 0.1)), - IMPROVED_REFLEXES(16, 6, 88, 19, PrayerCategory.PINK, Sounds.IMPROVED_REFLEXES_2662, new SkillBonus(Skills.ATTACK, 0.1)), - RAPID_RESTORE(19, 26, 89, 21, PrayerCategory.PURPLE, Sounds.RAPID_RESTORE_2679), - RAPID_HEAL(22, 18, 90, 23, PrayerCategory.PURPLE, Sounds.RAPID_HEAL_2678), - PROTECT_ITEMS(25, 18, 91, 25, PrayerCategory.DARK_GREEN, Sounds.PROTECT_ITEMS_1982), - HAWK_EYE(26, 6, 864, 27, PrayerCategory.LIME_GREEN, Sounds.HAWK_EYE_2666, new SkillBonus(Skills.RANGE, 0.1)), - MYSTIC_LORE(27, 6, 865, 29, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_2668, new SkillBonus(Skills.MAGIC, 0.1)), - STEEL_SKIN(28, 3, 92, 31, PrayerCategory.BABY_BLUE, Sounds.STEEL_SKIN_2687, new SkillBonus(Skills.DEFENCE, 0.15)), - ULTIMATE_STRENGTH(31, 3, 93, 33, PrayerCategory.GREEN, Sounds.ULTIMATE_STRENGTH_2691, new SkillBonus(Skills.STRENGTH, 0.15)), - INCREDIBLE_REFLEXES(34, 3, 94, 35, PrayerCategory.PINK, Sounds.INCREDIBLE_REFLEXES_2667, new SkillBonus(Skills.ATTACK, 0.15)), - PROTECT_FROM_SUMMONING(35, 2, 1168, 53, PrayerCategory.DARK_BROWN, PrayerCategory.MAGENTA, new Audio(4262)), + THICK_SKIN(1, 30, 83, 5, PrayerCategory.BABY_BLUE, Sounds.THICK_SKIN_2690, new SkillBonus(Skills.DEFENCE, 0.05)), + BURST_OF_STRENGTH(4, 60, 84, 7, PrayerCategory.GREEN, Sounds.STRENGTH_BURST_2688, new SkillBonus(Skills.STRENGTH, 0.05)), + CLARITY_OF_THOUGHT(7, 60, 85, 9, PrayerCategory.PINK, Sounds.CLARITY_2664, new SkillBonus(Skills.ATTACK, 0.05)), + SHARP_EYE(8, 30, 862, 11, PrayerCategory.LIME_GREEN, Sounds.SHARP_EYE_2685, new SkillBonus(Skills.RANGE, 0.05)), + MYSTIC_WILL(9, 30, 863, 13, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_WILL_2670, new SkillBonus(Skills.MAGIC, 0.05)), + ROCK_SKIN(10, 15, 86, 15, PrayerCategory.BABY_BLUE, Sounds.ROCK_SKIN_2684, new SkillBonus(Skills.DEFENCE, 0.1)), + SUPERHUMAN_STRENGTH(13, 30, 87, 17, PrayerCategory.GREEN, Sounds.SUPERHUMAN_STRENGTH_2689, new SkillBonus(Skills.STRENGTH, 0.1)), + IMPROVED_REFLEXES(16, 30, 88, 19, PrayerCategory.PINK, Sounds.IMPROVED_REFLEXES_2662, new SkillBonus(Skills.ATTACK, 0.1)), + RAPID_RESTORE(19, 30, 89, 21, PrayerCategory.PURPLE, Sounds.RAPID_RESTORE_2679), + RAPID_HEAL(22, 20, 90, 23, PrayerCategory.PURPLE, Sounds.RAPID_HEAL_2678), + PROTECT_ITEMS(25, 20, 91, 25, PrayerCategory.DARK_GREEN, Sounds.PROTECT_ITEMS_1982), + HAWK_EYE(26, 15, 864, 27, PrayerCategory.LIME_GREEN, Sounds.HAWK_EYE_2666, new SkillBonus(Skills.RANGE, 0.1)), + MYSTIC_LORE(27, 15, 865, 29, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_2668, new SkillBonus(Skills.MAGIC, 0.1)), + STEEL_SKIN(28, 10, 92, 31, PrayerCategory.BABY_BLUE, Sounds.STEEL_SKIN_2687, new SkillBonus(Skills.DEFENCE, 0.15)), + ULTIMATE_STRENGTH(31, 20, 93, 33, PrayerCategory.GREEN, Sounds.ULTIMATE_STRENGTH_2691, new SkillBonus(Skills.STRENGTH, 0.15)), + INCREDIBLE_REFLEXES(34, 20, 94, 35, PrayerCategory.PINK, Sounds.INCREDIBLE_REFLEXES_2667, new SkillBonus(Skills.ATTACK, 0.15)), + PROTECT_FROM_SUMMONING(35, 3, 1168, 53, PrayerCategory.DARK_BROWN, PrayerCategory.MAGENTA, new Audio(4262)), PROTECT_FROM_MAGIC(37, 3, 95, 37, PrayerCategory.LIGHT_BROWN, Sounds.PROTECT_FROM_MAGIC_2675), PROTECT_FROM_MISSILES(40, 3, 96, 39, PrayerCategory.LIGHT_BROWN, Sounds.PROTECT_FROM_MISSILES_2677), - PROTECT_FROM_MELEE(43, 4, 97, 41, PrayerCategory.LIGHT_BROWN, Sounds.PROTECT_FROM_MELEE_2676), - EAGLE_EYE(44, 3, 866, 43, PrayerCategory.LIME_GREEN, Sounds.EAGLE_EYE_2665, new SkillBonus(Skills.RANGE, 0.15)), - MYSTIC_MIGHT(45, 3, 867, 45, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_MIGHT_2669, new SkillBonus(Skills.MAGIC, 0.15)), + PROTECT_FROM_MELEE(43, 3, 97, 41, PrayerCategory.LIGHT_BROWN, Sounds.PROTECT_FROM_MELEE_2676), + EAGLE_EYE(44, 10, 866, 43, PrayerCategory.LIME_GREEN, Sounds.EAGLE_EYE_2665, new SkillBonus(Skills.RANGE, 0.15)), + MYSTIC_MIGHT(45, 10, 867, 45, PrayerCategory.LIME_GREEN, Sounds.MYSTIC_MIGHT_2669, new SkillBonus(Skills.MAGIC, 0.15)), RETRIBUTION(46, 12, 98, 47, PrayerCategory.LIGHT_BROWN, PrayerCategory.MAGENTA, new Audio(2682)), REDEMPTION(49, 6, 99, 49, PrayerCategory.LIGHT_BROWN, PrayerCategory.MAGENTA, new Audio(2680)), SMITE(52, 2, 100, 51, PrayerCategory.LIGHT_BROWN, PrayerCategory.MAGENTA, new Audio(2686)), - CHIVALRY(60, 2, 1052, 55, PrayerCategory.PINK, Sounds.KR_CHIVALRY_3826, 65, new SkillBonus(Skills.DEFENCE, 0.2), new SkillBonus(Skills.STRENGTH, 0.18), new SkillBonus(Skills.ATTACK, 0.15)), - PIETY(70, 2, 1053, 57, PrayerCategory.PINK, Sounds.KR_PIETY_3825, 70, new SkillBonus(Skills.DEFENCE, 0.25), new SkillBonus(Skills.STRENGTH, 0.23), new SkillBonus(Skills.ATTACK, 0.2)); + CHIVALRY(60, 4, 1052, 55, PrayerCategory.PINK, Sounds.KR_CHIVALRY_3826, 65, new SkillBonus(Skills.DEFENCE, 0.2), new SkillBonus(Skills.STRENGTH, 0.18), new SkillBonus(Skills.ATTACK, 0.15), new SkillBonus(Skills.MAGIC, 0.15), new SkillBonus(Skills.RANGE, 0.15)), + PIETY(70, 3, 1053, 57, PrayerCategory.PINK, Sounds.KR_PIETY_3825, 70, new SkillBonus(Skills.DEFENCE, 0.25), new SkillBonus(Skills.STRENGTH, 0.23), new SkillBonus(Skills.ATTACK, 0.2), new SkillBonus(Skills.MAGIC, 0.2), new SkillBonus(Skills.RANGE, 0.2)); /** * Represents the a cache of objects related to prayers in order to decide @@ -63,6 +63,7 @@ public enum PrayerType { /** * The drain rate. + * The drain rate X 2 is the number of seconds (not ticks) that it takes to drain 1 point at 0 prayer bonus */ private final int drain; From 8f55baa13eec8e3dac0e06cf3a35d9d2cb51a15e Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 16 Nov 2024 16:19:06 -0700 Subject: [PATCH 128/306] Experience multiplier now scales based on the skill level This slows down the extremely boosted early game while still allowing the multiplier to reduce late-game grind. --- Server/src/main/core/game/node/entity/skill/Skills.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index 9f550245a..bc07f8e25 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -290,7 +290,13 @@ public final class Skills { private double getExperienceMod(int slot, double experience, boolean playerMod, boolean multiplyer) { //Keywords for people ctrl + Fing the project //xprate xp rate xp multiplier skilling rate - return experienceMultiplier; + + //Snowscape Custom: experience multiplier starts at 1x and scales to the selected multiplier as level incrceases + double perLevel = (experienceMutiplier-1)/100; + double finalMult = staticLevels[slot]*perLevel+1; + return finalMult; + //return experienceMultiplier; + /*if (!(entity instanceof Player)) { return 1.0; } From 63c7fc3f702e1a2560cbc9046cc4c1357e8c2f93 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 16 Nov 2024 16:45:43 -0700 Subject: [PATCH 129/306] Fixed typo in variable name --- Server/src/main/core/game/node/entity/skill/Skills.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index bc07f8e25..fc3ed9191 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -292,7 +292,7 @@ public final class Skills { //xprate xp rate xp multiplier skilling rate //Snowscape Custom: experience multiplier starts at 1x and scales to the selected multiplier as level incrceases - double perLevel = (experienceMutiplier-1)/100; + double perLevel = (experienceMultiplier-1)/100; double finalMult = staticLevels[slot]*perLevel+1; return finalMult; //return experienceMultiplier; From ee6f83eb7e0b1b4d3b1ac970f8bc96a4e650e766 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 10:56:19 -0700 Subject: [PATCH 130/306] Improved timing of pickpocket repeating, and allowed repeating even when caught --- .../content/global/skill/thieving/ThievingListeners.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt index 8068d35eb..77a7f25dc 100644 --- a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt +++ b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt @@ -68,8 +68,8 @@ class ThievingListeners : InteractionListener { return@on true } - //Custom portion. Repeat pickpocket, only proceed every other tick - if (GameWorld.ticks % 2 == 0) { + //Custom portion. Repeat pickpocket, only proceed if it has been long enough since the last pickpocket action + if (getAttribute(player, "pickpockettick", 0) <= GameWorld.ticks) { player.animator.animate(PICKPOCKET_ANIM) val lootTable = pickpocketRoll(player, pickpocketData.low, pickpocketData.high, pickpocketData.table) @@ -79,7 +79,9 @@ class ThievingListeners : InteractionListener { playHurtAudio(player, 20) - stun(player, pickpocketData.stunTime) + //stun(player, pickpocketData.stunTime) + stun(player, 0) + setAttribute(player, "pickpockettick", GameWorld.ticks + pickpocketData.stunTime) player.impactHandler.manualHit(node.asNpc(),RandomFunction.random(pickpocketData.stunDamageMin,pickpocketData.stunDamageMax),ImpactHandler.HitsplatType.NORMAL) @@ -87,6 +89,7 @@ class ThievingListeners : InteractionListener { } else { playAudio(player, Sounds.PICK_2581) //player.lock(2) + setAttribute(player, "pickpockettick", GameWorld.ticks + 2) lootTable.forEach { player.inventory.add(it) } player.skills.addExperience(Skills.THIEVING,pickpocketData.experience) } From 5319cabdae527cd96b3cca3a31845d81459ed047 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 12:59:35 -0700 Subject: [PATCH 131/306] Selecting "make 10 bars" in the smelting interface will now make 30, allowing a full inventory --- .../main/content/global/handlers/iface/SmeltingInterface.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/handlers/iface/SmeltingInterface.java b/Server/src/main/content/global/handlers/iface/SmeltingInterface.java index 4032ff524..b7fadd28c 100644 --- a/Server/src/main/content/global/handlers/iface/SmeltingInterface.java +++ b/Server/src/main/content/global/handlers/iface/SmeltingInterface.java @@ -49,7 +49,7 @@ public class SmeltingInterface extends ComponentPlugin { * @author 'Vexia */ public enum BarButton { - BRONZE_1(16, Bar.BRONZE, 1), BRONZE_5(15, Bar.BRONZE, 5), BRONZE_10(14, Bar.BRONZE, 10), BRONZE_X(13, Bar.BRONZE, -1), BLURITE_1(20, Bar.BLURITE, 1), BLURITE_5(19, Bar.BLURITE, 5), BLURITE_10(18, Bar.BLURITE, 10), BLURITE_X(17, Bar.BLURITE, -1), IRON_1(24, Bar.IRON, 1), IRON_5(23, Bar.IRON, 5), IRON_10(22, Bar.IRON, 10), IRON_X(21, Bar.IRON, -1), SILVER_1(28, Bar.SILVER, 1), SILVER_5(27, Bar.SILVER, 5), SILVER_10(26, Bar.SILVER, 10), SILVER_X(25, Bar.SILVER, -1), STEEL_1(32, Bar.STEEL, 1), STEEL_5(31, Bar.STEEL, 5), STEEL_10(30, Bar.STEEL, 10), STEEL_X(29, Bar.STEEL, -1), GOLD_1(36, Bar.GOLD, 1), GOLD_5(35, Bar.GOLD, 5), GOLD_10(34, Bar.GOLD, 10), GOLD_X(33, Bar.GOLD, -1), MITHRIL_1(40, Bar.MITHRIL, 1), MITHRIL_5(39, Bar.MITHRIL, 5), MITHRIL_10(38, Bar.MITHRIL, 10), MITHRIL_X(37, Bar.MITHRIL, -1), ADAMANT_1(44, Bar.ADAMANT, 1), ADAMANT_5(43, Bar.ADAMANT, 5), ADAMANT_10(42, Bar.ADAMANT, 10), ADAMANT_X(41, Bar.ADAMANT, -1), RUNE_1(48, Bar.RUNITE, 1), RUNE_5(47, Bar.RUNITE, 5), RUNE_10(46, Bar.RUNITE, 10), RUNE_X(45, Bar.RUNITE, -1); + BRONZE_1(16, Bar.BRONZE, 1), BRONZE_5(15, Bar.BRONZE, 5), BRONZE_10(14, Bar.BRONZE, 30), BRONZE_X(13, Bar.BRONZE, -1), BLURITE_1(20, Bar.BLURITE, 1), BLURITE_5(19, Bar.BLURITE, 5), BLURITE_10(18, Bar.BLURITE, 30), BLURITE_X(17, Bar.BLURITE, -1), IRON_1(24, Bar.IRON, 1), IRON_5(23, Bar.IRON, 5), IRON_10(22, Bar.IRON, 30), IRON_X(21, Bar.IRON, -1), SILVER_1(28, Bar.SILVER, 1), SILVER_5(27, Bar.SILVER, 5), SILVER_10(26, Bar.SILVER, 30), SILVER_X(25, Bar.SILVER, -1), STEEL_1(32, Bar.STEEL, 1), STEEL_5(31, Bar.STEEL, 5), STEEL_10(30, Bar.STEEL, 30), STEEL_X(29, Bar.STEEL, -1), GOLD_1(36, Bar.GOLD, 1), GOLD_5(35, Bar.GOLD, 5), GOLD_10(34, Bar.GOLD, 30), GOLD_X(33, Bar.GOLD, -1), MITHRIL_1(40, Bar.MITHRIL, 1), MITHRIL_5(39, Bar.MITHRIL, 5), MITHRIL_10(38, Bar.MITHRIL, 30), MITHRIL_X(37, Bar.MITHRIL, -1), ADAMANT_1(44, Bar.ADAMANT, 1), ADAMANT_5(43, Bar.ADAMANT, 5), ADAMANT_10(42, Bar.ADAMANT, 30), ADAMANT_X(41, Bar.ADAMANT, -1), RUNE_1(48, Bar.RUNITE, 1), RUNE_5(47, Bar.RUNITE, 5), RUNE_10(46, Bar.RUNITE, 30), RUNE_X(45, Bar.RUNITE, -1); /** * Constructs a new {@code BarButton} {@code Object}. From a86b734e0dac8363d7dec14999fb63daf9700bb8 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 13:04:51 -0700 Subject: [PATCH 132/306] Replaced "Make 10" with "Make 30" for crafting interfaces that use the chat dialogue The client will still display 10, but the action will repeat 30 times. --- .../main/core/game/dialogue/SkillDialogueHandler.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Server/src/main/core/game/dialogue/SkillDialogueHandler.kt b/Server/src/main/core/game/dialogue/SkillDialogueHandler.kt index 58e692b23..ada3a4232 100644 --- a/Server/src/main/core/game/dialogue/SkillDialogueHandler.kt +++ b/Server/src/main/core/game/dialogue/SkillDialogueHandler.kt @@ -154,8 +154,8 @@ open class SkillDialogueHandler( // "Make 5 sets" Option 3 -> 5 // "Make 10 sets" Option - 2 -> 10 - else -> 10 + 2 -> 30 + else -> 30 } } }, @@ -182,7 +182,7 @@ open class SkillDialogueHandler( when (buttonId) { 6, 10 -> return 1 5, 9 -> return 5 - 4, 8 -> return 10 + 4, 8 -> return 30 3, 7 -> return -1 } return 1 @@ -211,7 +211,7 @@ open class SkillDialogueHandler( when (buttonId) { 7, 11, 15 -> return 1 6, 10, 14 -> return 5 - 5, 9, 13 -> return 10 + 5, 9, 13 -> return 30 4, 8, 12 -> return -1 } return 1 @@ -241,7 +241,7 @@ open class SkillDialogueHandler( when (buttonId) { 8, 12, 16, 20 -> return 1 7, 11, 15, 19 -> return 5 - 6, 10, 14, 18 -> return 10 + 6, 10, 14, 18 -> return 30 5, 9, 13, 17 -> return -1 } return 1 @@ -278,7 +278,7 @@ open class SkillDialogueHandler( when (buttonId) { 9, 13, 17, 21, 25 -> return 1 8, 12, 16, 20, 24 -> return 5 - 7, 11, 15, 19, 23 -> return 10 + 7, 11, 15, 19, 23 -> return 30 6, 10, 14, 18, 22 -> return -1 } return 1 From 9ed560cca674ad87f6b3a33d1d1c6c402a1f31db Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 14:16:39 -0700 Subject: [PATCH 133/306] Can now fletch arrow shafts from higher tier logs, getting more arrowshafts in return This uses the same exp, level requirements, and arrowshaft output as Old School Runescape. --- .../global/skill/fletching/Fletching.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/global/skill/fletching/Fletching.java b/Server/src/main/content/global/skill/fletching/Fletching.java index de5a99e65..bc2b49f79 100644 --- a/Server/src/main/content/global/skill/fletching/Fletching.java +++ b/Server/src/main/content/global/skill/fletching/Fletching.java @@ -265,13 +265,13 @@ public class Fletching { } } private enum Items{ - STANDARD(1511,FletchingItems.ARROW_SHAFT, FletchingItems.SHORT_BOW, FletchingItems.LONG_BOW, FletchingItems.WOODEN_STOCK), + STANDARD(1511, FletchingItems.ARROW_SHAFT, FletchingItems.SHORT_BOW, FletchingItems.LONG_BOW, FletchingItems.WOODEN_STOCK), ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT), - OAK(1521, FletchingItems.OAK_SHORTBOW, FletchingItems.OAK_LONGBOW, FletchingItems.OAK_STOCK), - WILLOW(1519, FletchingItems.WILLOW_SHORTBOW, FletchingItems.WILLOW_LONGBOW, FletchingItems.WILLOW_STOCK), - MAPLE(1517, FletchingItems.MAPLE_SHORTOW, FletchingItems.MAPLE_LONGBOW, FletchingItems.MAPLE_STOCK), - YEW(1515, FletchingItems.YEW_SHORTBOW, FletchingItems.YEW_LONGBOW, FletchingItems.YEW_STOCK), - MAGIC(1513, FletchingItems.MAGIC_SHORTBOW, FletchingItems.MAGIC_LONGBOW), + OAK(1521, FletchingItems.OAK_ARROW_SHAFT, FletchingItems.OAK_SHORTBOW, FletchingItems.OAK_LONGBOW, FletchingItems.OAK_STOCK), + WILLOW(1519, FletchingItems.WILLOW_ARROW_SHAFT, FletchingItems.WILLOW_SHORTBOW, FletchingItems.WILLOW_LONGBOW, FletchingItems.WILLOW_STOCK), + MAPLE(1517, FletchingItems.MAPLE_ARROW_SHAFT, FletchingItems.MAPLE_SHORTOW, FletchingItems.MAPLE_LONGBOW, FletchingItems.MAPLE_STOCK), + YEW(1515, FletchingItems.YEW_ARROW_SHAFT, FletchingItems.YEW_SHORTBOW, FletchingItems.YEW_LONGBOW, FletchingItems.YEW_STOCK), + MAGIC(1513, FletchingItems.MAGIC_ARROW_SHAFT, FletchingItems.MAGIC_SHORTBOW, FletchingItems.MAGIC_LONGBOW), TEAK(6333, FletchingItems.TEAK_STOCK), MAHOGANY(6332, FletchingItems.MAHOGANY_STOCK); @@ -306,26 +306,31 @@ public class Fletching { OGRE_ARROW_SHAFT(2864, 6.4, 5, 4), //Oak logs + OAK_ARROW_SHAFT(52, 10, 15, 30), OAK_SHORTBOW(54, 16.5, 20, 1), OAK_LONGBOW(56,25,25,1), OAK_STOCK(9442, 16, 24, 1), //Willow logs + WILLOW_ARROW_SHAFT(52, 15, 30, 45), WILLOW_SHORTBOW(60, 33.3, 35, 1), WILLOW_LONGBOW(58, 41.5, 40, 1), WILLOW_STOCK(9444, 22, 39, 1), //Maple logs + MAPLE_ARROW_SHAFT(52, 20, 45, 60), MAPLE_SHORTOW(64, 50, 50, 1), MAPLE_LONGBOW(62, 58.3, 55, 1), MAPLE_STOCK(9448, 32, 54, 1), //Yew logs + YEW_ARROW_SHAFT(52, 25, 60, 75), YEW_SHORTBOW(68, 67.5, 65, 1), YEW_LONGBOW(66, 75, 70, 1), YEW_STOCK(9452, 50, 69, 1), //Magic logs + MAGIC_ARROW_SHAFT(52, 30, 75, 90), MAGIC_SHORTBOW(72, 83.3, 80,1), MAGIC_LONGBOW(70, 91.5, 85, 1), From eebcb2527412dcfe30e1e6d65f1fd6a5b8a782f6 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 14:18:44 -0700 Subject: [PATCH 134/306] Updated fletching message to include the new arrowshaft quantities --- .../content/global/skill/fletching/FletchingPulse.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Server/src/main/content/global/skill/fletching/FletchingPulse.java b/Server/src/main/content/global/skill/fletching/FletchingPulse.java index 9c7d0d638..dbc18af9f 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingPulse.java +++ b/Server/src/main/content/global/skill/fletching/FletchingPulse.java @@ -110,6 +110,16 @@ public final class FletchingPulse extends SkillPulse { switch (fletch) { case ARROW_SHAFT: return "You carefully cut the wood into 15 arrow shafts."; + case OAK_ARROW_SHAFT: + return "You carefully cut the wood into 30 arrow shafts."; + case WILLOW_ARROW_SHAFT: + return "You carefully cut the wood into 45 arrow shafts."; + case MAPLE_ARROW_SHAFT: + return "You carefully cut the wood into 60 arrow shafts."; + case YEW_ARROW_SHAFT: + return "You carefully cut the wood into 75 arrow shafts."; + case MAGIC_ARROW_SHAFT: + return "You carefully cut the wood into 90 arrow shafts."; default: return "You carefully cut the wood into " + (StringUtils.isPlusN(fletch.getItem().getName()) ? "an" : "a") + " " + fletch.getItem().getName().replace("(u)", "").trim() + "."; } From b33ad22740a18b4f66e9ca2e5a52b9e66e2c1327 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Nov 2024 17:16:20 -0700 Subject: [PATCH 135/306] Removing Jarvald reference to NPC Constlib, since I have no idea how to update that The original change (https://gitlab.com/2009scape/2009scape/-/commit/fb2535e248926fdc2a21f3a633e3c5e291e20520?merge_request_iid=1911) Says it requires a constlib update. From what I can tell, that is made here: https://gitlab.com/2009scape/tools/rs09-constants-library. However, I have no idea how to actually get a new build of this. Perhaps the server files will be updated to include this in the future, but in the meantime I am changing this back so the server actually starts. --- .../region/fremennik/rellekka/dialogue/JarvaldDialogue.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt index cdf685e13..0079c1b14 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt @@ -200,6 +200,6 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun getIds(): IntArray { - return intArrayOf(NPCs.JARVALD_2435, NPCs.JARVALD_2436, NPCs.JARVALD_2437, NPCs.JARVALD_2438) + return intArrayOf(2435, NPCs.JARVALD_2436, NPCs.JARVALD_2437, NPCs.JARVALD_2438) } } From 440f8ce3acba7fb3d20a148772b7e9186a0c752f Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 20 Nov 2024 19:21:17 -0700 Subject: [PATCH 136/306] Corrected default exp rate Changing the default exp rate to anything other than 5.0 causes the new rate to override the player's selection at tutorial island. I lowered the default just to reduce the amount of exp you gain during tutorial island, but with the new scaling exp rate that's no longer required. --- Server/worldprops/default.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index fd25dd94c..37ca25c6c 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -58,7 +58,8 @@ members = true #activity as displayed on the world list activity = "SnowScape" pvp = false -default_xp_rate = 1.0 +#any default_xp_rate other than 5.0 will override player selection +default_xp_rate = 5.0 allow_slayer_reroll = false #enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already. enable_default_clan = true From 6cca2d1beda6b1fcbab6100ca0f095e766fa0001 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 20 Nov 2024 19:33:24 -0700 Subject: [PATCH 137/306] Allow trading any item Attempting to trade an untradeable item will give a warning message, but the trade will still be allowed to go through. --- .../entity/player/link/request/trade/TradeContainer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java index c58521aab..86abca19e 100644 --- a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java +++ b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java @@ -49,8 +49,9 @@ public final class TradeContainer extends Container { return; } if (!tradeable(item) && !GameWorld.getSettings().isDevMode()) { - player.getPacketDispatch().sendMessage("You can't trade this item."); - return; + player.getPacketDispatch().sendMessage("This item is not normally tradeable. Be careful not to break any quests!"); + //player.getPacketDispatch().sendMessage("You can't trade this item."); + //return; } Item remove = new Item(item.getId(), amount); remove.setAmount(stabalizeAmount(remove, amount, player.getInventory())); From 6ed0ead8a7ef6329699f1fa12a8ad28d9b7e4ddc Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 20 Nov 2024 19:39:50 -0700 Subject: [PATCH 138/306] Removed door dialogue in the stronghold of security No need to explain how to secure your account over and over, we aren't kids. --- .../barbvillage/stronghold/StrongHoldSecurityPlugin.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/content/region/misthalin/barbvillage/stronghold/StrongHoldSecurityPlugin.java b/Server/src/main/content/region/misthalin/barbvillage/stronghold/StrongHoldSecurityPlugin.java index c6de2b356..2845b5e49 100644 --- a/Server/src/main/content/region/misthalin/barbvillage/stronghold/StrongHoldSecurityPlugin.java +++ b/Server/src/main/content/region/misthalin/barbvillage/stronghold/StrongHoldSecurityPlugin.java @@ -223,12 +223,16 @@ public final class StrongHoldSecurityPlugin extends MapZone implements Plugin Date: Thu, 21 Nov 2024 17:10:08 -0700 Subject: [PATCH 139/306] Added small summoning exp gain every minute a familiar is summoned The gain is the summoning level required + 10. --- .../content/global/skill/summoning/familiar/Familiar.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java index 4177e1d5c..064de882c 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java +++ b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java @@ -225,10 +225,14 @@ public abstract class Familiar extends NPC implements Plugin { @Override public void handleTickActions() { - //Snowscape: only count down the familiar timer if summoning points are zero + //Snowscape: only count down the familiar timer if summoning points are zero, and give some summoning exp every minute a familiar is summoned. if (owner.getSkills().getLevel(Skills.SUMMONING) == 0) { ticks--; } + if (getWorldTicks() % 100 == 0) { + owner.getSkills().addExperience(Skills.SUMMONING, pouch.getLevelRequired()+10, true); + } + fracDrain += pointsPerTick; if (fracDrain > 1.0 && ticks > 0) { fracDrain -= 1.0; From 3119a01e3fb4d5733a3ed05341eef3b86e535f51 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 21 Nov 2024 17:44:13 -0700 Subject: [PATCH 140/306] Additional steps to remove random events The random events came back for some characters, seems the timer got started somehow. This change should pause the timer every time it's registered, so it should never start again. --- Server/src/main/core/game/system/timer/impl/AntiMacro.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt index ab3c18394..8968827b7 100644 --- a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt +++ b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt @@ -41,7 +41,8 @@ class AntiMacro : PersistTimer(0, "antimacro", isAuto = true), Commands { override fun onRegister(entity: Entity) { if (entity !is Player || entity.isArtificial) entity.timers.removeTimer(this) - if (entity is Player && entity.rights == Rights.ADMINISTRATOR) + //if (entity is Player && entity.rights == Rights.ADMINISTRATOR) + if (entity is Player) paused = true if (runInterval == 0) From 7749e8263f513cf3e46e12c3b67b2d5a426aa22c Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Fri, 22 Nov 2024 06:59:42 +0000 Subject: [PATCH 141/306] Introduced new dialogue engine compatible with spinoff revision 578 project --- Server/data/configs/npc_spawns.json | 4 + .../lumbridge/dialogue/DonieDialogue.java | 129 --------- .../lumbridge/dialogue/DonieDialogue.kt | 53 ++++ .../core/game/dialogue/DialogueLabeller.kt | 251 ++++++++++++++++++ 4 files changed, 308 insertions(+), 129 deletions(-) delete mode 100644 Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.java create mode 100644 Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt create mode 100644 Server/src/main/core/game/dialogue/DialogueLabeller.kt diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 25a67f84e..bdc23b4cc 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -5055,6 +5055,10 @@ "npc_id": "2237", "loc_data": "{3249,3266,0,1,5}-" }, + { + "npc_id": "2238", + "loc_data": "{3219,3247,0,1,6}-" + }, { "npc_id": "2240", "loc_data": "{3077,3259,0,1,4}-" diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.java b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.java deleted file mode 100644 index dbe66ddbf..000000000 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.java +++ /dev/null @@ -1,129 +0,0 @@ -package content.region.misthalin.lumbridge.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.game.world.GameWorld; - -/** - * Represents the dialogue plugin used for the donie npc. - * @author 'Vexia - * @version 1.00 - */ -@Initializable -public final class DonieDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code DonieDialogue} {@code Object}. - */ - public DonieDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code DonieDialogue} {@code Object}. - * @param player the player. - */ - public DonieDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new DonieDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hello there, can I help you?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Select an Option", "Where am I?", "How are you today?", "Your shoe lace is untied."); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Where am I?"); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How are you today?"); - stage = 20; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Your shoe lace is untied."); - stage = 30; - break; - } - break; - case 10: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "This is the town of Lumbridge my friend."); - stage = 11; - break; - case 11: - interpreter.sendOptions("Select an Option", "Where am I?", "How are you today?", "Your shoe lace is untied."); - stage = 1; - break; - case 20: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Aye, not too bad thank you. Lovely weather in", "" + GameWorld.getSettings().getName() + " this fine day."); - stage = 21; - break; - case 21: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Weather?"); - stage = 22; - break; - case 22: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Yes weather, you know."); - stage = 23; - break; - case 23: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "The state or condition of the atmosphere at a time and", "place, with respect to variables such as temperature,", "moisture, wind velocity, and barometric pressure."); - stage = 24; - break; - case 24: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "..."); - stage = 25; - break; - case 25: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Not just a pretty face eh? Ha ha ha."); - stage = 26; - break; - case 26: - end(); - break; - case 30: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "No it's not!"); - stage = 31; - break; - case 31: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No you're right. I have nothing to back that up."); - stage = 32; - break; - case 32: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Fool! Leave me alone!"); - stage = 33; - break; - case 33: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 2238 }; - } -} diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt new file mode 100644 index 000000000..7626499b9 --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt @@ -0,0 +1,53 @@ +package content.region.misthalin.lumbridge.dialogue + +import core.api.* +import core.game.dialogue.* +import core.game.node.entity.player.Player +import core.game.world.GameWorld +import core.game.world.GameWorld.settings +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class DonieDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return DonieDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, DonieDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.DONIE_2238) + } +} + +class DonieDialogueFile : DialogueLabeller() { + override fun addConversation() { + assignToIds(NPCs.DONIE_2238) + + npc(ChatAnim.FRIENDLY, "Hello there, can I help you?") + options( + DialogueOption("whereami", "Where am I?", expression = ChatAnim.THINKING), + DialogueOption("howareyou", "How are you today?"), + DialogueOption("shoelace", "Your shoe lace is untied."), + ) + + label("whereami") + npc("This is the town of Lumbridge my friend.") + + label("howareyou") + npc("Aye, not too bad thank you. Lovely weather in", ""+ (GameWorld.settings?.name ?: "2009Scape") +" this fine day.") + player("Weather?") + npc("Yes weather, you know.") + npc("The state or condition of the atmosphere at a time and", "place, with respect to variables such as temperature,", "moisture, wind velocity, and barometric pressure.") + player("...") + npc("Not just a pretty face eh? Ha ha ha.") + + label("shoelace") + npc(ChatAnim.ANGRY, "No it's not!") + player("No you're right. I have nothing to back that up.") + npc(ChatAnim.ANGRY, "Fool! Leave me alone!") + + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/dialogue/DialogueLabeller.kt b/Server/src/main/core/game/dialogue/DialogueLabeller.kt new file mode 100644 index 000000000..b36c5ccae --- /dev/null +++ b/Server/src/main/core/game/dialogue/DialogueLabeller.kt @@ -0,0 +1,251 @@ +package core.game.dialogue + +import core.api.InputType +import core.api.face +import core.api.splitLines +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item + +/** Alias FacialExpression to ChatAnim for compatibility. */ +typealias ChatAnim = FacialExpression +/** Alias InputType to InputType for compatibility. */ +typealias InputType = InputType +/** Create container class DialogueOption for [DialogueLabeller.options] */ +class DialogueOption( + val goto: String, + val option: String, + val spokenText: String = option, + val expression: ChatAnim = ChatAnim.NEUTRAL, + val skipPlayer: Boolean = false, + val callback: ((player: Player, npc: NPC) -> Boolean)? = null +) + +/** + * DialogueLabeller is another way to organize a dialogue file. + * It shares the same dialogue layout as another project for portability. + * - Uses [stage] is for the current loop and [super.stage] as the "next" stage + * - Have [dialogueCounter] assign stages and guards for each option/player/npc dialogue + * - Assign [exec] and [goto] the same [dialogueCounter] to execute all in one pass + * - Save [label] to a HashMap to refer to when using [goto] + * - Loops again when a [goto] is encountered, ends when no [stageHit] during a stage + * + * ! WARNING: DO NOT use functions in DialogueFile as it will cause unexpected behavior. + * + * Example: [content.region.misthalin.lumbridge.dialogue.RangedTutorDialogue] + */ +abstract class DialogueLabeller : DialogueFile() { + + companion object { + /** + * Makes NPC stop in its tracks and look at player. + * An alternative to setting up DialoguePlugin(player) to be used in InteractionListener. + */ + fun captureNPC(player: Player, npc: NPC) { + face(npc, player.location) + npc.setDialoguePlayer(player) // This prevents random walking in [NPC.java handleTickActions()] + npc.getWalkingQueue().reset() + npc.getPulseManager().clear() + } + } + + /** Maps labels to stage numbers, to make jumps. */ + val labelStageMap = HashMap () + /** Assigns the number to each dialogue line. */ + var dialogueCounter = 0 + /** Set [stage] to start off (1 when there is an initial label). */ + var startingStage: Int? = null + /** Keeps the current stage for the whole cycle. */ + override var stage = -1 + /** Assigns the number to each stage. */ + var stageHit = false + /** Jump to next stage number when hitting a goto. */ + var jumpTo: Int? = null + /** ButtonID on every click */ + var buttonID: Int? = null + /** ButtonID when user clicks on an option */ + var optButton: Int? = null + /** Input value after a user enters a value */ + var optInput: Any? = null + + /** Implement this function instead of overriding handle. */ + abstract fun addConversation() + + /** Helper function to create an individual stage for each of the dialogue stages. */ + private fun assignIndividualStage(callback: () -> Unit) { + if (startingStage == null) { startingStage = 0 } + if (stage == dialogueCounter) { // Run this stage when the stage equals to the dialogueCounter of this dialogue + callback() // CALLBACK FUNCTION + super.stage++ // Increment the stage to the next stage (only applies after a pass) + stageHit = true // Flag that the stage was hit, so that it doesn't close the dialogue + } + dialogueCounter++ // Increment the dialogueCounter to assign each line of dialogue + } + + /** Formats a vararg messages or falls back to message to an array for spread function. */ + private fun formatMessages(messages: Array?, message: String = ""): Array { + return if (messages == null || messages.isEmpty()) { + splitLines(message) + } else if (messages.size > 1) { + messages + } else { + splitLines(messages[0]) // A single line message is similar to a splitLine returning 1 line. + } + } + + /** Does absolutely nothing but to make it look like the other API. */ + fun assignToIds(npcid: Int) { /* super.npc = NPC(npcid) */ } + + /** Marks the start of a series of dialogue that can be jumped to using a [goto]. */ + fun label(label: String) { + if (startingStage == null) { startingStage = 1 } + dialogueCounter++ + labelStageMap[label] = dialogueCounter + } + + /** Jumps to a [label] after a series of dialogue. */ + fun goto(label: String) { + if (stage == dialogueCounter) { + jumpTo = labelStageMap[label] + } + } + + /** Jumps to a [label] inside an [exec]. */ + fun loadLabel(player: Player, label: String) { + goto(label) + } + + /** + * Executes the callback between stages and can be used for branching with [loadLabel]. + * You can chain as many exec as you like since they read sequentially. + * You can also read [options] and [input] values here via [optButton] and [optInput]. + */ + fun exec(callback: (player: Player, npc: NPC) -> Unit) { + if (startingStage == null) { startingStage = 0 } + if (stage == dialogueCounter) { + callback(player!!, npc!!) + } + } + + /** Dialogue player/playerl. Shows player chathead with text. **/ + fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { + assignIndividualStage { interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) } + } + /** Dialogue player/playerl. Shows player chathead with text. **/ + fun player(vararg messages: String) { player(ChatAnim.NEUTRAL, *messages) } + @Deprecated("Use player() instead.", ReplaceWith("player(chatAnim, *messages)")) + fun playerl(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use player() instead.") } + @Deprecated("Use player() instead.", ReplaceWith("player(*messages)")) + fun playerl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use player() instead.") } + + /** Dialogue npc/npcl. Shows npc chathead with text. **/ + fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { + assignIndividualStage { interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) } + } + /** Dialogue npc/npcl. Shows npcId chathead with text. **/ + fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int, vararg messages: String) { + assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) } + } + /** Dialogue npc/npcl. Shows npc chathead with text. **/ + fun npc(vararg messages: String) { npc(ChatAnim.NEUTRAL, *messages) } + @Deprecated("Use npc() instead.", ReplaceWith("npc(chatAnim, *messages)")) + fun npcl(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use npc() instead.") } + @Deprecated("Use npc() instead.", ReplaceWith("npc(*messages)")) + fun npcl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use npc() instead.") } + + /** Dialogue item/iteml. Shows item with text. **/ + fun item(item: Item, vararg messages: String, message: String = "") { + assignIndividualStage { interpreter!!.sendItemMessage(item, *formatMessages(messages, message)) } + } + @Deprecated("Use item() instead.", ReplaceWith("item(item, *messages)")) + fun iteml(item: Item, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use item() instead.") } + + /** Dialogue overloaded doubleItem/doubleIteml. Shows two items with text. **/ + fun item(item: Item, item2: Item, vararg messages: String, message: String = "") { + assignIndividualStage { interpreter!!.sendDoubleItemMessage(item, item2, formatMessages(messages, message).joinToString(" ")) } + } + + /** Dialogue line/linel. Simply shows text. **/ + fun line(vararg messages: String) { + assignIndividualStage { interpreter!!.sendDialogue(*messages) } + } + @Deprecated("Use line() instead.", ReplaceWith("line(*messages)")) + fun linel(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use line() instead.") } + + /** Dialogue option. Shows the option dialogue with choices for the user to select. **/ + fun options(vararg options: DialogueOption, title: String = "Select an Option") { + // Filter out options that aren't shown. + val filteredOptions = options.filter{ if (it.callback != null) { it.callback.invoke(player!!, npc!!) } else { true } } + // Stage Part 1: Options List Dialogue + assignIndividualStage { interpreter!!.sendOptions(title, *filteredOptions.map{ it.option }.toTypedArray()) } + // Stage Part 2: Show spoken text. + var opt = if (buttonID != null && buttonID in 1..filteredOptions.size) { filteredOptions[buttonID!! - 1] } else { null } + assignIndividualStage { + if (opt?.skipPlayer == true) { + jumpTo = stage + 1 + } else { + interpreter!!.sendDialogues(player, opt?.expression ?: ChatAnim.NEUTRAL, *(splitLines(opt?.spokenText ?: " "))) + } + optButton = buttonID // transfer the buttonID to a temp memory for the next stage + } + // Stage Part 3: Jump To goto + if (stage == dialogueCounter && optButton != null && optButton in 1..filteredOptions.size) { + jumpTo = labelStageMap[filteredOptions[optButton!! - 1].goto] + } + dialogueCounter++ + } + @Deprecated("Use options(DialogueOption()) and not options(string).", ReplaceWith("options(DialogueOption(options))")) + override fun options(vararg options: String?, title: String) { throw Exception("Deprecated DialogueLabel: Use options(DialogueOption()) and not options(string).") } + + /** Dialogue input. Shows the input dialogue with an input box for the user to type in. Read [optInput] for the value. **/ + fun input(type: InputType, prompt: String = "Enter the amount") { + assignIndividualStage { + // These are similar to calling sendInputDialogue + when (type) { + InputType.AMOUNT -> interpreter!!.sendInput(true, prompt) + InputType.NUMERIC -> interpreter!!.sendInput(false, prompt) + InputType.STRING_SHORT -> interpreter!!.sendInput(true, prompt) // Only 12 letters + InputType.STRING_LONG -> interpreter!!.sendLongInput(prompt) // Very long text, can overflow. + InputType.MESSAGE -> interpreter!!.sendMessageInput(prompt) + } + if (type == InputType.AMOUNT) { + player!!.setAttribute("parseamount", true) + } + player!!.setAttribute("runscript") { value: Any -> + optInput = value + // The next line is a hack. Because this prompt is overlays the actual chatbox, we trigger the next dialogue with a call to handle. + interpreter!!.handle(player!!.interfaceManager.chatbox.id, 2) + } + player!!.setAttribute("input-type", type) + } + } + /** Dialogue input. Shows the input dialogue with an input box for the user to type in. Read [optInput] in an [exec] function for the value. **/ + fun input(numeric: Boolean, prompt: String = "Enter the amount") { input( if (numeric) { InputType.NUMERIC } else { InputType.STRING_SHORT }, prompt) } + + /** Hook onto the handle function of DialogueFile. This function gets called every loop with a super.stage. */ + override fun handle(componentID: Int, buttonID: Int) { + this.buttonID = buttonID + startingStage = null + /** This -1 stage is to read labels into a hashmap and to find the starting stage. */ + if (stage == -1) { + dialogueCounter = 0 + addConversation() // Force all labels to be recorded into hashmap. + super.stage = startingStage ?: 0 + } + for (i in 0..10) { // Limit to 10 jumpTo PER DIALOGUE LINE to prevent infinite looping/ping-ponging jumps. + if (jumpTo != null) { // If jumpTo is set, set the super.stage stage as the new jumpTo stage. + super.stage = jumpTo as Int + jumpTo = null + } + stageHit = false + stage = super.stage // [stage] is for the current loop. [super.stage] is treated as the "next" stage. + dialogueCounter = 0 + addConversation() // MAIN CALLBACK FUNCTION + // If there is no jumpTo set, or jumpTo is set to the same stage as this(infinite loop), exit. + if (jumpTo == null || jumpTo == stage) { + break + } + } + if (!stageHit) { end() } // If a dialogue stage is not hit, end the dialogues. + } +} \ No newline at end of file From f258632fb52d3cf8f4c52e68a437f0fddf61605c Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 24 Nov 2024 20:21:34 -0700 Subject: [PATCH 142/306] Farming produce is automatically noted if wearing an amulet of farming or amulet of nature Since the leprechaun is right there and can do the same function, this just saves the annoying clicking of harvesting and using the produce on the leprechaun over and over. Note that the other functions of the amulet of farming or amulet of nature are not implemented yet. --- .../content/global/skill/farming/CropHarvester.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/farming/CropHarvester.kt b/Server/src/main/content/global/skill/farming/CropHarvester.kt index f5fda6108..43d1ee70c 100644 --- a/Server/src/main/content/global/skill/farming/CropHarvester.kt +++ b/Server/src/main/content/global/skill/farming/CropHarvester.kt @@ -82,9 +82,17 @@ class CropHarvester : OptionHandler() { sendMessage(player, "You lack the needed tool to harvest these crops.") return true } + val necklace = getItemFromEquipment(player, EquipmentSlot.NECK) + var amulet = false + if (necklace != null && (necklace.name.lowercase().contains("amulet of farming") || necklace.name.lowercase().contains("amulet of nature"))) { + amulet = true + } val sendHarvestMessages = if (fPatch.type == PatchType.FLOWER_PATCH) false else true if (sendHarvestMessages && firstHarvest) { sendMessage(player, "You begin to harvest the $patchName.") + if (amulet) { + sendMessage(player, "The leprechaun exchanges your produce for banknotes.") + } firstHarvest = false } animate(player, anim) @@ -92,7 +100,11 @@ class CropHarvester : OptionHandler() { // TODO: If a flower patch is being harvested, delay the clearing of the // patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75 delay = 2 - addItem(player, reward.id) + if (amulet) { + addItem(player, note(reward).id) + } else { + addItem(player, reward.id) + } rewardXP(player, Skills.FARMING, plantable.harvestXP) if (patch.patch.type in livesBased) { patch.rollLivesDecrement( From f3c9dd2d9c50a6389bc84d8cfba7b987fdf80a35 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 24 Nov 2024 21:07:42 -0700 Subject: [PATCH 143/306] Changed Low Alch spell into Note Spell Casting on an item will note all of the matching items in your inventory. 10% of the items (rounded down) are charged as a "tax" so that other remote deposit options are still competitive. --- .../skill/magic/modern/ModernListeners.kt | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index d56b8230b..6d356e205 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -102,7 +102,7 @@ class ModernListeners : SpellListener("modern"){ onCast(Modern.LOW_ALCHEMY, ITEM){ player, node -> val item = node?.asItem() ?: return@onCast requires(player,21, arrayOf(Item(Items.FIRE_RUNE_554,3),Item(Items.NATURE_RUNE_561))) - alchemize(player,item,high = false) + notespell(player,item) } onCast(Modern.HIGH_ALCHEMY, ITEM){ player, node -> @@ -214,7 +214,52 @@ class ModernListeners : SpellListener("modern"){ player.pulseManager.run(SmeltingPulse(player, item, bar, 1, true)) setDelay(player,false) } + + //Snowscape custom: Low Alch spell replaced with Note spell. This spell charges 10% of the items converted to notes as a tax. + public fun notespell(player: Player, item: Item) : Boolean { + if (item.definition.isUnnoted) { + if (item.definition.noteId < 0) { + player.sendMessage("This item cannot be noted.") + return false + } + val amount = player.inventory.getAmount(item.id) + player.inventory.remove(Item(item.id, amount)) + player.inventory.add(note(Item(item.id, kotlin.math.ceil(amount*0.9).toInt()))) + player.sendMessage("The Bank of Gielinor appreciates your business.") + } else { + player.sendMessage("This item is already noted!") + return false + /* Unnoting is too strong, allowing runecrafting to happen at breakneck speeds and allowing infinite food to be brought along. Leaving the code here in case we want to enable it again someday. + val startingamount = player.inventory.getAmount(item.id) + val freespace = player.inventory.freeSlots() + var amount = minOf(startingamount, freespace) + if (startingamount - amount == 1) amount++ + if (amount == 0) { + player.sendMessage("You do not have enough inventory space to unnote this item.") + return false + } + player.inventory.remove(Item(item.id, amount)) + player.inventory.add(unnote(Item(item.id, amount))) + */ + } + + val weapon = player.equipment.getItem(getItemFromEquipment(player, EquipmentSlot.WEAPON)) + if (weapon != null && !weapon.equals(MagicStaff.FIRE_RUNE)) { + player.animate(Animation(9625)) + player.graphics(Graphics(1692)) + } else { + player.animate(Animation(712)) + player.graphics(Graphics(112)) + } + playAudio(player,Sounds.LOW_ALCHEMY_98) + + removeRunes(player) + addXP(player, 31.0) + showMagicTab(player) + setDelay(player, 5) + return true + } fun alchemize(player: Player, item: Item, high: Boolean, explorersRing: Boolean = false): Boolean { if(item.name == "Coins") player.sendMessage("You can't alchemize something that's already gold!").also { return false } if((!item.definition.isTradeable) && (!item.definition.isAlchemizable)) player.sendMessage("You can't cast this spell on something like that.").also { return false } From 40196333ad8bf3ee8b41c3e1b680f1f44ef141a0 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 24 Nov 2024 21:52:06 -0700 Subject: [PATCH 144/306] Changes to Ava's devices from Animal Magnetism The devices no longer need to be worn, completing the quest is enough. Also standardized arrow break rates to exactly 20% at all levels. Ava's devices will pick up 100% of the arrows that don't break. --- .../core/game/node/entity/combat/RangeSwingHandler.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt index c0e20bf67..bd2aa0d37 100644 --- a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt @@ -345,7 +345,7 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) dropLocation = null } if (dropLocation != null && state.rangeWeapon.isDropAmmo) { - val rate = 5 * (1.0 + e.skills.getLevel(Skills.RANGE) * 0.01) * dropRate + val rate = 5 * dropRate if (RandomFunction.randomize(rate.toInt()) != 0) { val drop = GroundItemManager.increase(Item(ammo.id, amount), dropLocation, e) if (drop != null) { @@ -367,20 +367,23 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) */ private fun getDropRate(e: Entity?): Double { if (e is Player) { - val cape = e.equipment[EquipmentContainer.SLOT_CAPE] + //val cape = e.equipment[EquipmentContainer.SLOT_CAPE] val weapon = e.equipment[EquipmentContainer.SLOT_WEAPON] - if (cape != null && (cape.id == 10498 || cape.id == 10499) && weapon != null && weapon.id != 10034 && weapon.id != 10033) { + //if (cape != null && (cape.id == 10498 || cape.id == 10499) && weapon != null && weapon.id != 10034 && weapon.id != 10033) { + if (hasRequirement(e, "Animal Magnetism", false) && weapon != null && weapon.id != 10034 && weapon.id != 10033) { val rate = 80 if (RandomFunction.random(100) < rate) { + /* val torso = e.equipment[EquipmentContainer.SLOT_CHEST] val modelId = torso?.definition?.maleWornModelId1 ?: -1 if (modelId == 301 || modelId == 306 || modelId == 3379) { e.packetDispatch.sendMessage("Your armour interferes with Ava's device.") return 1.0 } + */ return (-1).toDouble() } - return 0.33 + return 0.0 } } return 1.0 From 6cc6a4c69c2ea8996dc16d378c19a8b3422235d3 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 5 Dec 2024 15:01:26 -0700 Subject: [PATCH 145/306] Fixing minecarts that lead to keldagrim. --- .../region/misc/keldagrim/handlers/KeldagrimPlugin.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimPlugin.kt b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimPlugin.kt index 24a7a333b..186343d26 100644 --- a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimPlugin.kt +++ b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimPlugin.kt @@ -46,6 +46,12 @@ class KeldagrimOptionHandlers : OptionHandler() { 28094 -> player.dialogueInterpreter.open(GETrapdoorDialogueID) } } + "ride" -> { + when(node.id){ + 7029 -> player.dialogueInterpreter.open(GETrapdoorDialogueID) + 7030 -> player.dialogueInterpreter.open(GETrapdoorDialogueID) + } + } "enter" -> { when(node.id){ 5014 -> player.properties.teleportLocation = Location.create(2730, 3713, 0) @@ -62,6 +68,8 @@ class KeldagrimOptionHandlers : OptionHandler() { SceneryDefinition.forId(9138).handlers["option:climb-up"] = this SceneryDefinition.forId(28094).handlers["option:open"] = this SceneryDefinition.forId(5014).handlers["option:enter"] = this + SceneryDefinition.forId(7029).handlers["option:ride"] = this + SceneryDefinition.forId(7030).handlers["option:ride"] = this return this } } From a788b64e44f884f94c30ad1181d655915b0192ec Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 5 Dec 2024 15:20:10 -0700 Subject: [PATCH 146/306] Added Burgh de Rott bank functionality --- .../content/global/handlers/scenery/SearchOptionPlugin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Server/src/main/content/global/handlers/scenery/SearchOptionPlugin.java b/Server/src/main/content/global/handlers/scenery/SearchOptionPlugin.java index 3b2144efb..4702587bb 100644 --- a/Server/src/main/content/global/handlers/scenery/SearchOptionPlugin.java +++ b/Server/src/main/content/global/handlers/scenery/SearchOptionPlugin.java @@ -8,6 +8,8 @@ import core.game.node.item.Item; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.*; + /** * Handles the search option. * @author 'Vexia @@ -80,6 +82,10 @@ public class SearchOptionPlugin extends OptionHandler { player.getInventory().add(new Item(946)); return true; } + if (node.getId() == 12799 && hasRequirement(player, "In Aid of the Myreque")) { + openBankAccount(player); + return true; + } player.getPacketDispatch().sendMessage("You search the " + node.getName().toLowerCase() + " but find nothing."); return true; } From be7143be206eb9246ad098bca0d6855d94e699f0 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 5 Dec 2024 15:53:31 -0700 Subject: [PATCH 147/306] Updated pickpocket to stop if health gets low If your health is low enough that you'll die if you get caught, then pickpocketing will stop repeating. --- .../main/content/global/skill/thieving/ThievingListeners.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt index 77a7f25dc..c01ef2e6c 100644 --- a/Server/src/main/content/global/skill/thieving/ThievingListeners.kt +++ b/Server/src/main/content/global/skill/thieving/ThievingListeners.kt @@ -95,7 +95,11 @@ class ThievingListeners : InteractionListener { } } //pickpocket again. - InteractionListeners.run(node.id, IntType.NPC,"Pickpocket",player,node) + if (player.skills.lifepoints > pickpocketData.stunDamageMax) { + InteractionListeners.run(node.id, IntType.NPC,"Pickpocket",player,node) + } else { + player.sendMessage("It's probably not a good idea to continue with your injuries.") + } return@on true } From ffe1e11d11cce3fb48e019e97327c8860f43a1ef Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 6 Dec 2024 08:05:40 -0700 Subject: [PATCH 148/306] Traps with a catch now last 10 minutes instead of 1 --- Server/src/main/content/global/skill/hunter/TrapSetting.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/hunter/TrapSetting.java b/Server/src/main/content/global/skill/hunter/TrapSetting.java index ec0f87ba3..421a982bf 100644 --- a/Server/src/main/content/global/skill/hunter/TrapSetting.java +++ b/Server/src/main/content/global/skill/hunter/TrapSetting.java @@ -306,7 +306,7 @@ public class TrapSetting { case 3: handleCatch(counter, wrapper, node, npc, success); if (success) { - wrapper.setTicks(GameWorld.getTicks() + 100); + wrapper.setTicks(GameWorld.getTicks() + 1000); wrapper.setReward(node); wrapper.setObject(getFinalId(wrapper, node)); switch(wrapper.getType()) { From ecb3a66d5877cf7a776c187c23375fa399ef3f7a Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 6 Dec 2024 09:13:09 -0700 Subject: [PATCH 149/306] Fishing with Hunter feathers and Note Spell changes Feathers earned with hunting can now be used for fly fishing. The note spell no longer charges a 10% tax, but is instead limited to noting 10 items at a time. --- .../main/content/global/skill/fishing/FishingOption.kt | 2 +- .../content/global/skill/magic/modern/ModernListeners.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/global/skill/fishing/FishingOption.kt b/Server/src/main/content/global/skill/fishing/FishingOption.kt index b75ccf9b4..5b304893c 100644 --- a/Server/src/main/content/global/skill/fishing/FishingOption.kt +++ b/Server/src/main/content/global/skill/fishing/FishingOption.kt @@ -11,7 +11,7 @@ enum class FishingOption(val tool: Int, val level: Int, val animation: Animation CRAYFISH_CAGE(Items.CRAYFISH_CAGE_13431, 1, Animation(10009), null, "cage", Fish.CRAYFISH), SMALL_NET(Items.SMALL_FISHING_NET_303, 1, Animation(621), null, "net", Fish.SHRIMP, Fish.ANCHOVIE), BAIT(Items.FISHING_ROD_307, 5, Animation(622), intArrayOf(Items.FISHING_BAIT_313), "bait", Fish.SARDINE, Fish.HERRING), - LURE(Items.FLY_FISHING_ROD_309, 20, Animation(622), intArrayOf(Items.FEATHER_314, Items.STRIPY_FEATHER_10087), "lure", Fish.TROUT, Fish.SALMON, Fish.RAINBOW_FISH), + LURE(Items.FLY_FISHING_ROD_309, 20, Animation(622), intArrayOf(Items.FEATHER_314, Items.STRIPY_FEATHER_10087, Items.RED_FEATHER_10088, Items.BLUE_FEATHER_10089, Items.YELLOW_FEATHER_10090, Items.ORANGE_FEATHER_10091), "lure", Fish.TROUT, Fish.SALMON, Fish.RAINBOW_FISH), PIKE_BAIT(Items.FISHING_ROD_307, 25, Animation(622), intArrayOf(Items.FISHING_BAIT_313), "bait", Fish.PIKE), LOBSTER_CAGE(Items.LOBSTER_POT_301, 40, Animation(619), null, "cage", Fish.LOBSTER), HARPOON(Items.HARPOON_311, 35, Animation(618), null, "harpoon", Fish.TUNA, Fish.SWORDFISH), diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 6d356e205..f05c616d9 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -215,17 +215,17 @@ class ModernListeners : SpellListener("modern"){ setDelay(player,false) } - //Snowscape custom: Low Alch spell replaced with Note spell. This spell charges 10% of the items converted to notes as a tax. + //Snowscape custom: Low Alch spell replaced with Note spell. This spell converts up to 10 items to notes. public fun notespell(player: Player, item: Item) : Boolean { if (item.definition.isUnnoted) { if (item.definition.noteId < 0) { player.sendMessage("This item cannot be noted.") return false } - val amount = player.inventory.getAmount(item.id) + val amount = kotlin.math.min(player.inventory.getAmount(item.id), 10) player.inventory.remove(Item(item.id, amount)) - player.inventory.add(note(Item(item.id, kotlin.math.ceil(amount*0.9).toInt()))) - player.sendMessage("The Bank of Gielinor appreciates your business.") + player.inventory.add(note(Item(item.id, amount))) + //player.sendMessage("The Bank of Gielinor appreciates your business.") } else { player.sendMessage("This item is already noted!") return false From 05c1ac1dc0d6130d94024eca493e953def009281 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 7 Dec 2024 19:36:12 -0700 Subject: [PATCH 150/306] Added runecrafting exp when crafting altar teleport tablets --- .../main/content/global/skill/runecrafting/RuneCraftPulse.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 5006b52be..204ff13f3 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -326,6 +326,7 @@ public final class RuneCraftPulse extends SkillPulse { if (altar == Altar.SOUL) { tablet = new Item(8022, amount); } if (tablet != null && player.getInventory().remove(clay)) { player.getInventory().add(tablet); + player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * amount, true); player.getPacketDispatch().sendMessage("You bind the temple's power into teleport tablets."); } } From b1ca068e3f05f30c1d5a504b7d05da8f98aec3f4 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 7 Dec 2024 19:54:27 -0700 Subject: [PATCH 151/306] Removed delay on note spell casting Since it only does 10 items at a time, it is often cast 2-3 times in a row. The delay is unnecessary for this spell. --- .../main/content/global/skill/magic/modern/ModernListeners.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index f05c616d9..a22aa32e0 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -257,7 +257,7 @@ class ModernListeners : SpellListener("modern"){ removeRunes(player) addXP(player, 31.0) showMagicTab(player) - setDelay(player, 5) + //setDelay(player, 5) return true } fun alchemize(player: Player, item: Item, high: Boolean, explorersRing: Boolean = false): Boolean { From 97053798ffc71fecb6c081bf15cfd67f7e779ca7 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 7 Dec 2024 20:16:45 -0700 Subject: [PATCH 152/306] Fixed free spell cast bug and removed delay on bind spells The chance to not consume runes was being checked before checking if the runes were in the inventory, allowing casting of spells that the player did not have the runes for. This has been fixed. Additionaly, the forced delay on bind spells has been removed, so they can be spammed. This is definitely unbalanced for pvp, nobody does pvp so it's fine. If possible in the future, reinstat the delay when targeting players. --- .../game/node/entity/combat/spell/MagicSpell.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index 86b7e1260..601cc835f 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -214,19 +214,18 @@ public abstract class MagicSpell implements Plugin { } } */ + /* Snowscape custom: removing forced delay on binding spells. If possible, reimplement this for pvp scenarios if((spellId == 12 || spellId == 30 || spellId == 56) && caster instanceof Player){ if (caster.getAttribute("entangleDelay", 0) > GameWorld.getTicks()) { caster.asPlayer().sendMessage("You have recently cast a binding spell."); return false; } } + */ if (caster instanceof Player) { Player p = (Player) caster; //if(p.getEquipment().get(3) != null && p.getEquipment().get(3).getId() == 14726){ - if(this instanceof CombatSpell && RandomFunction.getRandom(100) > 33){ - //p.sendMessage("Your staff negates the rune requirement of the spell."); - return true; - } + //} if (runes == null) { return true; @@ -237,6 +236,11 @@ public abstract class MagicSpell implements Plugin { return false; } } + //Snowscape custom: only consume runes 33% of the time + if(this instanceof CombatSpell && RandomFunction.getRandom(100) > 33){ + //p.sendMessage("Your staff negates the rune requirement of the spell."); + return true; + } if (remove) { toRemove.forEach(i -> { p.getInventory().remove(i); From 579df71848cb1478b7ee7c57cfa63bc9d48fb282 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 8 Dec 2024 14:36:34 -0700 Subject: [PATCH 153/306] Implemented familiar auto loot blocklist Adding the name of an item to the player ignore list will prevent familiars from looting that item. --- .../src/main/core/game/node/entity/npc/drop/NPCDropTables.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 2ce42e98c..1273dc594 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -172,6 +172,9 @@ public final class NPCDropTables { * @return true if item was successfully added. */ private boolean addItemFamiliar(Player player, Item item) { + if (player.getCommunication().getBlocked().contains(item.getName().toLowerCase().replace(" ","_"))) { + return false; + } if ((player.getFamiliarManager().getFamiliar() instanceof PackYakNPC) && ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().contains(12435, 1) && player.getBank().add(item)) { ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().remove(new Item(12435, 1)); player.sendMessage("Your familiar picked up and banked " + item.getAmount() + " " + item.getName() + "."); From b4950343ec59305704d9eba24fdcb9f26d35f65e Mon Sep 17 00:00:00 2001 From: GregF Date: Mon, 20 Jan 2025 11:49:01 +0000 Subject: [PATCH 154/306] Fixed bug preventing super restore recovering prayer --- .../main/content/data/consumables/effects/RestoreEffect.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/data/consumables/effects/RestoreEffect.java b/Server/src/main/content/data/consumables/effects/RestoreEffect.java index 79dc76ccb..ba9b3ea8d 100644 --- a/Server/src/main/content/data/consumables/effects/RestoreEffect.java +++ b/Server/src/main/content/data/consumables/effects/RestoreEffect.java @@ -30,11 +30,13 @@ public class RestoreEffect extends ConsumableEffect { int[] skills = this.all_skills ? ALL_SKILLS : SKILLS; for(int skill : skills){ int statL = sk.getStaticLevel(skill); + int boost = (int) (base + (statL * bonus)); int curL = sk.getLevel(skill); if(curL < statL){ - int boost = (int) (base + (statL * bonus)); p.getSkills().updateLevel(skill, boost, statL); } + if (skill == Skills.PRAYER) + p.getSkills().incrementPrayerPoints(boost); } } } From b849de2dabc193ef8e6190240896f73e0ab97193 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 12:00:38 +0000 Subject: [PATCH 155/306] Fixed magic secateurs patch bones not applying --- Server/src/main/content/global/skill/farming/CropHarvester.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/farming/CropHarvester.kt b/Server/src/main/content/global/skill/farming/CropHarvester.kt index f5fda6108..1ba3dd426 100644 --- a/Server/src/main/content/global/skill/farming/CropHarvester.kt +++ b/Server/src/main/content/global/skill/farming/CropHarvester.kt @@ -97,7 +97,7 @@ class CropHarvester : OptionHandler() { if (patch.patch.type in livesBased) { patch.rollLivesDecrement( getDynLevel(player, Skills.FARMING), - requiredItem == Items.MAGIC_SECATEURS_7409 + inInventory(player, Items.MAGIC_SECATEURS_7409) //add ||inEquipment() check when Fairy Tale pt 1 has been implemented ) } else { patch.harvestAmt-- From deecf136bc35aae2b0cf41d3194e19e30e43e60c Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 12:08:58 +0000 Subject: [PATCH 156/306] Fixed slayer cape perk activation --- Server/src/main/core/api/ContentAPI.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index c0f395b69..6a97979c1 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -4,6 +4,7 @@ import com.moandjiezana.toml.Toml import content.data.consumables.* import content.data.skill.SkillingTool import content.global.handlers.iface.ge.StockMarket +import content.global.skill.slayer.SlayerEquipmentFlags import content.global.skill.slayer.SlayerManager import content.global.skill.slayer.Tasks import content.global.skill.summoning.familiar.BurdenBeast @@ -2169,6 +2170,9 @@ fun dumpContainer(player: Player, container: core.game.container.Container): Int sendMessage(player, "A magical force prevents you from removing your ${item.name}.") return@forEach } + if (SlayerEquipmentFlags.isSlayerEq(item.id)) { + SlayerEquipmentFlags.updateFlags(player) + } } container.remove(item) From 9beb7219ea7cfc25c94b34d2b8841f9940f24796 Mon Sep 17 00:00:00 2001 From: Kennynes Date: Mon, 20 Jan 2025 12:25:25 +0000 Subject: [PATCH 157/306] Fixed examine texts for some cabbages and other items --- Server/data/configs/item_configs.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 852a6fc39..366cc6be3 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -20559,7 +20559,7 @@ }, { "ge_buy_limit": "1000", - "examine": "On ground: Cabbage... yuck!In inventory: Yuck, I don't like cabbage.", + "examine": "Yuck, I don't like cabbage.", "grand_exchange_price": "41", "durability": null, "name": "Cabbage", @@ -20578,7 +20578,7 @@ "id": "1966" }, { - "examine": "On ground: Cabbage... yuck!In inventory: Yuck, I don't like cabbage.", + "examine": "Yuck, a cabbage from Draynor Manor. I don't like cabbage.", "grand_exchange_price": "55", "durability": null, "name": "Cabbage", @@ -42660,7 +42660,7 @@ "id": "4619" }, { - "examine": "It looks horrible.On ground: Not good for eating.", + "examine": "It looks horrible.", "durability": null, "name": "Black mushroom", "weight": "1", @@ -70692,7 +70692,7 @@ }, { "ge_buy_limit": "100", - "examine": "In inventory: Nice bit of crafting! When released: Nice bit of crafting that...", + "examine": "Nice bit of crafting!", "grand_exchange_price": "3236", "durability": null, "name": "Toy doll", @@ -70710,7 +70710,7 @@ "id": "7764" }, { - "examine": "In inventory: Nice bit of crafting! When released: Nice bit of crafting that...", + "examine": "Nice bit of crafting!", "grand_exchange_price": "3289", "durability": null, "name": "Toy doll (wound)", From d08656021c78184fb305710e7f76bbb179e38d38 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 12:35:01 +0000 Subject: [PATCH 158/306] Fixed pillory random event completion teleport location --- .../main/content/global/ame/events/pillory/PilloryInterface.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt index 55e54a0fb..22ff21957 100644 --- a/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt +++ b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt @@ -201,7 +201,7 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { } override fun getRestrictions(): Array { - return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT) + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP) } override fun areaEnter(entity: Entity) { From d5c7d747679ddb5b32036ff57a7794130cd760d0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 12:46:57 +0000 Subject: [PATCH 159/306] Fixed a bug where the player could get locked planting while farming --- .../skill/farming/UseWithPatchHandler.kt | 80 ++++++++++--------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt index 26f8658fa..497abcad9 100644 --- a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt +++ b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt @@ -263,51 +263,53 @@ class UseWithPatchHandler : InteractionListener { sendMessage(player, "You need ${prependArticle(requiredItem.asItem().name.lowercase())} to plant that.") return@onUseWith true } - player.lock() - if (removeItem(player, plantItem)) { - when (requiredItem) { - Items.SPADE_952 -> { - animate(player, spadeDigAnim) - playAudio(player, Sounds.DIGSPADE_1470) + + queueScript(player, 0, QueueStrength.WEAK) { stage: Int -> + when (stage) { + 0 -> { + val (anim, sound) = when (requiredItem) { + Items.SPADE_952 -> Pair(spadeDigAnim, Sounds.DIGSPADE_1470) + else -> Pair(seedDibberAnim,Sounds.FARMING_DIBBING_2432) + } + animate(player, anim) + playAudio(player, sound) + val delay = if (patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || plantable == Plantable.SCARECROW) 3 else 0 + return@queueScript delayScript(player,anim.duration + delay) } - Items.SEED_DIBBER_5343 -> { - animate(player, seedDibberAnim) - playAudio(player, Sounds.FARMING_DIBBING_2432) + 1 -> { + if (removeItem(player, plantItem)) { + if (plantable == Plantable.JUTE_SEED && patch == FarmingPatch.MCGRUBOR_HOPS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 0, 7)) { + player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 7) + } + p.plant(plantable) + rewardXP(player, Skills.FARMING, plantable.plantingXP) + p.setNewHarvestAmount() + if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) { + addItem(player, Items.PLANT_POT_5350) + } + + val itemAmount = + if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) "the" + else if (plantItem.amount == 1) "a" + else plantItem.amount + val itemName = + if (plantItem.amount == 1) plantable.displayName else StringUtils.plusS( + plantable.displayName + ) + val patchName = p.patch.type.displayName() + if (plantable == Plantable.SCARECROW) { + sendMessage(player, "You place the scarecrow in the $patchName.") + } else { + sendMessage(player, "You plant $itemAmount $itemName in the $patchName.") + } + } + return@queueScript stopExecuting(player) } + else -> return@queueScript stopExecuting(player) } - val delay = if (patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || plantable == Plantable.SCARECROW) 0 else 3 - submitIndividualPulse(player, object : Pulse(delay) { - override fun pulse(): Boolean { - if (plantable == Plantable.JUTE_SEED && patch == FarmingPatch.MCGRUBOR_HOPS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 0, 7)) { - player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 7) - } - p.plant(plantable) - rewardXP(player, Skills.FARMING, plantable.plantingXP) - p.setNewHarvestAmount() - if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) { - addItem(player, Items.PLANT_POT_5350) - } - - val itemAmount = - if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) "the" - else if (plantItem.amount == 1) "a" - else plantItem.amount - val itemName = if (plantItem.amount == 1) plantable.displayName else StringUtils.plusS(plantable.displayName) - val patchName = p.patch.type.displayName() - if (plantable == Plantable.SCARECROW) { - sendMessage(player, "You place the scarecrow in the $patchName.") - } else { - sendMessage(player, "You plant $itemAmount $itemName in the $patchName.") - } - - player.unlock() - return true - } - }) } } } - return@onUseWith true } } From eb3884180e968cb04a8c1bcaacf9352ad59b4fcf Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Mon, 20 Jan 2025 12:56:19 +0000 Subject: [PATCH 160/306] Signpost improvements Minor quest log fixes Implemented map for talismans in Wizard Tower basement --- Server/data/configs/object_configs.json | 2 +- .../handlers/scenery/SignpostListener.kt | 123 +++++++++++++----- .../falador/quest/doricsquest/DoricsQuest.kt | 17 ++- .../varrock/quest/romeo/RomeoJuliet.java | 6 +- .../wiztower/handlers/TalismanMapInterface.kt | 21 +++ 5 files changed, 129 insertions(+), 40 deletions(-) create mode 100644 Server/src/main/content/region/misthalin/wiztower/handlers/TalismanMapInterface.kt diff --git a/Server/data/configs/object_configs.json b/Server/data/configs/object_configs.json index 66e83f536..54f50f614 100644 --- a/Server/data/configs/object_configs.json +++ b/Server/data/configs/object_configs.json @@ -16324,7 +16324,7 @@ "ids": "11629" }, { - "examine": "South to Falador :: West to Taverley :: East to Varrock.", + "examine": "This tells you which way is which.", "ids": "11630,11631,11632,11633" }, { diff --git a/Server/src/main/content/global/handlers/scenery/SignpostListener.kt b/Server/src/main/content/global/handlers/scenery/SignpostListener.kt index 837462159..19622a201 100644 --- a/Server/src/main/content/global/handlers/scenery/SignpostListener.kt +++ b/Server/src/main/content/global/handlers/scenery/SignpostListener.kt @@ -11,18 +11,21 @@ class SignpostListener : InteractionListener { override fun defineListeners() { on(Scenery.SIGNPOST_18493, IntType.SCENERY, "read") { player, node -> if (node.asScenery().location.equals(Location(3235, 3228))) { + // Authentic setInterfaceText(player, "Head north towards Fred's farm, and the windmill.", 135, 3) // North setInterfaceText(player, "South to the swamps of Lumbridge.", 135, 9) // South setInterfaceText(player, "Cross the bridge and head east to Al Kharid or north to Varrock.", 135, 8) // East setInterfaceText(player, "West to the Lumbridge Castle and Draynor Village. Beware the goblins!", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else if (node.asScenery().location.equals(Location(3261, 3230))) { + // Authentic setInterfaceText(player, "North to farms and Varrock.", 135, 3) // North setInterfaceText(player, "The River Lum lies to the south.", 135, 9) // South setInterfaceText(player, "East to Al Kharid - toll gate; bring some money.", 135, 8) // East setInterfaceText(player, "West to Lumbridge.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else if (node.asScenery().location.equals(Location(2983, 3278))) { + // Authentic setInterfaceText(player, "North to the glorious White Knights' city of Falador.", 135, 3) // North setInterfaceText(player, "South to Rimmington.", 135, 9) // South setInterfaceText(player, "East to Port Sarim and Draynor Village.", 135, 8) // East @@ -45,12 +48,14 @@ class SignpostListener : InteractionListener { } on(Scenery.SIGNPOST_24263, IntType.SCENERY, "read") { player, node -> if (node.asScenery().location.equals(Location(3268, 3332))) { + // Authentic setInterfaceText(player, "Sheep lay this way.", 135, 3) // North setInterfaceText(player, "South through farms to Al Kharid and Lumbridge.", 135, 9) // South setInterfaceText(player, "East to Al Kharid mine and follow the path north to Varrock east gate.", 135, 8) // East setInterfaceText(player, "West to Champion's Guild and Varrock south gate.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else if (node.asScenery().location.equals(Location(3283, 3333))) { + // Authentic setInterfaceText(player, "North to Varrock mine and Varrock east gate.", 135, 3) // North setInterfaceText(player, "South to large Mining area and Al Kharid.", 135, 9) // South setInterfaceText(player, "Follow the path east to the Dig Site.", 135, 8) // East @@ -66,7 +71,13 @@ class SignpostListener : InteractionListener { return@on true } on(Scenery.SIGNPOST_4132, IntType.SCENERY, "read") { player, node -> - if (node.asScenery().location.equals(Location(3166, 3286))) { + if (node.asScenery().location.equals(Location(3223, 3427))) { + setInterfaceText(player, "North to Varrock Palace.", 135, 3) // North + setInterfaceText(player, "South to the Champion's Guild.", 135, 9) // South + setInterfaceText(player, "East to the Dig Site.", 135, 8) // East + setInterfaceText(player, "West to Barbarian Village and Falador.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else if (node.asScenery().location.equals(Location(3166, 3286))) { setInterfaceText(player, "North to the windmill.", 135, 3) // North setInterfaceText(player, "South to a fishing pond next to Fred's farm.", 135, 9) // South setInterfaceText(player, "East to Lumbridge.", 135, 8) // East @@ -85,24 +96,24 @@ class SignpostListener : InteractionListener { setInterfaceText(player, "Follow the path west to Ardougne.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else if (node.asScenery().location.equals(Location(2604, 3240))) { - setInterfaceText(player, "North to the Ardougne City Zoo.", 135, 3) // North - setInterfaceText(player, "South to the Monastery.", 135, 9) // South - setInterfaceText(player, "East to the Tower of Life.", 135, 8) // East - setInterfaceText(player, "West to the Clocktower.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else if (node.asScenery().location.equals(Location(2605, 3298))) { - setInterfaceText(player, "North to the Fishing Guild and Hemenster.", 135, 3) // North - setInterfaceText(player, "South to the Ardougne City Zoo.", 135, 9) // South - setInterfaceText(player, "East to Ardougne Market.", 135, 8) // East - setInterfaceText(player, "West to Ardougne Castle and West Ardougne.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else if (node.asScenery().location.equals(Location(2646, 3404))) { - setInterfaceText(player, "North to the Ranging Guild and Seer's Village.", 135, 3) // North - setInterfaceText(player, "South to the Ardougne City.", 135, 9) // South - setInterfaceText(player, "East to the Sorcerer's Tower.", 135, 8) // East - setInterfaceText(player, "West to the Fishing Guild.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else { + setInterfaceText(player, "North to Ardougne Zoo.", 135, 3) // North + setInterfaceText(player, "South to the Monastery.", 135, 9) // South + setInterfaceText(player, "East to the Tower of Life.", 135, 8) // East + setInterfaceText(player, "West to the Clocktower.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else if (node.asScenery().location.equals(Location(2605, 3298))) { + setInterfaceText(player, "North to the Fishing Guild and Baxtorian Falls.", 135, 3) // North + setInterfaceText(player, "South to Ardougne Zoo and Port Khazard.", 135, 9) // South + setInterfaceText(player, "East to Ardougne Market and Witchaven.", 135, 8) // East + setInterfaceText(player, "West to Ardougne Castle and Ardougne West.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else if (node.asScenery().location.equals(Location(2646, 3404))) { + setInterfaceText(player, "North to the Ranging Guild and Seer's Village.", 135, 3) // North + setInterfaceText(player, "South to the Ardougne City.", 135, 9) // South + setInterfaceText(player, "East to the Sorcerer's Tower.", 135, 8) // East + setInterfaceText(player, "West to the Fishing Guild.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else { setInterfaceText(player, "North to unknown.", 135, 3) // North setInterfaceText(player, "South to unknown.", 135, 9) // South setInterfaceText(player, "East to unknown.", 135, 8) // East @@ -122,7 +133,57 @@ class SignpostListener : InteractionListener { setInterfaceText(player, "North to Edgeville.", 135, 3) // North setInterfaceText(player, "South to Draynor Manor.", 135, 9) // South setInterfaceText(player, "East to Varrock west gate.", 135, 8) // East - setInterfaceText(player, "West to Barbarian Village.", 135, 12) // West + setInterfaceText(player, "West to Barbarian Village and Falador.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else { + setInterfaceText(player, "North to unknown.", 135, 3) // North + setInterfaceText(player, "South to unknown.", 135, 9) // South + setInterfaceText(player, "East to unknown.", 135, 8) // East + setInterfaceText(player, "West to unknown.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } + return@on true + } + on(Scenery.SIGNPOST_4135, IntType.SCENERY, "read") { player, node -> + if (node.asScenery().location.equals(Location(3448, 3486))) { + setInterfaceText(player, "North to the Slayer Tower.", 135, 3) // North + setInterfaceText(player, "South to Mort Myre Swamp.", 135, 9) // South + setInterfaceText(player, "East to Canifis.", 135, 8) // East + setInterfaceText(player, "West to Varrock.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else { + setInterfaceText(player, "North to unknown.", 135, 3) // North + setInterfaceText(player, "South to unknown.", 135, 9) // South + setInterfaceText(player, "East to unknown.", 135, 8) // East + setInterfaceText(player, "West to unknown.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } + return@on true + } + on(Scenery.SIGNPOST_31296, IntType.SCENERY, "read") { player, node -> + if (node.asScenery().location.equals(Location(3304, 3109))) { + // Authentic + setInterfaceText(player, "North to Al Kharid.", 135, 3) // North + setInterfaceText(player, "South to the Desert Mining Camp and Pollnivneach.", 135, 9) // South + setInterfaceText(player, "East and across the river to the Ruins of Uzer.", 135, 8) // East + setInterfaceText(player, "West to the Kalphite Lair.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else { + setInterfaceText(player, "North to unknown.", 135, 3) // North + setInterfaceText(player, "South to unknown.", 135, 9) // South + setInterfaceText(player, "East to unknown.", 135, 8) // East + setInterfaceText(player, "West to unknown.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } + return@on true + } + on(Scenery.STONE_SIGNPOST_11630, IntType.SCENERY, "read") { player, node -> + // Authentic // https://youtu.be/vvHXKTOh_g4 + if (node.asScenery().location.equals(Location(2967, 3412))) { + setInterfaceText(player, "North to Goblin Village.", 135, 3) // North + setInterfaceText(player, "South to Falador.", 135, 9) // South + setInterfaceText(player, "East to Varrock.", 135, 8) // East + setInterfaceText(player, "West to Taverley.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else { setInterfaceText(player, "North to unknown.", 135, 3) // North @@ -143,17 +204,17 @@ class SignpostListener : InteractionListener { * SceneryDefinition.forId(4133).getHandlers().put("option:read", this); * SceneryDefinition.forId(4134).getHandlers().put("option:read", this); * SceneryDefinition.forId(4135).getHandlers().put("option:read", this); - * SceneryDefinition.forId(5164).getHandlers().put("option:read", this); - * SceneryDefinition.forId(10090).getHandlers().put("option:read", this); - * SceneryDefinition.forId(13873).getHandlers().put("option:read", this); - * SceneryDefinition.forId(15522).getHandlers().put("option:read", this); - * SceneryDefinition.forId(25397).getHandlers().put("option:read", this); - * SceneryDefinition.forId(30039).getHandlers().put("option:read", this); - * SceneryDefinition.forId(30040).getHandlers().put("option:read", this); - * SceneryDefinition.forId(31296).getHandlers().put("option:read", this); - * SceneryDefinition.forId(31298).getHandlers().put("option:read", this); - * SceneryDefinition.forId(31299).getHandlers().put("option:read", this); - * SceneryDefinition.forId(31300).getHandlers().put("option:read", this); + * + * SceneryDefinition.forId(5164).getHandlers().put("option:read", this); No + * SceneryDefinition.forId(10090).getHandlers().put("option:read", this); No + * + * SceneryDefinition.forId(13873).getHandlers().put("option:read", this); No + * + * SceneryDefinition.forId(15522).getHandlers().put("option:read", this); No + * SceneryDefinition.forId(25397).getHandlers().put("option:read", this); No + * + * SceneryDefinition.forId(30039).getHandlers().put("option:read", this); // ???? + * SceneryDefinition.forId(30040).getHandlers().put("option:read", this); // ?????? * // ObjectDefinition.forId(31301).getConfigurations().put("option:read", this);//goblin village * return this; * } diff --git a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt index 5c04c3983..cc189df02 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt @@ -15,18 +15,23 @@ class DoricsQuest : Quest("Doric's Quest", 17, 16, 1, 31, 0, 1, 100) { override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) player ?: return - var line = 11 + var line = 12 if(stage == 0) { line(player, "I can start this quest by speaking to !!Doric?? who is !!North of??", line++) line(player, "!!Falador??.", line++) + line++ line(player, "There aren't any requirements but !!Level 15 Mining?? will help.", line++) } else { if(stage in 1..99) { - line(player, "I have spoken to !!Doric??.", line++) - line(player, "I need to collect some items and bring them to !!Doric??:", line++) - line(player, "6 Clay", line++, inInventory(player, Items.CLAY_434, 6)) - line(player, "4 Copper Ore", line++, inInventory(player, Items.COPPER_ORE_436, 4)) - line(player, "2 Iron Ore", line++, inInventory(player, Items.IRON_ORE_440, 2)) + // https://www.youtube.com/watch?v=vm4BEXtMoO0 + line(player, "I have spoken to Doric. He agreed to let me use his anvils", line++, true) + line(player, "if I bring him some materials.", line++, true) + line++ + line(player, "I need to collect the following materials and bring them all", line++) + line(player, "to !!Doric??:", line++) + line(player, "!!6 Clay.??", line++, inInventory(player, Items.CLAY_434, 6)) + line(player, "!!4 Copper Ore.??", line++, inInventory(player, Items.COPPER_ORE_436, 4)) + line(player, "!!2 Iron Ore.??", line++, inInventory(player, Items.IRON_ORE_440, 2)) } if(stage == 100) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java index 744214e26..90ddba6a7 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java @@ -29,7 +29,8 @@ public class RomeoJuliet extends Quest { case 10: line(player, "I have agreed to find Juliet for Romeo and tell her how he", 4+ 7); line(player, "feels. For some reason he can't just do this himself.", 5+ 7); - line(player, BLUE + "All I need to do now is find " + RED + "Juliet.", 6+ 7); + // https://www.youtube.com/watch?v=ush_RVY4tvw + line(player, BLUE + "I should go and speak to " + RED + "Juliet" + BLUE + ", wherever she is?", 7+ 7); break; case 20: line(player, "I have agreed to find Juliet for Romeo and tell her how he", 4+ 7); @@ -113,6 +114,7 @@ public class RomeoJuliet extends Quest { line(player, BLUE + "I have to find " + RED + "Romeo" + BLUE + " and tell him what's happened.", 18+ 7); break; case 100: + // https://www.youtube.com/watch?v=m4bZ4GmHxRs line(player, "Romeo and Juliet can be together in peace.", 4+ 7); line(player, "I went to the Apothecary regarding making this cadava", 5+ 7); line(player, "potion, and he told me to bring him some cadava berries.", 6+ 7); @@ -121,7 +123,7 @@ public class RomeoJuliet extends Quest { line(player, "I told Romeo what was going to happen, but I'm not exactly", 9+ 7); line(player, "sure he understood what was happening. Ah well, I was", 10+ 7); line(player, "rewarded for all of my help regardless.", 11+ 7); - line(player, "QUEST COMPLETE!", 12+ 7); + line(player, "QUEST COMPLETE!", 13+ 7); break; } } diff --git a/Server/src/main/content/region/misthalin/wiztower/handlers/TalismanMapInterface.kt b/Server/src/main/content/region/misthalin/wiztower/handlers/TalismanMapInterface.kt new file mode 100644 index 000000000..b97893d88 --- /dev/null +++ b/Server/src/main/content/region/misthalin/wiztower/handlers/TalismanMapInterface.kt @@ -0,0 +1,21 @@ +package content.region.misthalin.wiztower.handlers + +import core.api.* +import core.game.interaction.InteractionListener +import org.rs09.consts.Scenery +import org.rs09.consts.Components + +// http://youtu.be/T62dugdfzSQ +/** Map for talismans in Wizard Tower basement. I display everything, because let's be real, you can find this online... */ +class TalismanMapInterface : InteractionListener { + override fun defineListeners() { + on(intArrayOf(Scenery.MAP_38421, Scenery.MAP_38422), SCENERY, "study") { player, node -> + openInterface(player, Components.RCGUILD_MAP_780) + // Air talisman to Death talisman + for(i in 35..48) { + setComponentVisibility(player, Components.RCGUILD_MAP_780, i, false) + } + return@on true + } + } +} \ No newline at end of file From 39634b6cafad411aa9d5a940fb07a9de79a86831 Mon Sep 17 00:00:00 2001 From: gregf36665 Date: Fri, 1 Nov 2024 10:11:09 +0000 Subject: [PATCH 161/306] Implement penguin egg acquisition --- Server/data/configs/item_configs.json | 24 +++++-- Server/data/configs/npc_spawns.json | 2 +- .../dialogue/PenguinKeeperDialogue.kt | 62 +++++++++++++++++++ 3 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 Server/src/main/content/region/kandarin/ardougne/dialogue/PenguinKeeperDialogue.kt diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 366cc6be3..9261394b7 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -106567,16 +106567,17 @@ "id": "12480" }, { - "examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.", + "examine": "Can't fly and can barely walk, but adorable nonetheless.", "durability": null, "name": "Baby penguin", "archery_ticket_price": "0", "id": "12481" }, { - "examine": "I can hatch this in an Incubator.", + "examine": "I can hatch this in an incubator.", "durability": null, "name": "Penguin egg", + "tradeable": "false", "archery_ticket_price": "0", "id": "12483" }, @@ -108972,14 +108973,14 @@ "id": "12761" }, { - "examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.", + "examine": "Can't fly and can barely walk, but adorable nonetheless.", "durability": null, "name": "Baby penguin", "archery_ticket_price": "0", "id": "12763" }, { - "examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.", + "examine": "Can't fly and can barely walk, but adorable nonetheless.", "durability": null, "name": "Baby penguin", "archery_ticket_price": "0", @@ -132095,5 +132096,20 @@ "archery_ticket_price": "0", "id": "14658", "equipment_slot": "0" + }, + { + "examine": "Emperor of all he surveys.", + "name": "Penguin", + "id": "12482" + }, + { + "examine": "Emperor of all he surveys.", + "name": "Penguin", + "id": "12762" + }, + { + "examine": "Emperor of all he surveys.", + "name": "Penguin", + "id": "12764" } ] \ No newline at end of file diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index bdc23b4cc..4ccdde965 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -10909,7 +10909,7 @@ }, { "npc_id": "6891", - "loc_data": "{2598,3272,0,0,0}-" + "loc_data": "{2598,3272,0,1,0}-" }, { "npc_id": "6893", diff --git a/Server/src/main/content/region/kandarin/ardougne/dialogue/PenguinKeeperDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/dialogue/PenguinKeeperDialogue.kt new file mode 100644 index 000000000..9a6ccdff9 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/dialogue/PenguinKeeperDialogue.kt @@ -0,0 +1,62 @@ +package content.region.kandarin.ardougne.dialogue + +import core.api.addItem +import core.api.getDynLevel +import core.api.hasAnItem +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class PenguinKeeperDialogue(player: Player? = null) : DialoguePlugin(player) { + override fun getIds(): IntArray { + return intArrayOf(NPCs.PENGUIN_KEEPER_6891) + } + + companion object{ + const val YES = 20 + const val NO = 40 + const val FULL = 50 + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(stage){ + 0 -> playerl(FacialExpression.FRIENDLY, "Hello there. How are the penguins doing today?").also { stage++ } + 1 -> npcl(FacialExpression.FRIENDLY, "They are doing fine, thanks.").also{ + if (getDynLevel(player, Skills.SUMMONING) < 30 || hasAnItem(player, Items.PENGUIN_EGG_12483).exists()) + stage = END_DIALOGUE + else + stage++ + } + 2 -> npcl(FacialExpression.HALF_ASKING,"Actually, you might be able to help me with something - if you are interested.").also { stage++ } + 3 -> playerl(FacialExpression.ASKING, "What do you mean?").also { stage++ } + 4 -> npcl(FacialExpression.NEUTRAL, "Well, you see, the penguins have been laying so many eggs recently that we can't afford to raise them all ourselves.").also { stage++ } + 5 -> npcl(FacialExpression.ASKING, " You seem to know a bit about raising animals - would you like to raise a penguin for us? ").also { stage++ } + 6 -> showTopics( + Topic("Yes, of course.", YES), + Topic("No thanks.", NO) + ) + + YES -> npcl(FacialExpression.HAPPY, "Wonderful!").also { + if (addItem(player, Items.PENGUIN_EGG_12483)) + stage++ + else + stage = FULL + } + YES + 1 -> npcl(FacialExpression.HAPPY, "Here you go - this egg will hatch into a baby penguin.").also { stage++ } + YES + 2 -> npcl(FacialExpression.HAPPY, "They eat raw fish and aren't particularly fussy about anything, so it won't be any trouble to raise.").also { stage++ } + YES + 3 -> playerl(FacialExpression.HAPPY, "Okay, thank you very much.").also { stage = END_DIALOGUE } + + NO -> npcl(FacialExpression.NEUTRAL, " Fair enough. The offer still stands if you change your mind. ").also { stage = END_DIALOGUE } + + FULL -> npcl(FacialExpression.SAD, "You don't have inventory space though.").also { stage = END_DIALOGUE } + } + return true + } +} \ No newline at end of file From 9af776e3c6981d66786245c2433f899598f52f63 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 13:49:58 +0000 Subject: [PATCH 162/306] Refactored some runecrafting code Corrected the Ourania altar reward, now fully authentic --- .../skill/runecrafting/RuneCraftPulse.java | 171 +++++++++--------- 1 file changed, 84 insertions(+), 87 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index d32bea579..62c8b5efc 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -2,6 +2,7 @@ package content.global.skill.runecrafting; import content.global.handlers.item.equipment.fistofguthixgloves.FOGGlovesManager; import core.ServerConstants; +import core.api.Container; import core.game.container.impl.EquipmentContainer; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.player.Player; @@ -28,6 +29,7 @@ import java.util.Arrays; * A class used to craft runes. * * @author Vexia + * @author Player Name */ public final class RuneCraftPulse extends SkillPulse { @@ -111,36 +113,36 @@ public final class RuneCraftPulse extends SkillPulse { if (!hasRequirement(player, "Legacy of Seergaze")) return false; } - if (!altar.isOurania() && player.getSkills().getLevel(Skills.RUNECRAFTING) < rune.getLevel()) { - player.getPacketDispatch().sendMessage("You need a Runecrafting level of at least " + rune.getLevel() + " to craft this rune."); + if (!altar.isOurania() && getDynLevel(player, Skills.RUNECRAFTING) < rune.getLevel()) { + sendMessage(player, "You need a Runecrafting level of at least " + rune.getLevel() + " to craft this rune."); return false; } - if (combination && !player.getInventory().containsItem(PURE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need pure essence to craft this rune."); + if (combination && amountInInventory(player, PURE_ESSENCE.getId()) == 0) { + sendMessage(player, "You need pure essence to craft this rune."); return false; } - if (!altar.isOurania() && !rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need pure essence to craft this rune."); + if (!altar.isOurania() && !rune.isNormal() && amountInInventory(player, PURE_ESSENCE.getId()) == 0) { + sendMessage(player, "You need pure essence to craft this rune."); return false; } - if (!altar.isOurania() && rune.isNormal() && !player.getInventory().containsItem(PURE_ESSENCE) && !player.getInventory().containsItem(RUNE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need rune essence or pure essence in order to craft this rune."); + if (!altar.isOurania() && rune.isNormal() && amountInInventory(player, PURE_ESSENCE.getId()) == 0 && amountInInventory(player, RUNE_ESSENCE.getId()) == 0) { + sendMessage(player, "You need rune essence or pure essence in order to craft this rune."); return false; } - if (altar.isOurania() && !player.getInventory().containsItem(PURE_ESSENCE)) { - player.getPacketDispatch().sendMessage("You need pure essence to craft this rune."); + if (altar.isOurania() && amountInInventory(player, PURE_ESSENCE.getId()) == 0) { + sendMessage(player, "You need pure essence to craft this rune."); return false; } - if (combination && player.getSkills().getLevel(Skills.RUNECRAFTING) < combo.getLevel()) { - player.getPacketDispatch().sendMessage("You need a Runecrafting level of at least " + combo.getLevel() + " to combine this rune."); + if (combination && getDynLevel(player, Skills.RUNECRAFTING) < combo.getLevel()) { + sendMessage(player, "You need a Runecrafting level of at least " + combo.getLevel() + " to combine this rune."); return false; } if (node != null) { if (node.getName().contains("rune") && !hasSpellImbue()) { final Rune r = Rune.forItem(node); final Talisman t = Talisman.forName(r.name()); - if (!player.getInventory().containsItem(t.getTalisman())) { - player.getPacketDispatch().sendMessage("You don't have the correct talisman to combine this rune."); + if (amountInInventory(player, t.getTalisman().getId()) == 0) { + sendMessage(player, "You don't have the correct talisman to combine this rune."); return false; } talisman = t; @@ -167,25 +169,63 @@ public final class RuneCraftPulse extends SkillPulse { return true; } + private static final int[][] OuraniaTable = { //https://x.com/JagexAsh/status/1312893446395506688/photo/1 + /*level up to 9*/ { 2, 7, 15, 30, 60, 105, 165, 250, 400, 700,1300,2500,5000,10000}, + /*level up to 19*/ { 3, 9, 21, 45, 85, 145, 225, 400,1000,2200,4600,6700,8500,10000}, + /*level up to 29*/ { 8, 23, 55, 110, 220, 430, 850,1650,3250,4750,6150,7500,8800,10000}, + /*level up to 39*/ { 20, 60, 120, 250, 500,1000,2000,4000,5300,6500,7600,8500,9300,10000}, + /*level up to 49*/ { 40, 120, 240, 500,1000,2000,4000,5500,6500,7300,8050,8750,9400,10000}, + /*level up to 59*/ { 80, 250, 600,1300,2650,4150,5250,6250,7000,7700,8350,8950,9500,10000}, + /*level up to 69*/ {100, 300, 700,1500,3050,4450,5500,6450,7200,7900,8500,9050,9550,10000}, + /*level up to 79*/ {200, 700,1700,3500,5000,6200,7100,7800,8300,8700,9100,9400,9700,10000}, + /*level up to 89*/ {400,1000,2450,3900,5250,6300,7100,7800,8400,8900,9300,9600,9800,10000}, + /*level up to 98*/ {650,1650,3300,4750,6100,7100,7800,8400,8900,9300,9600,9800,9900,10000}, + /*level up to 99*/ {900,2200,3750,5200,6550,7500,8100,8600,9000,9300,9600,9800,9900,10000} + }; + /** * Method used to craft runes. */ private void craft() { - final Item item = new Item(getEssence().getId(), getEssenceAmount()); + final Item item = getEssenceItem(); int amount = player.getInventory().getAmount(item); - if (!altar.isOurania()) { + if (altar.isOurania()) { + if (removeItem(player, item, Container.INVENTORY)) { + sendMessage(player, "You bind the temple's power into runes."); + player.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_RC, amount); + + int[] OuraniaValues; + if (getDynLevel(player, Skills.RUNECRAFTING) == 99) { + OuraniaValues = OuraniaTable[10]; + } else { + int index = getDynLevel(player, Skills.RUNECRAFTING) / 10; + OuraniaValues = OuraniaTable[index]; + } + for (int i = 0; i < amount; i++) { + int roll = RandomFunction.random(10000); + Rune rune = null; + for (int j = 0; j < 14; j++) { + if (roll < OuraniaValues[j]) { + rune = Rune.values()[13 - j]; + break; + } + } + rewardXP(player, Skills.RUNECRAFTING, rune.getExperience() * 2); + addItemOrDrop(player, rune.getRune().getId(), 1); + } + } + } else { int total = 0; for(int j = 0; j < amount; j++) { // since getMultiplier is stochastic, roll `amount` independent copies total += getMultiplier(); } - Item i = new Item(rune.getRune().getId(), total); - if (player.getInventory().remove(item) && player.getInventory().hasSpaceFor(i)) { - player.getPacketDispatch().sendMessage("You bind the temple's power into " + (combination ? combo.getRune().getName().toLowerCase() : rune.getRune().getName().toLowerCase()) + "s."); - player.getInventory().add(i); + if (removeItem(player, item, Container.INVENTORY)) { + sendMessage(player, "You bind the temple's power into " + (combination ? combo.getRune().getName().toLowerCase() : rune.getRune().getName().toLowerCase()) + "s."); + addItemOrDrop(player, rune.getRune().getId(), total); player.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_RC, amount); - + // Fist of guthix gloves double xp = rune.getExperience() * amount; if ((altar == Altar.AIR && inEquipment(player, Items.AIR_RUNECRAFTING_GLOVES_12863, 1)) @@ -193,7 +233,7 @@ public final class RuneCraftPulse extends SkillPulse { || (altar == Altar.EARTH && inEquipment(player, Items.EARTH_RUNECRAFTING_GLOVES_12865, 1))) { xp += xp * FOGGlovesManager.updateCharges(player, amount) / amount; } - player.getSkills().addExperience(Skills.RUNECRAFTING, xp, true); + rewardXP(player, Skills.RUNECRAFTING, xp); // Achievement Diary handling // Craft some nature runes @@ -201,7 +241,7 @@ public final class RuneCraftPulse extends SkillPulse { player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 2, 3); } // Craft 196 or more air runes simultaneously - if (altar == Altar.AIR && i.getAmount() >= 196) { + if (altar == Altar.AIR && total >= 196) { player.getAchievementDiaryManager().finishTask(player, DiaryType.FALADOR, 2, 2); } // Craft a water rune at the Water Altar @@ -210,58 +250,34 @@ public final class RuneCraftPulse extends SkillPulse { } } - } else { - if (player.getInventory().remove(item)) { - player.getPacketDispatch().sendMessage("You bind the temple's power into runes."); - player.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_RC, amount); - for (int i = 0; i < amount; i++) { - Rune rune = null; - while (rune == null) { - final Rune temp = Rune.values()[RandomFunction.random(Rune.values().length)]; - if (player.getSkills().getLevel(Skills.RUNECRAFTING) >= temp.getLevel()) { - rune = temp; - } else { - if (RandomFunction.random(3) == 1) { - rune = temp; - } - } - } - player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * 2, true); - Item runeItem = rune.getRune(); - player.getInventory().add(runeItem); - } - } } } /** * Method used to combine runes. */ - private final void combine() { + private void combine() { final Item remove = node.getName().contains("talisman") ? node : talisman != null ? talisman.getTalisman() : Talisman.forName(Rune.forItem(node).name()).getTalisman(); boolean imbued = hasSpellImbue(); - if (!imbued ? player.getInventory().remove(remove) : imbued) { + if (!imbued ? removeItem(player, remove, Container.INVENTORY) : imbued) { int amount = 0; int essenceAmt = player.getInventory().getAmount(PURE_ESSENCE); final Item rune = node.getName().contains("rune") ? Rune.forItem(node).getRune() : Rune.forName(Talisman.forItem(node).name()).getRune(); int runeAmt = player.getInventory().getAmount(rune); - if (essenceAmt > runeAmt) { - amount = runeAmt; - } else { - amount = essenceAmt; - } - if (player.getInventory().remove(new Item(PURE_ESSENCE.getId(), amount)) && player.getInventory().remove(new Item(rune.getId(), amount))) { + amount = Math.min(essenceAmt, runeAmt); + if (removeItem(player, new Item(PURE_ESSENCE.getId(), amount), Container.INVENTORY) && removeItem(player, new Item(rune.getId(), amount), Container.INVENTORY)) { for (int i = 0; i < amount; i++) { if (RandomFunction.random(1, 3) == 1 || hasBindingNecklace()) { - player.getInventory().add(new Item(combo.getRune().getId(), 1)); - player.getSkills().addExperience(Skills.RUNECRAFTING, combo.getExperience(), true); + addItemOrDrop(player, combo.getRune().getId(), 1); + rewardXP(player, Skills.RUNECRAFTING, combo.getExperience()); } } if (hasBindingNecklace()) { player.getEquipment().get(EquipmentContainer.SLOT_AMULET).setCharge(player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() - 1); if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() > 14) { - player.getEquipment().remove(BINDING_NECKLACE, true); - player.getPacketDispatch().sendMessage("Your binding necklace crumbles into dust."); + if (player.getEquipment().remove(BINDING_NECKLACE, true)) { + sendMessage(player, "Your binding necklace crumbles into dust."); + } } } } @@ -278,39 +294,21 @@ public final class RuneCraftPulse extends SkillPulse { } /** - * Gets the essence amount. + * Gets the rune essence item. * - * @return the amount of essence. + * @return the rune essence item. */ - private int getEssenceAmount() { - if (altar.isOurania() && player.getInventory().containsItem(PURE_ESSENCE)) { - return player.getInventory().getAmount(PURE_ESSENCE); + private Item getEssenceItem() { + if (altar.isOurania() && amountInInventory(player, PURE_ESSENCE.getId()) > 0) { + return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); } - if (!rune.isNormal() && player.getInventory().containsItem(PURE_ESSENCE)) { - return player.getInventory().getAmount(PURE_ESSENCE); - } else if (rune.isNormal() && player.getInventory().containsItem(PURE_ESSENCE)) { - return player.getInventory().getAmount(PURE_ESSENCE); - } else { - return player.getInventory().getAmount(RUNE_ESSENCE); + if (!rune.isNormal() && amountInInventory(player, PURE_ESSENCE.getId()) > 0) { + return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); } - } - - /** - * Gets the rune essence that needs to be defined. - * - * @return the item. - */ - private Item getEssence() { - if (altar.isOurania() && player.getInventory().containsItem(PURE_ESSENCE)) { - return PURE_ESSENCE; - } - if (!rune.isNormal() && player.getInventory().containsItem(PURE_ESSENCE)) { - return PURE_ESSENCE; - } else if (rune.isNormal() && player.getInventory().containsItem(PURE_ESSENCE)) { - return PURE_ESSENCE; - } else { - return RUNE_ESSENCE; + if (rune.isNormal() && amountInInventory(player, RUNE_ESSENCE.getId()) > 0) { + return new Item(RUNE_ESSENCE.getId(), amountInInventory(player, RUNE_ESSENCE.getId())); } + return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); } /** @@ -322,7 +320,7 @@ public final class RuneCraftPulse extends SkillPulse { if (altar.isOurania()) { return 1; } - int rcLevel = player.getSkills().getLevel(Skills.RUNECRAFTING); + int rcLevel = getDynLevel(player, Skills.RUNECRAFTING); int runecraftingFormulaRevision = ServerConstants.RUNECRAFTING_FORMULA_REVISION; boolean lumbridgeDiary = player.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE).isComplete(1); return RuneCraftPulse.getMultiplier(rcLevel, rune, runecraftingFormulaRevision, lumbridgeDiary); @@ -337,7 +335,7 @@ public final class RuneCraftPulse extends SkillPulse { } } - if(multipleLevels.length > i && runecraftingFormulaRevision >= 573) { + if (multipleLevels.length > i && runecraftingFormulaRevision >= 573) { int a = Math.max(multipleLevels[i-1], rune.getLevel()); int b = multipleLevels[i]; if(b <= 99 || runecraftingFormulaRevision >= 581) { @@ -374,5 +372,4 @@ public final class RuneCraftPulse extends SkillPulse { public Altar getAltar() { return altar; } - } From a932c309b303057675ef6369ecc1532ae4832492 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 13:52:46 +0000 Subject: [PATCH 163/306] Fixed bug where ultimate ironmen could have rewards sent to bank Fixed the allquest command on new accounts on first login --- .../summoning/familiar/FamiliarManager.java | 19 +++++++----- .../minigame/fishingtrawler/TrawlerLoot.kt | 29 ++++++++++++++----- Server/src/main/core/api/ContentAPI.kt | 4 +-- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java index 02bb0a403..888fa8f3e 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java +++ b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java @@ -69,19 +69,19 @@ public final class FamiliarManager { } public void parse(JSONObject familiarData) { - for (Pets pet : Pets.values()) { - for (int id : new int[]{pet.getBabyItemId(), pet.getGrownItemId(), pet.getOvergrownItemId()}) { - if (id != -1) { - petDetails.put(id, new ArrayList()); - } - } - } - int currentPet = -1; if (familiarData.containsKey("currentPet")) { currentPet = Integer.parseInt(familiarData.get("currentPet").toString()); } if (player.version < 2) { //migrate the v1 format + for (Pets pet : Pets.values()) { + for (int id : new int[]{pet.getBabyItemId(), pet.getGrownItemId(), pet.getOvergrownItemId()}) { + if (id != -1) { + petDetails.put(id, new ArrayList()); + } + } + } + JSONArray petDetails = (JSONArray) familiarData.get("petDetails"); for (Object petDetail : petDetails) { JSONObject detail = (JSONObject) petDetail; @@ -267,6 +267,9 @@ public final class FamiliarManager { player.getDialogueInterpreter().sendDialogue("You need a summoning level of " + pets.getSummoningLevel() + " to summon this."); return false; } + if (!this.petDetails.containsKey(itemId)) { + petDetails.put(itemId, new ArrayList()); + } int last = this.petDetails.get(itemId).size() - 1; if (last < 0) { //new pet last = 0; diff --git a/Server/src/main/content/minigame/fishingtrawler/TrawlerLoot.kt b/Server/src/main/content/minigame/fishingtrawler/TrawlerLoot.kt index 8511a1810..87ed06dbe 100644 --- a/Server/src/main/content/minigame/fishingtrawler/TrawlerLoot.kt +++ b/Server/src/main/content/minigame/fishingtrawler/TrawlerLoot.kt @@ -1,8 +1,12 @@ package content.minigame.fishingtrawler import content.global.skill.fishing.Fish +import core.api.Container +import core.api.addItem +import core.api.addItemOrDrop import core.api.splitLines import core.game.node.entity.player.Player +import core.game.node.entity.player.link.IronmanMode import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.game.node.item.WeightedChanceItem @@ -57,25 +61,34 @@ object TrawlerLoot { @JvmStatic fun addLootAndMessage(player: Player, fishLevel: Int, rolls: Int, skipJunk: Boolean) { if (rolls < 1) return - val frequencyList = listOf>(HashMap(), HashMap(), HashMap()) + val frequencyList = listOf>(HashMap(), HashMap(), HashMap()) getLoot(fishLevel, rolls, skipJunk).forEach { - if (!player.bank.add(it)) GroundItemManager.create(it, player) when (it.id) { - in trawlerFishIds -> frequencyList[0].merge(it.name, 1, Int::plus) - in trawlerMisc -> frequencyList[1].merge(it.name, 1, Int::plus) - in junkItems -> frequencyList[2].merge(it.name, 1, Int::plus) + in trawlerFishIds -> frequencyList[0].merge(it.id, 1, Int::plus) + in trawlerMisc -> frequencyList[1].merge(it.id, 1, Int::plus) + in junkItems -> frequencyList[2].merge(it.id, 1, Int::plus) } } - player.sendMessage(colorize("%RYour reward has been sent to your bank:")) - // Extract and join each frequency maps entries as string. Split based on length, then send each line as message. + // Extract and join each frequency map's entries as items frequencyList.forEachIndexed { idx, fMap -> if (fMap.isNotEmpty()) { + // Give reward + fMap.forEach { + if (player.ironmanManager.mode == IronmanMode.ULTIMATE || !addItem(player, it.key, it.value, Container.BANK)) { + val notedIdIfFish = if (idx == 0) it.key + 1 else it.key + addItemOrDrop(player, notedIdIfFish, it.value) + } + } + // Split based on length, then send each line as message splitLines( - fMap.entries.joinToString(prefix = if (idx == 0) "Fish: " else if (idx == 1) "Misc: " else "Junk: ", postfix = ".") { "${it.key}: ${it.value}" }, + fMap.entries.joinToString(prefix = if (idx == 0) "Fish: " else if (idx == 1) "Misc: " else "Junk: ", postfix = ".") { "${Item(it.key).name}: ${it.value}" }, 85 ).forEach { player.sendMessage(it) } } } + if (player.ironmanManager.mode != IronmanMode.ULTIMATE) { + player.sendMessage(colorize("%RYour reward has been sent to your bank:")) + } } private val lootTable = arrayOf( diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 6a97979c1..b4e936906 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -448,9 +448,9 @@ fun addItemOrDrop(player: Player, id: Int, amount: Int = 1) { fun addItemOrBank(player: Player, id: Int, amount: Int = 1) { val item = Item(id, amount) if (!player.inventory.add(item)) { - if (player.bankPrimary.add(item)) { + if (player.ironmanManager.mode != IronmanMode.ULTIMATE && player.bankPrimary.add(item)) { sendMessage(player, colorize("%RThe ${item.name} has been sent to your bank.")) - } else if (player.bankSecondary.add(item)) { + } else if (player.ironmanManager.mode != IronmanMode.ULTIMATE && player.bankSecondary.add(item)) { sendMessage(player, colorize("%RThe ${item.name} has been sent to your secondary bank.")) } else { GroundItemManager.create(item, player) From 3838f01adf7b78af3061438ccac1e01c9cd9a63f Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 13:54:34 +0000 Subject: [PATCH 164/306] Made POH deaths safer, fixing random event bug --- .../src/main/content/global/skill/construction/HouseZone.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index 7157912ae..860b38e03 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -81,8 +81,9 @@ public final class HouseZone extends MapZone { if (e instanceof Player) { Player p = (Player) e; HouseManager.leave(p); + return true; } - return true; + return super.death(e, killer); } @Override From f75577d41d7b0c3050c0207e4fbf5d706f778cc9 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 20 Jan 2025 13:56:18 +0000 Subject: [PATCH 165/306] ::itemsearch now usable by everyone --- .../main/core/game/system/command/sets/DevelopmentCommandSet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index 0e4efde67..dbf032a3c 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -213,7 +213,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { } } - define("itemsearch") {player, args -> + define("itemsearch", Privilege.STANDARD, "itemsearch name", "Searches for items that match the name.") {player, args -> val itemName = args.copyOfRange(1, args.size).joinToString(" ").lowercase() for (i in 0 until 15000) { val name = getItemName(i).lowercase() From 00b5a44c31453e37e4cc33764d34dc9f51f41ee9 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 12:23:10 +0000 Subject: [PATCH 166/306] Added additional dialogue helpers --- .../lumbridge/dialogue/DonieDialogue.kt | 10 +- .../core/game/dialogue/DialogueLabeller.kt | 141 ++++++++++++++++-- 2 files changed, 133 insertions(+), 18 deletions(-) diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt index 7626499b9..d699af8c3 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DonieDialogue.kt @@ -30,7 +30,7 @@ class DonieDialogueFile : DialogueLabeller() { options( DialogueOption("whereami", "Where am I?", expression = ChatAnim.THINKING), DialogueOption("howareyou", "How are you today?"), - DialogueOption("shoelace", "Your shoe lace is untied."), + DialogueOption("shoelace", "Your shoe lace is untied.", skipPlayer=true), ) label("whereami") @@ -45,9 +45,15 @@ class DonieDialogueFile : DialogueLabeller() { npc("Not just a pretty face eh? Ha ha ha.") label("shoelace") + open(player!!, DonieDialogueShoelaceFile(), npc!!) + + } +} +class DonieDialogueShoelaceFile : DialogueLabeller() { + override fun addConversation() { + player("Your shoe lace is untied.") npc(ChatAnim.ANGRY, "No it's not!") player("No you're right. I have nothing to back that up.") npc(ChatAnim.ANGRY, "Fool! Leave me alone!") - } } \ No newline at end of file diff --git a/Server/src/main/core/game/dialogue/DialogueLabeller.kt b/Server/src/main/core/game/dialogue/DialogueLabeller.kt index b36c5ccae..6a48b86ae 100644 --- a/Server/src/main/core/game/dialogue/DialogueLabeller.kt +++ b/Server/src/main/core/game/dialogue/DialogueLabeller.kt @@ -2,6 +2,7 @@ package core.game.dialogue import core.api.InputType import core.api.face +import core.api.openDialogue import core.api.splitLines import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player @@ -13,12 +14,12 @@ typealias ChatAnim = FacialExpression typealias InputType = InputType /** Create container class DialogueOption for [DialogueLabeller.options] */ class DialogueOption( - val goto: String, - val option: String, - val spokenText: String = option, - val expression: ChatAnim = ChatAnim.NEUTRAL, - val skipPlayer: Boolean = false, - val callback: ((player: Player, npc: NPC) -> Boolean)? = null + val goto: String, // Required: Label to go to if player selects option. + val option: String, // Required: Printed text on the option list. + val spokenText: String = option, // Optional: Option selected will be spoken text unless provided here. + val expression: ChatAnim = ChatAnim.NEUTRAL, // Optional: Player expression to show. + val skipPlayer: Boolean = false, // Optional: Skips the player spoken text (if wildly different) + val optionIf: ((player: Player, npc: NPC) -> Boolean)? = null // Optional: Function to show/not show option. ) /** @@ -32,7 +33,7 @@ class DialogueOption( * * ! WARNING: DO NOT use functions in DialogueFile as it will cause unexpected behavior. * - * Example: [content.region.misthalin.lumbridge.dialogue.RangedTutorDialogue] + * ! HELP: There are snippets below that you can copy and modify to use as part of your code. */ abstract class DialogueLabeller : DialogueFile() { @@ -41,11 +42,12 @@ abstract class DialogueLabeller : DialogueFile() { * Makes NPC stop in its tracks and look at player. * An alternative to setting up DialoguePlugin(player) to be used in InteractionListener. */ - fun captureNPC(player: Player, npc: NPC) { + fun open(player: Player, dialogue: Any, npc: NPC) { face(npc, player.location) npc.setDialoguePlayer(player) // This prevents random walking in [NPC.java handleTickActions()] npc.getWalkingQueue().reset() npc.getPulseManager().clear() + openDialogue(player, dialogue, npc) } } @@ -74,7 +76,7 @@ abstract class DialogueLabeller : DialogueFile() { /** Helper function to create an individual stage for each of the dialogue stages. */ private fun assignIndividualStage(callback: () -> Unit) { if (startingStage == null) { startingStage = 0 } - if (stage == dialogueCounter) { // Run this stage when the stage equals to the dialogueCounter of this dialogue + if (stage == dialogueCounter && jumpTo == null) { // Run this stage when the stage equals to the dialogueCounter of this dialogue callback() // CALLBACK FUNCTION super.stage++ // Increment the stage to the next stage (only applies after a pass) stageHit = true // Flag that the stage was hit, so that it doesn't close the dialogue @@ -97,15 +99,16 @@ abstract class DialogueLabeller : DialogueFile() { fun assignToIds(npcid: Int) { /* super.npc = NPC(npcid) */ } /** Marks the start of a series of dialogue that can be jumped to using a [goto]. */ - fun label(label: String) { + fun label(label: String, nesting: () -> Unit = {}) { if (startingStage == null) { startingStage = 1 } dialogueCounter++ labelStageMap[label] = dialogueCounter + nesting() } /** Jumps to a [label] after a series of dialogue. */ fun goto(label: String) { - if (stage == dialogueCounter) { + if (stage == dialogueCounter && jumpTo == null) { jumpTo = labelStageMap[label] } } @@ -122,11 +125,16 @@ abstract class DialogueLabeller : DialogueFile() { */ fun exec(callback: (player: Player, npc: NPC) -> Unit) { if (startingStage == null) { startingStage = 0 } - if (stage == dialogueCounter) { + if (stage == dialogueCounter && jumpTo == null) { callback(player!!, npc!!) } } + /** Manual stage. For custom creation of an individual stage. Must call interpreter in some form. **/ + fun manual(callback: (player: Player, npc: NPC) -> Unit) { + assignIndividualStage { callback(player!!, npc!!) } + } + /** Dialogue player/playerl. Shows player chathead with text. **/ fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { assignIndividualStage { interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) } @@ -143,9 +151,13 @@ abstract class DialogueLabeller : DialogueFile() { assignIndividualStage { interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) } } /** Dialogue npc/npcl. Shows npcId chathead with text. **/ - fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int, vararg messages: String) { + fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int = npc!!.id, vararg messages: String) { assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) } } + /** Dialogue npc/npcl. Shows npcId chathead with text. **/ + fun npc(npcId: Int = npc!!.id, vararg messages: String) { + assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), ChatAnim.NEUTRAL, *formatMessages(messages)) } + } /** Dialogue npc/npcl. Shows npc chathead with text. **/ fun npc(vararg messages: String) { npc(ChatAnim.NEUTRAL, *messages) } @Deprecated("Use npc() instead.", ReplaceWith("npc(chatAnim, *messages)")) @@ -175,7 +187,7 @@ abstract class DialogueLabeller : DialogueFile() { /** Dialogue option. Shows the option dialogue with choices for the user to select. **/ fun options(vararg options: DialogueOption, title: String = "Select an Option") { // Filter out options that aren't shown. - val filteredOptions = options.filter{ if (it.callback != null) { it.callback.invoke(player!!, npc!!) } else { true } } + val filteredOptions = options.filter{ if (it.optionIf != null) { it.optionIf.invoke(player!!, npc!!) } else { true } } // Stage Part 1: Options List Dialogue assignIndividualStage { interpreter!!.sendOptions(title, *filteredOptions.map{ it.option }.toTypedArray()) } // Stage Part 2: Show spoken text. @@ -211,9 +223,10 @@ abstract class DialogueLabeller : DialogueFile() { if (type == InputType.AMOUNT) { player!!.setAttribute("parseamount", true) } + // This runscript is the same runscript as the one in ContentAPI sendInputDialogue player!!.setAttribute("runscript") { value: Any -> optInput = value - // The next line is a hack. Because this prompt is overlays the actual chatbox, we trigger the next dialogue with a call to handle. + // The next line is a hack. Because this prompt overlays the actual chat box, we trigger the next dialogue with a call to handle. interpreter!!.handle(player!!.interfaceManager.chatbox.id, 2) } player!!.setAttribute("input-type", type) @@ -222,6 +235,16 @@ abstract class DialogueLabeller : DialogueFile() { /** Dialogue input. Shows the input dialogue with an input box for the user to type in. Read [optInput] in an [exec] function for the value. **/ fun input(numeric: Boolean, prompt: String = "Enter the amount") { input( if (numeric) { InputType.NUMERIC } else { InputType.STRING_SHORT }, prompt) } + /** Calls another dialogue file. Always use this to open another dialogue file instead of calling openDialogue() in exec{} due to interfaces clashing. **/ + fun open(player: Player, dialogue: Any, vararg args: Any) { + assignIndividualStage { core.api.openDialogue(player, dialogue, *args) } + } + + /** WARNING: DIALOGUE LABELLER WILL BREAK IN CERTAIN FUNCTIONS. USE open() instead. */ + fun openDialogue(player: Player, dialogue: Any, vararg args: Any) { + core.api.openDialogue(player, dialogue, *args) + } + /** Hook onto the handle function of DialogueFile. This function gets called every loop with a super.stage. */ override fun handle(componentID: Int, buttonID: Int) { this.buttonID = buttonID @@ -248,4 +271,90 @@ abstract class DialogueLabeller : DialogueFile() { } if (!stageHit) { end() } // If a dialogue stage is not hit, end the dialogues. } -} \ No newline at end of file +} + +/* +// COPY PASTA SNIPPETS SECTION FOR QUICK BOILERPLATES + +// STANDARD: Initializing with DialoguePlugin. +@Initializable +class DonieDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return DonieDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, DonieDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.DONIE_2238) + } +} +class DonieDialogueFile : DialogueLabeller() { + override fun addConversation() { + assignToIds(NPCs.DONIE_2238) + + npc(ChatAnim.FRIENDLY, "Hello there, can I help you?") + goto("nowhere") + } +} + +// NEW! (EXPERIMENTAL): Initializing with InteractionListener. +class SomeDudeDialogue : InteractionListener { + override fun defineListeners() { + on(NPCs.PRIEST_OF_GUTHIX_8555, IntType.NPC, "talk-to") { player, node -> + DialogueLabeller.open(player, SomeDudeDialogueLabellerFile(), node as NPC) + return@on true + } + } +} + +// Exec with quest stage branches. +exec { player, npc -> + when(getQuestStage(player, SomeQuest.questName)) { + 100 -> loadLabel(player, "SomeQuestStage100") + 10, 20 -> loadLabel(player, "SomeQuestStage10") + else -> { + loadLabel(player, "SomeQuestStage0") + } + } +} + +// Exec to move quest stage up. +exec { player, npc -> + if (getQuestStage(player, SomeQuest.questName) == 0) { + setQuestStage(player, SomeQuest.questName, 10) + } +} + +// Exec to add item, set attribute. +exec { player, npc -> + if (removeItem(player, Items.ITEM_1)) { + addItemOrDrop(player, Items.ITEM_2) + } + if (getAttribute(player, attributeSomething, null) == null) { + setAttribute(player, attributeSomething, player.location) + } +} + +// Open to another dialogue file. +npc("I'm going to another file.") +open(player!!, SomeDialogueFile2(), npc!!) +... +class SomeDialogueFile2 : DialogueLabeller() { + override fun addConversation() { + npc("This is another file.") + } +} + +// Options with all the different controls. +options( + DialogueOption("Label1", "Line 1 Say", expression=ChatAnim.THINKING), + DialogueOption("Label2", "Line 2 Huh", skipPlayer=true), + DialogueOption("Label3", "Line 3 Blah", spokenText="I say something else", expression=ChatAnim.FRIENDLY), + DialogueOption("Label4", "Line 4 What") { player, npc -> + return@DialogueOption false // Don't show + } +) + +*/ \ No newline at end of file From e34a81ec6cd8402a5af49d6f8e82a4ff1f70d5e6 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 12:29:51 +0000 Subject: [PATCH 167/306] Implemented Heroes Quest --- Server/data/configs/door_configs.json | 4 +- Server/data/configs/drop_tables.json | 20 ++ Server/data/configs/item_configs.json | 2 +- Server/data/configs/npc_configs.json | 2 +- Server/data/configs/npc_spawns.json | 6 +- .../content/data/consumables/Consumables.java | 2 +- .../main/content/global/skill/fishing/Fish.kt | 2 +- .../burthorpe/dialogue/AchiettiesDialogue.kt | 39 --- .../burthorpe/dialogue/HelemosDialogue.kt | 47 ++++ .../quest/heroesquest/AchiettiesDialogue.kt | 179 ++++++++++++ .../heroesquest/AlfonseTheWaiterDialogue.kt | 59 ++++ .../heroesquest/CharlieTheCookDialogue.kt | 84 ++++++ .../quest/heroesquest/GarvDialogue.kt | 72 +++++ .../quest/heroesquest/GerrantDialogue.kt | 65 +++++ .../quest/heroesquest/GripBehavior.kt | 58 ++++ .../quest/heroesquest/GripDialogue.kt | 118 ++++++++ .../quest/heroesquest/GruborDialogue.kt | 84 ++++++ .../quest/heroesquest/HeroesQuest.kt | 262 ++++++++++++++++++ .../quest/heroesquest/HeroesQuestListener.kt | 154 ++++++++++ .../quest/heroesquest/KatrineDialogueFile.kt | 126 +++++++++ .../quest/heroesquest/StravenDialogueFile.kt | 72 +++++ .../quest/heroesquest/TrobertDialogue.kt | 91 ++++++ .../portsarim/dialogue/GerrantDialogue.java | 82 ------ .../dialogue/AlfonseWaiterDialogue.java | 92 ------ .../brimhaven/dialogue/GarvDialogue.java | 88 ------ .../brimhaven/dialogue/GruborDialogue.java | 99 ------- .../brimhaven/handlers/BrimhavenListeners.kt | 30 -- .../quest/shieldofarrav/KatrineDialogue.java | 15 +- .../quest/shieldofarrav/ShieldofArrav.java | 16 ++ .../quest/shieldofarrav/StravenDialogue.java | 11 + .../link/request/trade/TradeContainer.java | 3 +- 31 files changed, 1542 insertions(+), 442 deletions(-) delete mode 100644 Server/src/main/content/region/asgarnia/burthorpe/dialogue/AchiettiesDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/dialogue/HelemosDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt create mode 100644 Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt delete mode 100644 Server/src/main/content/region/asgarnia/portsarim/dialogue/GerrantDialogue.java delete mode 100644 Server/src/main/content/region/karamja/brimhaven/dialogue/AlfonseWaiterDialogue.java delete mode 100644 Server/src/main/content/region/karamja/brimhaven/dialogue/GarvDialogue.java delete mode 100644 Server/src/main/content/region/karamja/brimhaven/dialogue/GruborDialogue.java diff --git a/Server/data/configs/door_configs.json b/Server/data/configs/door_configs.json index 8d6a61db5..50cf42836 100644 --- a/Server/data/configs/door_configs.json +++ b/Server/data/configs/door_configs.json @@ -301,7 +301,7 @@ }, { "id": "2025", - "replaceId": "1534", + "replaceId": "2026", "fence": "false", "metal": "false" }, @@ -925,7 +925,7 @@ }, { "id": "3747", - "replaceId": "1534", + "replaceId": "3748", "fence": "false", "metal": "false" }, diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 8aff52d67..ec5ee681a 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -58865,6 +58865,26 @@ "description": "Ram", "main": [] }, + { + "default": [ + { + "minAmount": "1", + "weight": "1.0", + "id": "526", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "1583", + "maxAmount": "1" + } + ], + "charm": [], + "ids": "6108", + "description": "", + "main": [] + }, { "default": [], "charm": [], diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 9261394b7..91c5fc970 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -16869,7 +16869,7 @@ "id": "1583" }, { - "examine": "Apparently my name is Hartigan", + "examine": "Apparently my name is Hartigen.", "durability": null, "name": "Id papers", "tradeable": "false", diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 410e5e31f..aa9d10c4a 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -52638,7 +52638,7 @@ "name": "Entrana firebird", "defence_level": "1", "safespot": null, - "lifepoints": "1", + "lifepoints": "5", "strength_level": "1", "id": "6108", "range_level": "1", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 4ccdde965..99aba5be0 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -2217,11 +2217,11 @@ }, { "npc_id": "789", - "loc_data": "{2811,3167,0,0,0}-" + "loc_data": "{2811,3167,0,1,0}-" }, { "npc_id": "792", - "loc_data": "{2774,3197,0,0,0}-" + "loc_data": "{2774,3197,0,1,0}-" }, { "npc_id": "793", @@ -4413,7 +4413,7 @@ }, { "npc_id": "1884", - "loc_data": "{2811,3174,0,0,0}-" + "loc_data": "{2811,3174,0,1,0}-" }, { "npc_id": "1902", diff --git a/Server/src/main/content/data/consumables/Consumables.java b/Server/src/main/content/data/consumables/Consumables.java index 7b217c81a..89e90496a 100644 --- a/Server/src/main/content/data/consumables/Consumables.java +++ b/Server/src/main/content/data/consumables/Consumables.java @@ -52,7 +52,7 @@ public enum Consumables { COOKED_JUBBLY(new Food(new int[] {7568}, new HealingEffect(15))), BASS(new Food(new int[] {365}, new HealingEffect(13))), SWORDFISH(new Food(new int[] {373}, new HealingEffect(14))), - LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(14))), + LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(11))), MONKFISH(new Food(new int[] {7946}, new HealingEffect(16))), SHARK(new Food(new int[] {385}, new HealingEffect(20))), SEA_TURTLE(new Food(new int[] {397}, new HealingEffect(21))), diff --git a/Server/src/main/content/global/skill/fishing/Fish.kt b/Server/src/main/content/global/skill/fishing/Fish.kt index 46b73bee2..8ccc67f24 100644 --- a/Server/src/main/content/global/skill/fishing/Fish.kt +++ b/Server/src/main/content/global/skill/fishing/Fish.kt @@ -24,7 +24,7 @@ enum class Fish(val id: Int, val level: Int, val experience: Double, val lowChan LOBSTER(Items.RAW_LOBSTER_377, 40, 90.0, 0.16, 0.375), BASS(Items.RAW_BASS_363, 46, 100.0, 0.078, 0.16), SWORDFISH(Items.RAW_SWORDFISH_371, 50, 100.0, 0.105, 0.191), - LAVA_EEL(Items.RAW_LAVA_EEL_2148, 53, 30.0, 0.227, 0.379), + LAVA_EEL(Items.RAW_LAVA_EEL_2148, 53, 60.0, 0.227, 0.379), MONKFISH(Items.RAW_MONKFISH_7944, 62, 120.0, 0.293, 0.356), KARAMBWAN(Items.RAW_KARAMBWAN_3142, 65, 105.0, 0.414, 0.629), SHARK(Items.RAW_SHARK_383, 76, 110.0, 0.121, 0.16), diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/AchiettiesDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/AchiettiesDialogue.kt deleted file mode 100644 index a4585b87e..000000000 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/AchiettiesDialogue.kt +++ /dev/null @@ -1,39 +0,0 @@ -import core.api.openDialogue -import core.game.dialogue.DialogueBuilder -import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.plugin.Initializable -import org.rs09.consts.NPCs - -/** - * @author qmqz - * @author Trident101 - */ - -@Initializable -class AchiettiesDialogue(player: Player? = null) : DialoguePlugin(player){ - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - openDialogue(player, AchiettiesDialogueFile(), npc) - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { - return AchiettiesDialogue(player) - } - - override fun getIds(): IntArray { - return intArrayOf(NPCs.ACHIETTIES_796) - } -} - -class AchiettiesDialogueFile : DialogueBuilderFile() { - - override fun create(b: DialogueBuilder) { - b.defaultDialogue().npcl(FacialExpression.FRIENDLY, - "Greetings. Welcome to the Heroes' Guild." - ) - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HelemosDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HelemosDialogue.kt new file mode 100644 index 000000000..aede4cd5f --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HelemosDialogue.kt @@ -0,0 +1,47 @@ +package content.region.asgarnia.burthorpe.dialogue + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class HelemosDialogue(player: Player? = null) : DialoguePlugin(player){ + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, HelemosDialogueFile(), npc) + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return HelemosDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.HELEMOS_797) + } +} +class HelemosDialogueFile : DialogueBuilderFile() { + + override fun create(b: DialogueBuilder) { + + b.onPredicate { _ -> true } + .npc("Welcome to the Heroes' Guild!") + .options() + .let { optionBuilder -> + optionBuilder.option("So do you sell anything here?") + .playerl("So do you sell anything good here?") + .npcl("Why yes! We DO run an exclusive shop for our members!") + .endWith { _, player -> + openNpcShop(player, NPCs.HELEMOS_797) + end() + } + optionBuilder.option_playerl("So what can I do here?") + .npcl("Look around... there are all sorts of things to keep our guild members entertained!") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt new file mode 100644 index 000000000..4d23b5ad2 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt @@ -0,0 +1,179 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class AchiettiesDialogue(player: Player? = null) : DialoguePlugin(player){ + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, AchiettiesDialogueFile(), npc) + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return AchiettiesDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.ACHIETTIES_796) + } +} + +class AchiettiesDialogueFile : DialogueBuilderFile() { + + override fun create(b: DialogueBuilder) { + + b.onQuestStages(HeroesQuest.questName, 0,1) + .branch { player -> + return@branch getQuestStage(player, HeroesQuest.questName) + }.let{ branch -> + branch.onValue(0) + .npcl(FacialExpression.FRIENDLY, "Greetings. Welcome to the Heroes' Guild.") + .npcl("Only the greatest heroes of this land may gain entrance to this guild.") + // - If the player's skill levels are lower than the quest requirements. (I think this is after 2009) + // linel("Before starting this quest, be aware that one or more of your skill levels are lower than what is required to fully complete it.") + .options() + .let { optionBuilder -> + optionBuilder.option("I'm a hero, may I apply to join?") + .playerl("I'm a hero. May I apply to join?") + .branch { player -> + return@branch if (HeroesQuest.hasRequirements(player)) { + 1 + } else { + 0 + } + }.let { branch -> + branch.onValue(0) + .npcl("You're a hero? I've never heard of YOU. You are required to possess at least 55 quest points to file an application.") + .npcl("Additionally you must have completed the Shield of Arrav, Lost City, Merlin's Crystal and Dragon Slayer quests.") + .end() + return@let branch + }.onValue(1) + .betweenStage { df, player, _, _ -> + if(getQuestStage(player, HeroesQuest.questName) == 0) { + setQuestStage(player, HeroesQuest.questName, 1) + } + } + .npcl("Well you seem to meet our initial requirements, so you may now begin the tasks to earn membership in the Heroes' Guild.") + .npcl("The three items required for entrance are: An Entranan Firebird feather, a Master Thieves' armband, and a cooked Lava Eel.") + .options() + .let { optionBuilder2 -> + optionBuilder2.option_playerl("Any hints on getting the thieves armband?") + .npcl("I'm sure you have the relevant contacts to find out about that.") + .end() + optionBuilder2.option_playerl("Any hints on getting the feather?") + .npcl("Not really - other than Entranan firebirds tend to live on Entrana.") + .end() + optionBuilder2.option_playerl("Any hints on getting the eel?") + .npcl("Maybe go and find someone who knows a lot about fishing?") + .end() + optionBuilder2.option_playerl("I'll start looking for all those things then.") + .npcl("Good luck with that.") + .end() + } + + optionBuilder.option_playerl("Good for the foremost heroes of the land.") + .npcl("Yes. Yes it is.") + .end() + } + branch.onValue(1) + .npcl("Greetings. Welcome to the Heroes' Guild.") + .npcl("How goes thy quest adventurer?") + .playerl("It's tough. I've not done it yet.") + .npcl("Remember, the items you need to enter are:") + .npcl("An Entranan Firebirds' feather, A Master Thieves armband, and a cooked Lava Eel.") + .options() + .let { optionBuilder2 -> + optionBuilder2.option_playerl("Any hints on getting the thieves armband?") + .npcl("I'm sure you have the relevant contacts to find out about that.") + .end() + optionBuilder2.option_playerl("Any hints on getting the feather?") + .npcl("Not really - other than Entranan firebirds tend to live on Entrana.") + .end() + optionBuilder2.option_playerl("Any hints on getting the eel?") + .npcl("Maybe go and find someone who knows a lot about fishing?") + .end() + optionBuilder2.option_playerl("I'll start looking for all those things then.") + .npcl("Good luck with that.") + .end() + } + } + + b.onQuestStages(HeroesQuest.questName, 2,3,4) + .npcl("Greetings. Welcome to the Heroes' Guild.") + .npcl("How goes thy quest adventurer?") + .playerl("It's tough. I've not done it yet.") + .npcl("Remember, the items you need to enter are:") + .npcl("An Entranan Firebirds' feather, A Master Thieves armband, and a cooked Lava Eel.") + .options() + .let { optionBuilder2 -> + optionBuilder2.option_playerl("Any hints on getting the thieves armband?") + .npcl("I'm sure you have the relevant contacts to find out about that.") + .end() + optionBuilder2.option_playerl("Any hints on getting the feather?") + .npcl("Not really - other than Entranan firebirds tend to live on Entrana.") + .end() + optionBuilder2.option_playerl("Any hints on getting the eel?") + .npcl("Maybe go and find someone who knows a lot about fishing?") + .end() + optionBuilder2.option_playerl("I'll start looking for all those things then.") + .npcl("Good luck with that.") + .end() + } + + b.onQuestStages(HeroesQuest.questName, 6) + .npcl("Greetings. Welcome to the Heroes' Guild.") + .npcl("How goes thy quest adventurer?") + .branch { player -> + return@branch if (HeroesQuest.allItemsInInventory(player)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .playerl("It's tough. I've not done it yet.") + .npcl("Remember, the items you need to enter are:") + .npcl("An Entranan Firebirds' feather, A Master Thieves armband, and a cooked Lava Eel.") + .options() + .let { optionBuilder2 -> + optionBuilder2.option_playerl("Any hints on getting the thieves armband?") + .npcl("I'm sure you have the relevant contacts to find out about that.") + .end() + optionBuilder2.option_playerl("Any hints on getting the feather?") + .npcl("Not really - other than Entranan firebirds tend to live on Entrana.") + .end() + optionBuilder2.option_playerl("Any hints on getting the eel?") + .npcl("Maybe go and find someone who knows a lot about fishing?") + .end() + optionBuilder2.option_playerl("I'll start looking for all those things then.") + .npcl("Good luck with that.") + .end() + } + + branch.onValue(1) + .playerl("I have all the required items.") + .npcl("I see that you have. Well done. Now, to complete the quest, and gain entry to the Heroes' Guild in your final task all that you have to do is...") + .playerl("W-what? What do you mean? There's MORE?") + .npcl("I'm sorry, I was just having a little fun with you. Just a little Heroes' Guild humour there. What I really meant was") + .npcl("Congratulations! You have completed the Heroes' Guild entry requirements! You will find the door now open for you! Enter, Hero! And take this reward!") + .endWith { _, player -> + if (HeroesQuest.allItemsInInventory(player)) { + removeItem(player, Items.FIRE_FEATHER_1583) + removeItem(player, Items.LAVA_EEL_2149) + removeItem(player, Items.THIEVES_ARMBAND_1579) + if (getQuestStage(player, HeroesQuest.questName) == 6) { + finishQuest(player, HeroesQuest.questName) + } + } + } + } + + b.onQuestStages(HeroesQuest.questName, 100) + .npcl("Greetings. Welcome to the Heroes' Guild.") + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt new file mode 100644 index 000000000..41395fd1e --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt @@ -0,0 +1,59 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.getQuestStage +import core.api.openDialogue +import core.api.openNpcShop +import core.api.setQuestStage +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class AlfonseTheWaiterDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return AlfonseTheWaiterDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, AlfonseTheWaiterDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.ALFONSE_THE_WAITER_793) + } +} +class AlfonseTheWaiterDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onPredicate { _ -> true } + .npc("Welcome to the Shrimp and Parrot.", "Would you like to order, sir?") + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Yes please.") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + + optionBuilder.option_playerl("No thank you.") + .end() + + optionBuilder.optionIf("Do you sell Gherkins?"){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 2 && HeroesQuest.isPhoenix(player) } + .playerl("Do you sell Gherkins?") + .npc("Hmmmm Gherkins eh? Ask Charlie the cook, round the", "back. He may have some 'gherkins' for you!") + .linel("Alfonse winks at you.") + .endWith { _, player -> + if(getQuestStage(player, HeroesQuest.questName) == 2) { + setQuestStage(player, HeroesQuest.questName, 3) + } + } + + optionBuilder.option("Where do you get your Karambwan from?") + .npc("We buy directly off Lubufu, a local fisherman. He", "seems to have a monopoly over Karambwan sales.") + .end() + + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt new file mode 100644 index 000000000..851dbfc6d --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt @@ -0,0 +1,84 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.getQuestStage +import core.api.openDialogue +import core.api.openNpcShop +import core.api.setQuestStage +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class CharlieTheCookDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return CharlieTheCookDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, CharlieTheCookDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.CHARLIE_THE_COOK_794) + } +} +class CharlieTheCookDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .npc(FacialExpression.ANGRY, "Hey! What are you doing back here?") + .options() + .let { optionBuilder -> + val continuePath = b.placeholder() + + optionBuilder.optionIf("I'm looking for a gherkin..."){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player) } + .playerl("I'm looking for a gherkin...") + .goto(continuePath) + + optionBuilder.optionIf("I'm a fellow member of the Phoenix Gang."){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player) } + .playerl("I'm a fellow member of the Phoenix Gang.") + .goto(continuePath) + + optionBuilder.option_playerl("Just exploring.") + .npcl(FacialExpression.ANGRY, "Well, get out! This kitchen isn't for exploring. It's a private establishment! It's out of bounds to customers!") + .end() + + return@let continuePath.builder() + } + .npcl("Ah, a fellow Phoenix! So, tell me compadre... What brings you to sunny Brimhaven?") + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Sun, sand, and the fresh sea air!") + .playerl("Sun, sand, and the fresh sea air!") + .npcl("Well, can't say I blame you, compadre. I used to be a city boy myself, but have to admit it's a lot nicer living here nowadays. Brimhaven's certainly good for it.") + .playerl("I also want to steal Scarface Pete's candlesticks.") + .npcl("Ah yes, of course. The candlesticks. Well, I have to be honest with you, compadre, we haven't made much progress in that task ourselves so far.") + .npcl("We can however offer a little assistance. Setting up this restaurant was the start of things; we have a secret door out the back of here that leads through the back of Cap'n Arnav's garden.") + .npcl("Now, at the other side of Cap'n Arnav's garden, is an old side entrance to Scarface Pete's mansion. It seems to have been blocked off from the rest of the mansion some years ago and we can't seem to find a way through.") + .npcl("We're positive this is the key to entering the house undetected, however, and I promise to let you know if we find anything there.") + .playerl("Mind if I check it out for myself?") + .npcl("Not at all! The more minds we have working on the problem, the quicker we get that loot!") + .endWith { _, player -> + if (getQuestStage(player, HeroesQuest.questName) == 3) { + setQuestStage(player, HeroesQuest.questName, 4) + } + } + + optionBuilder.option_playerl("I want to steal Scarface Pete's candlesticks.") + .npcl("Ah yes, of course. The candlesticks. Well, I have to be honest with you, compadre, we haven't made much progress in that task ourselves so far.") + .npcl("We can however offer a little assistance. Setting up this restaurant was the start of things; we have a secret door out the back of here that leads through the back of Cap'n Arnav's garden.") + .npcl("Now, at the other side of Cap'n Arnav's garden, is an old side entrance to Scarface Pete's mansion. It seems to have been blocked off from the rest of the mansion some years ago and we can't seem to find a way through.") + .npcl("We're positive this is the key to entering the house undetected, however, and I promise to let you know if we find anything there.") + .playerl("Mind if I check it out for myself?") + .npcl("Not at all! The more minds we have working on the problem, the quicker we get that loot!") + .endWith { _, player -> + if (getQuestStage(player, HeroesQuest.questName) == 3) { + setQuestStage(player, HeroesQuest.questName, 4) + } + } + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt new file mode 100644 index 000000000..90ece14be --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt @@ -0,0 +1,72 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.* +import core.game.global.action.DoorActionHandler +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class GarvDialogue(player: Player? = null) : DialoguePlugin(player){ + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GarvDialogueFile(), npc) + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return GarvDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.GARV_788) + } +} + +class GarvDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + // Technically this won't happen since you have to get past Grubor. + b.onQuestStages(HeroesQuest.questName, 0,1,2) + .npcl("Hello. What do you want?") + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Can I go in there?") + .npcl("No. In there is private.") + .end() + optionBuilder.option_playerl("I want for nothing!") + .npcl("You're one of a very lucky few then.") + .end() + } + + b.onQuestStages(HeroesQuest.questName, 3,4,5,6,100) + // .npcl("Oi! Where do you think you're going pal?") - When you click on the door instead of Garv. + .npcl("Hello. What do you want?") + .playerl("Hi. I'm Hartigen. I've come to work here.") + .branch { player -> + return@branch if (inEquipment(player, Items.BLACK_FULL_HELM_1165) && inEquipment(player, Items.BLACK_PLATEBODY_1125) && inEquipment(player, Items.BLACK_PLATELEGS_1077)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("I assume you have your I.D. papers then?") + .branch { player -> + return@branch if (inInventory(player, Items.ID_PAPERS_1584)) { 1 } else { 0 } + }.let { branch2 -> + branch2.onValue(1) + .npcl("You'd better come in then, Grip will want to talk to you.") + .endWith { _, player -> + if(getQuestStage(player, HeroesQuest.questName) == 3) { + setQuestStage(player, HeroesQuest.questName, 4) + } + } + branch2.onValue(0) + .playerl("Uh... Yeah. About that...I must have left them in my other suit of armour.") + .end() + } + branch.onValue(0) + .npcl("Hartigen the Black Knight? I don't think so. He doesn't dress like that.") + .end() + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt new file mode 100644 index 000000000..22341f133 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt @@ -0,0 +1,65 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class GerrantDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return GerrantDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GerrantDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.GERRANT_558) + } +} +class GerrantDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onPredicate { _ -> true } + .npc(FacialExpression.HAPPY, "Welcome! You can buy fishing equipment at my store.", "We'll also buy anything you catch off you.") + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Let's see what you've got then.") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + + optionBuilder.option_playerl("Sorry, I'm not interested.") + .end() + + optionBuilder.optionIf("I want to find out how to catch a lava eel.") { player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 1 } + .playerl("I want to find out how to catch a lava eel.") + .npcl("Lava eels, eh? That's a tricky one, that is. You'll need a lava-proof fishing rod. The method for making this would be to take an ordinary fishing rod, and then cover it with fire-proof blamish oil.") + .branch { player -> + return@branch if (inInventory(player, Items.BLAMISH_SNAIL_SLIME_1581)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("Of course, you knew that already.") + .playerl("So where can I fish lava eels?") + .npcl("Taverley dungeon or the lava maze in the Wilderness.") + .end() + + branch.onValue(0) + .npcl("You know... thinking about it... I may have a jar of blamish slime around here somewhere. Now where did I put it?") + .linel("Gerrant searches around a bit.") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.BLAMISH_SNAIL_SLIME_1581) + } + .npcl("Aha! Here it is! Take this slime, mix it with some Harralander and water and you'll have the blamish oil you need to treat your fishing rod.") + .end() + } + + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt new file mode 100644 index 000000000..b1103adea --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt @@ -0,0 +1,58 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.node.entity.Entity +import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.item.GroundItem +import core.game.node.item.GroundItemManager +import core.game.node.item.Item +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class GripBehavior : NPCBehavior(NPCs.GRIP_792) { + // Attacking Grip + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + // You cannot attack if you are a black arm gang member. + if (attacker is Player && HeroesQuest.isBlackArm(attacker)) { + openDialogue(attacker, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + //"I can't attack the head guard here! There are too", "many witnesses around to see me do it! I'd have the", "whole of Brimhaven after me! Besides, if he dies I want", "the promotion!" + START_DIALOGUE -> sendPlayerDialogue(attacker, "I can't attack the head guard here! There are too many witnesses around to see me do it! I'd have the whole of Brimhaven after me! Besides, if he dies I want the promotion!") .also { stage++ } + 1 -> sendDialogueLines(attacker, "Perhaps you need another player's help...?").also { + stage = END_DIALOGUE + } + } + } + }) + return false + } + return true + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + if (getQuestStage(killer, HeroesQuest.questName) == 4) { + setQuestStage(killer, HeroesQuest.questName, 5) + } + + val gi = GroundItem( + Item(Items.GRIPS_KEY_RING_1588), + self.location, + 5000, + null, + ) + gi.forceVisible = true + gi.isRemainPrivate = false + + val gim = GroundItemManager.create(gi) + gim.isRemainPrivate = false + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripDialogue.kt new file mode 100644 index 000000000..4146b03e6 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripDialogue.kt @@ -0,0 +1,118 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class GripDialogue(player: Player? = null) : DialoguePlugin(player){ + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GripDialogueFile(), npc) + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return GripDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.GRIP_792) + } +} + +class GripDialogueFile : DialogueBuilderFile() { + + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .branch { player -> + return@branch if (getAttribute(player, HeroesQuest.attributeGripTookPapers, false)) { 1 } else { 0 } + }.let { branch -> + val continuePath = b.placeholder() + branch.onValue(1) + .goto(continuePath) + branch.onValue(0) + .playerl("Hi there. I am Hartigen, reporting for duty as your new deputy sir!") + .npcl("Ah good, at last. You took your time getting here! Now let me see...") + .npcl("I'll get your hours and duty roster sorted out in a while. Oh, and do you have your I.D. papers with you? Internal security is almost as important as external security for a guard.") + .branch { player -> + return@branch if (inInventory(player, Items.ID_PAPERS_1584)) { 1 } else { 0 } + }.let { branch -> + val continuePath2 = b.placeholder() + branch.onValue(1) + .playerl("Right here sir!") + .linel("You hand the ID papers over to Grip.") + .betweenStage { df, player, _, _ -> + if (removeItem(player, Items.ID_PAPERS_1584)) { + setAttribute(player, HeroesQuest.attributeGripTookPapers, true) + } + } + .goto(continuePath2) + branch.onValue(0) + .playerl("Oh, dear. I don't have that with me any more.") + .npcl("Well, that's no good! Go get them immediately, then report back for duty.") + .end() + return@let continuePath2.builder() + } + .goto(continuePath) + return@let continuePath.builder() + } + .options() + .let { optionBuilder -> + val returnJoin = b.placeholder() + + optionBuilder.option_playerl("So can I please guard the treasure room please?") + .npcl("Well, I might post you outside it sometimes. I prefer to be the only one allowed inside however.") + .npcl("There's some pretty valuable artefacts in there! Those keys stay ONLY with the head guard and Scarface Pete.") + .goto(returnJoin) + + optionBuilder.optionIf("So what do my duties involve?") { player -> + return@optionIf !getAttribute(player, HeroesQuest.attributeGripSaidDuties, false) + } + .betweenStage { _, player, _, _ -> + setAttribute(player, HeroesQuest.attributeGripSaidDuties, true) + } + .playerl("So what do my duties involve?") + .npcl("You'll have various guard related duties on various shifts. I'll assign specific duties as they are required as and when they become necessary. Just so you know, if anything happens to me") + .npcl("you'll need to take over as head guard here. You'll find important keys to the treasure room and Pete's quarters inside my jacket - although I doubt anything bad's going to happen to") + .npcl("me anytime soon!") + .linel("Grip laughs to himself at the thought.") + .goto(returnJoin) + + optionBuilder.option_playerl("Well, I'd better sort my new room out.") + .npcl("Yeah, I'll give you time to settle in. Better get a good night's sleep, I expect you to report for duty at oh five hundred hours tomorrow on the dot!") + .end() + + + optionBuilder.optionIf("Anything I can do now?") { player -> + return@optionIf getAttribute(player, HeroesQuest.attributeGripSaidDuties, false) + } + .playerl("Anything I can do now?") + .branch { player -> + return@branch if (inInventory(player, Items.MISCELLANEOUS_KEY_1586)) { + 1 + } else { + 0 + } + }.let { branch -> + branch.onValue(1) + .npcl("Can't think of anything right now.") + .end() + + branch.onValue(0) + .npcl("Hmm. Well, you could find out what this key opens for me. Apparently it's for something in this building, but for the life of me I can't find what.") + .linel("Grip hands you a key.") + .endWith { _, player -> + addItemOrDrop(player, Items.MISCELLANEOUS_KEY_1586) + } + } + + returnJoin.builder() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt new file mode 100644 index 000000000..d1378dd9f --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt @@ -0,0 +1,84 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class GruborDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return GruborDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GruborDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.GRUBOR_789) + } +} + +class GruborDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onPredicate { player -> getQuestStage(player, HeroesQuest.questName) >= 2 && + getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && + HeroesQuest.isBlackArm(player) + } + .playerl("Hi.") + .npcl("Hi, I'm a little busy right now.") + .end() + + b.onPredicate { player -> getQuestStage(player, HeroesQuest.questName) >= 2 && + !getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && + HeroesQuest.isBlackArm(player) + } + .npcl(FacialExpression.THINKING, "Yes? What do you want?") + .options() + .let { optionBuilder -> + + optionBuilder.option_playerl("Rabbit's foot.") + .npcl("Eh? What are you on about? Go away!") + .end() + + optionBuilder.option_playerl("Four leaved clover.") + .npcl("Oh you're one of the gang are you? Ok, hold up a second, I'll just let you in through here.") + .linel("You hear the door being unbarred from inside.") + .endWith { _, player -> + setAttribute(player, HeroesQuest.attributeGruborLetsYouIn, true) + } + + optionBuilder.option_playerl("Lucky horseshoe.") + .npcl("Eh? What are you on about? Go away!") + .end() + + optionBuilder.option_playerl("Black cat.") + .npcl("Eh? What are you on about? Go away!") + .end() + } + + + b.onPredicate { _ -> true } + .npcl(FacialExpression.THINKING, "Yes? What do you want?") + .options() + .let { optionBuilder -> + + optionBuilder.option_playerl("Would you like your hedges trimming?") + .npcl("Eh? Don't be daft! We don't even HAVE any hedges!") + .end() + + optionBuilder.option_playerl("I want to come in.") + .npcl("No, go away.") + .end() + + optionBuilder.option_playerl("Do you want to trade?") + .npcl("No, I'm busy.") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt new file mode 100644 index 000000000..829dcc8ae --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt @@ -0,0 +1,262 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import content.region.misthalin.varrock.quest.shieldofarrav.ShieldofArrav +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items + +/** + * Heroes' Quest + */ +@Initializable +class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { + /** + * Do note: "other players can help you even if they have already finished Heroes' Quest" + * 1 - Talked to Achietties to start the quest + * + * PHOENIX + * 2 - Talked to Katrine + * 3 - Talked to Alfonse + * 4 - Talked to Charlie + * 5 - HIDDEN Killed Grip (You need key from Black Arm Friend) + * 6 - Talked to Katrine with Candlestick + * BLACK ARM + * 2 - Talked to Straven + * 3 - Talked to Trobert + * 4 - Talked to Garv + * 5 - HIDDEN Unlocked Chest (You need Grip killed from Phoenix Friend) + * 6 - Talked to Katrine with Candlestick + * + * 100 - Achiettes with all the items + */ + + companion object { + const val questName = "Heroes' Quest" + const val attributeGruborLetsYouIn = "/save:quest:heroesquest-gruborletsyouin" + const val attributeGripTookPapers = "/save:quest:heroesquest-griptookpapers" + const val attributeGripSaidDuties = "/save:quest:heroesquest-gripsaidduties" + const val attributeHasOpenedBackdoor = "/save:quest:heroesquest-hasopenedbackdoor" + const val attributeHasOpenedChestDoor = "/save:quest:heroesquest-hasopenedchestdoor" + + fun checkQuestsAreComplete(player: Player): Boolean { + return isQuestComplete(player, "Shield of Arrav") && + isQuestComplete(player, "Lost City") && + isQuestComplete(player, "Merlin's Crystal") && + isQuestComplete(player, "Dragon Slayer") && + getQuestPoints(player) >= 55 + } + + /** Abstraction of Shield of Arrav isPhoenix function */ + fun isPhoenix(player: Player): Boolean { + return ShieldofArrav.isPhoenix(player) + } + + /** Abstraction of Shield of Arrav isBlackArm function */ + fun isBlackArm(player: Player): Boolean { + return ShieldofArrav.isBlackArm(player) + } + + fun hasRequirements(player: Player): Boolean { + return arrayOf( + hasLevelStat(player, Skills.HERBLORE, 25), + hasLevelStat(player, Skills.MINING, 50), + hasLevelStat(player, Skills.FISHING, 53), + hasLevelStat(player, Skills.COOKING, 53), + isQuestComplete(player, "Shield of Arrav"), + isQuestComplete(player, "Lost City"), + isQuestComplete(player, "Merlin's Crystal"), + isQuestComplete(player, "Dragon Slayer"), + getQuestPoints(player) >= 55, + ).all { it } + } + + fun allItemsInInventory(player: Player): Boolean { + return inInventory(player, Items.FIRE_FEATHER_1583) && + inInventory(player, Items.LAVA_EEL_2149) && + inInventory(player, Items.THIEVES_ARMBAND_1579) + } + } + + override fun drawJournal(player: Player?, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player!!, questName) > 0 + + if(!started){ + if (checkQuestsAreComplete(player)) { + line(player, "I can start this quest by speaking to !!Achietties?? at the", line++) + line(player, "!!Heroes' Guild?? located !!North?? of !!Taverly??", line++) + line(player, "as all required quests are complete, and I have enough QP.", line++) + } else { + line(player, "I can start this quest by speaking to !!Achietties?? at the", line++) + line(player, "!!Heroes' Guild?? located !!North?? of !!Taverly?? after completing", line++) + line(player, "!!The Shield of Arrav??", line++, isQuestComplete(player, "Shield of Arrav")) + line(player, "!!The Lost City??", line++, isQuestComplete(player, "Lost City")) + line(player, "!!Merlin's Crystal??", line++, isQuestComplete(player, "Merlin's Crystal")) + line(player, "!!The Dragon Slayer??", line++, isQuestComplete(player, "Dragon Slayer")) + line(player, "!!and gaining 55 Quest Points??", line++, getQuestPoints(player) >= 55) + } + line(player, "To complete this quest I need:", line++, false) + line(player, "!!Level 25 Herblore??", line++, hasLevelStat(player, Skills.HERBLORE, 25)) + line(player, "!!Level 50 Mining??", line++, hasLevelStat(player, Skills.MINING, 50)) + line(player, "!!Level 53 Fishing??", line++, hasLevelStat(player, Skills.FISHING, 53)) + line(player, "!!Level 53 Cooking??", line++, hasLevelStat(player, Skills.COOKING, 53)) + } else if (stage < 100) { + line(player, "!!Achietties?? will let me into the !!Heroes' Guild?? if I can get:", line++) + + // This is completely dependent on what you have in your inventory. + if (inInventory(player, Items.FIRE_FEATHER_1583)) { + line(player, "An Entranan Firebird Feather - I now have one on me!", line++, true) + } else { + line(player, "An !!Entranan Firebird Feather?? - I should check on !!Entrana??", line++) + } + + // This is completely dependent on what you have in your inventory. + if (inInventory(player, Items.LAVA_EEL_2149)) { + line(player, "A cooked lava eel - I now have one on me!", line++, true) + } else { + line(player, "A !!cooked lava eel?? - I should speak to a !!Fishing Expert??", line++) + } + + if (isPhoenix(player)) { + if (inInventory(player, Items.THIEVES_ARMBAND_1579)) { + line(player, "A Master Thieves Armband - I now have one on me!", line++, true) + } else { + line(player, "A !!Master Thieves Armband?? - the !!Phoenix Gang can help me??", line++) + } + + if (!inInventory(player, Items.THIEVES_ARMBAND_1579)) { + if (stage >= 2) { + line(player, "I spoke to Straven about the Master Thieves Armband.", line++, true) + } + + if (stage >= 3) { + line(player, "Then I told Alfonse the password 'Gherkin'.", line++, true) + } else if (stage >= 2) { + line(player, "He told me I can get one by stealing !!Pete's Candlestick??", line++) + line(player, "I should use the password he gave me at !!Brimhaven??", line++) + } + + if (stage >= 4) { + line(player, "Charlie told me about a secret door into Scarface Pete's", line++, true) + line(player, "hideout, but he couldn't find a way of getting through it.", line++, true) + } else if (stage >= 3) { + line(player, "He said, secretly speak to !!Charlie?? round the back.", line++) + } + + if (stage >= 6) { + line(player, "A rival gang member collected a candlestick for me after I", line++, true) + line(player, "killed Grip and got the Treasure Room key for them.", line++, true) + line(player, "I gave Straven Scarface Pete's candlestick, and in reward", line++, true) + line(player, "he gave me a Master Thieves Armband to prove my skills.", line++, true) + } else if (stage >= 4) { + line(player, "Maybe !!another player?? can help to get through this !!door???.", line++) + } + } + } + if (isBlackArm(player)) { + if (inInventory(player, Items.THIEVES_ARMBAND_1579)) { + line(player, "A Master Thieves Armband - I now have one on me!", line++, true) + } else { + line(player, "A !!Master Thieves Armband?? - the !!Black Arms can help me??", line++) + } + + if (!inInventory(player, Items.THIEVES_ARMBAND_1579)) { + if (stage >= 2) { + line(player, "I spoke to Katrine about the Master Thieves Armband.", line++, true) + } + + if (stage >= 3) { + line(player, "I used the Black Arm password to enter the Brimhaven HQ.", line++, true) + } else if (stage >= 2) { + line(player, "She told me I can get one by stealing !!Pete's Candlestick??", line++) + line(player, "I should use the password she gave me at !!Brimhaven??", line++) + } + + if (stage >= 4) { + line(player, "I managed to pass myself off as Hartigen and enter the", line++, true) + line(player, "HQ.", line++, true) + } else if (stage >= 3) { + line(player, "I need to disguise myself as !!Hartigen the Black Knight?? in", line++) + line(player, "order to get inside !!Scarface Pete's hideout??", line++) + } + + if (stage >= 6) { + line(player, "I collected the candlesticks with the Treasure Room key", line++, true) + line(player, "after a rival gang member killed Grip.", line++, true) + line(player, "I gave Katrine Scarface Pete's candlestick, and in reward", line++, true) + line(player, "she gave me a Master Thieves Armband to prove my skills.", line++, true) + } else if (stage >= 4) { + line(player, "I can move around the hideout, but now I need Grips keys", line++) + line(player, "to get into the treasure room and get the candlesticks.", line++) + line(player, "I need !!another player's help?? with this, as it's so risky.", line++) + } + } + } + + if (allItemsInInventory(player)) { + line(player, "Now that I have !!all the required items??, I should go and speak to", line++) + line(player, "!!Achietties?? and give them to her", line++) + } + } else { + // Everything above is replaced by this. + line(player, "I gave Achietties an Entranan Firebird Feather, A cooked", line++, true) + line(player, "lava eel from a dangerous fishing spot and after some", line++, true) + line(player, "difficulty, a Master Thief Armband.", line++, true) + line(player, "Once I had handed these over to Achietties I had proved", line++, true) + line(player, "myself worthy of entrance to the Heroes' Guild.", line++, true) + line++ + line++ + line(player,"QUEST COMPLETE!", line) + } + } + + override fun reset(player: Player) { + if (getQuestStage(player, questName) == 0) { + removeAttribute(player, attributeGruborLetsYouIn) + removeAttribute(player, attributeGripTookPapers) + removeAttribute(player, attributeGripSaidDuties) + removeAttribute(player, attributeHasOpenedBackdoor) + removeAttribute(player, attributeHasOpenedChestDoor) + + // For testing: if you set quest stage to 0, it will switch your gang (blackarm <-> phoenix) + // Remember to set stage to 0 twice to keep your gang. + println("Swapping gang for Heroes Quest.") + ShieldofArrav.swapGang(player) + } + } + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed the Heroes Quest!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.DRAGON_BATTLEAXE_1377, 240, 277, 5) + + drawReward(player,"1 Quest Point", ln++) + drawReward(player,"Access to the Heroes' Guild", ln++) + drawReward(player,"A total of 29,232 XP spread", ln++) + drawReward(player,"over twelve skills", ln++) + + rewardXP(player, Skills.ATTACK, 3075.0) + rewardXP(player, Skills.DEFENCE, 3075.0) + rewardXP(player, Skills.STRENGTH, 3075.0) + rewardXP(player, Skills.HITPOINTS, 3075.0) + rewardXP(player, Skills.RANGE, 2075.0) + rewardXP(player, Skills.FISHING, 2725.0) + rewardXP(player, Skills.COOKING, 2825.0) + rewardXP(player, Skills.WOODCUTTING, 1575.0) + rewardXP(player, Skills.FIREMAKING, 1575.0) + rewardXP(player, Skills.SMITHING, 2725.0) + rewardXP(player, Skills.MINING, 2575.0) + rewardXP(player, Skills.HERBLORE, 1325.0) + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt new file mode 100644 index 000000000..aa9e3b7c7 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt @@ -0,0 +1,154 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.combat.ImpactHandler +import core.game.node.entity.npc.NPC +import core.game.node.item.GroundItem +import core.game.world.map.Location +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class HeroesQuestListener: InteractionListener { + + override fun defineListeners() { + // Black arm gang office door. + on(Scenery.DOOR_2626, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, HeroesQuest.questName) >= 2 && + getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && + HeroesQuest.isBlackArm(player)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + openDialogue(player, GruborDialogueFile(), NPC(NPCs.GRUBOR_789)) + } + return@on true + } + + // Kitchen entrance + on(Scenery.DOOR_2628, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendDialogue(player, "This door is locked.") + } + return@on true + } + + // Kitchen wall + on(Scenery.WALL_2629, IntType.SCENERY, "push") { player, node -> + if (getQuestStage(player, HeroesQuest.questName) >= 4 && HeroesQuest.isPhoenix(player)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + openDialogue(player, CharlieTheCookDialogueFile(), NPC(NPCs.CHARLIE_THE_COOK_794)) + } + return@on true + } + + // Mansion frontdoor + on(Scenery.DOOR_2627, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, HeroesQuest.questName) >= 4 && HeroesQuest.isBlackArm(player)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + openDialogue(player, GarvDialogueFile(), NPC(NPCs.GARV_788)) + } + return@on true + } + + // Cupboard + + on(Scenery.CUPBOARD_2636, IntType.SCENERY, "search") { player, node -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + START_DIALOGUE -> sendNPCDialogue(player, NPCs.PIRATE_GUARD_799, "I don't think Mr Grip will like you opening that. That's his private drinks cabinet.") .also { stage++ } + 1 -> showTopics( + Topic(FacialExpression.NEUTRAL, "He won't notice me having a quick look.", 2), + Topic(FacialExpression.NEUTRAL, "Ok, I'll leave it.", END_DIALOGUE) + ) + 2 -> end().also { + val gripNpc = findNPC(NPCs.GRIP_792) + sendChat(gripNpc!!, "Stay out of my drinks cabinet!") + forceWalk(gripNpc, Location(2777, 3198, 0), "smart") + } + } + } + }) + return@on true + } + + // Mansion backdoor + on(Scenery.DOOR_2622, IntType.SCENERY, "open") { player, node -> + if (getAttribute(player, HeroesQuest.attributeHasOpenedBackdoor, false)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendDialogue(player, "This door is locked.") + } + return@on true + } + onUseWith(IntType.SCENERY, Items.MISCELLANEOUS_KEY_1586, Scenery.DOOR_2622) { player, used, with -> + setAttribute(player, HeroesQuest.attributeHasOpenedBackdoor, true) + DoorActionHandler.handleAutowalkDoor(player, with.asScenery()) + return@onUseWith true + } + + // Chest door + on(Scenery.DOOR_2621, IntType.SCENERY, "open") { player, node -> + if (getAttribute(player, HeroesQuest.attributeHasOpenedChestDoor, false)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendDialogue(player, "This door is locked.") + } + return@on true + } + onUseWith(IntType.SCENERY, Items.GRIPS_KEY_RING_1588, Scenery.DOOR_2621) { player, used, with -> + setAttribute(player, HeroesQuest.attributeHasOpenedChestDoor, true) + DoorActionHandler.handleAutowalkDoor(player, with.asScenery()) + return@onUseWith true + } + + // Chest + on(Scenery.CHEST_2632, IntType.SCENERY, "open"){ player, node -> + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CHEST_2633, -1) + return@on true + } + on(Scenery.CHEST_2633, IntType.SCENERY, "close"){ player, node -> + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CHEST_2632, -1) + return@on true + } + on(Scenery.CHEST_2633, IntType.SCENERY, "search"){ player, node -> + if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { + sendMessage(player, "You search the chest but find nothing.") + } else { + if (getQuestStage(player, HeroesQuest.questName) == 4) { + setQuestStage(player, HeroesQuest.questName, 5) + } + sendDialogue(player, "You find two candlesticks in the chest. So that will be one for you, and one for the person who killed Grip for you.") + addItemOrDrop(player, Items.PETES_CANDLESTICK_1577, 2) + } + return@on true + } + + // + on(Items.FIRE_FEATHER_1583, IntType.GROUNDITEM, "take") { player, groundItem -> + if (inEquipment(player, Items.ICE_GLOVES_1580)) { + addItem(player, Items.FIRE_FEATHER_1583) + removeGroundItem(groundItem as GroundItem) + } else { + sendChat(player, "Ouch!") + player.impactHandler.manualHit(player, 9, ImpactHandler.HitsplatType.NORMAL) + sendMessage(player, "It is too hot to take. You need something cold to pick it up with.") + } + return@on true + } + + // OilFishingRodListener.kt + DrinkBlamishOilListener.kt + FinishedPotion.java + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt new file mode 100644 index 000000000..df6bf22c4 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt @@ -0,0 +1,126 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.* +import org.rs09.consts.Items + +class KatrineDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + // 0 is handled by default in the old KatrineDialogue. + b.onQuestStages(HeroesQuest.questName, 1) + .playerl("Hey.") + .npcl("Hey.") + .options() + .let { optionBuilder -> + + optionBuilder.option_playerl("Who are all those people in there?") + .npcl("They're just various rogues and thieves.") + .playerl("They don't say a lot...") + .npcl("Nope.") + .end() + + optionBuilder.option_playerl("Is there any way I can get the rank of master thief?") + .npcl("Master thief? Ain't we the ambitious one!") + .npcl("Well, you're gonna have to do something pretty amazing.") + .playerl("Anything you can suggest?") + .npcl("Well, some of the MOST coveted prizes in thiefdom right now are in the pirate town of Brimhaven on Karamja.") + .npcl("The pirate leader Scarface Pete has a pair of extremely valuable candlesticks.") + .npcl("His security is VERY good.") + .npcl("We, of course, have gang members in a town like Brimhaven who may be able to help you.") + .npcl("Visit our hideout in the alleyway on palm street.") + .npcl("To get in you will need to tell them the secret password 'four leaved clover'.") + .endWith { _, player -> + if(getQuestStage(player, HeroesQuest.questName) == 1) { + setQuestStage(player, HeroesQuest.questName, 2) + } + } + + } + + // This is not authentic, she falls back to a boring default conversation, but I guess people might need help during the quest + b.onQuestStages(HeroesQuest.questName, 2,3,4) + .playerl("What am I supposed to be doing again?") + .npcl("You told me you wanted to get the rank of master thief! Now pay attention.") + .npcl("Some of the MOST coveted prizes in thiefdom right now are in the pirate town of Brimhaven on Karamja.") + .npcl("The pirate leader Scarface Pete has a pair of extremely valuable candlesticks.") + .npcl("His security is VERY good.") + .npcl("We, of course, have gang members in a town like Brimhaven who may be able to help you.") + .npcl("Visit our hideout in the alleyway on palm street.") + .npcl("To get in you will need to tell them the secret password 'four leaved clover'.") + .end() + + // As FYI, the fallback for 2,3,4 is + /** + * .options() + * .let { optionBuilder -> + * optionBuilder.option_playerl("Who are all those people in there?") + * .npcl("They're just various rogues and thieves.") + * .playerl("They don't say a lot...") + * .npcl("Nope.") + * .end() + * optionBuilder.option("Teach me to be a top class criminal!") + * .playerl("Teach me to be a top class criminal.") + * .npcl("Teach yourself.") + * .end() + * + * + * + * Player: + * I have a candlestick now! + * Katrine: + * Good for you. I'll give a master thief's armband to the one who retrieved that. I know it wasn't you. + */ + + + b.onQuestStages(HeroesQuest.questName, 5) + .branch { player -> + return@branch if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Who are all those people in there?") + .npcl("They're just various rogues and thieves.") + .playerl("They don't say a lot...") + .npcl("Nope.") + .end() + optionBuilder.option("I have a candlestick now.") + .playerl("I have a candlestick now!") + .npcl("Wow... is... it REALLY it?") + .npcl("This really is a FINE bit of thievery.") + .npcl("Us thieves have been trying to get hold of this one for a while!") + .npc("You wanted to be ranked as a master thief didn't you?", "Well, I guess this just about ranks as good enough!") + .linel("Katrine gives you a master thief armband.") + .endWith { _, player -> + if (removeItem(player, Items.PETES_CANDLESTICK_1577)) { + addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) + if (getQuestStage(player, HeroesQuest.questName) == 5) { + setQuestStage(player, HeroesQuest.questName, 6) + } + } + } + + branch.onValue(0) + .playerl("What am I supposed to be doing again?") + .npcl("You told me you wanted to get the rank of master thief! Now pay attention.") + .npcl("Some of the MOST coveted prizes in thiefdom right now are in the pirate town of Brimhaven on Karamja.") + .npcl("The pirate leader Scarface Pete keeps an extremely valuable candlesticks.") + .npcl("His security is VERY good.") + .npcl("We, of course, have gang members in a town like Brimhaven who may be able to help you.") + .npcl("Visit our hideout in the alleyway on palm street.") + .npcl("To get in you will need to tell them the secret password 'four leaved clover'.") + .end() + } + } + + // I lost the armband and some stupid default shit. + b.onQuestStages(HeroesQuest.questName, 6) + .playerl("I have lost my master thief's armband...") + .npcl("Lucky I 'ave a spare ain't it? Don't lose it again.") + .endWith { _, player -> + addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) + } + + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt new file mode 100644 index 000000000..1f94f41fb --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt @@ -0,0 +1,72 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.* +import org.rs09.consts.Items + +class StravenDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + // 0 is handled by default in the old StravenDialogue. + b.onQuestStages(HeroesQuest.questName, 1) + .playerl("How would I go about getting a Master Thief armband?") + .npcl("Ooh... tricky stuff. Took me YEARS to get that rank.") + .npcl("Well, what some of the more aspiring thieves in our gang are working on right now is to steal some very valuable candlesticks from Scarface Pete - the pirate leader on Karamja.") + .npcl("His security is excellent, and the target very valuable so that might be enough to get you the rank.") + .npcl("Go talk to our man Alfonse, the waiter in the Shrimp and Parrot.") + .npcl("Use the secret word 'gherkin' to show you're one of us.") + .endWith { _, player -> + if(getQuestStage(player, HeroesQuest.questName) == 1) { + setQuestStage(player, HeroesQuest.questName, 2) + } + } + + b.onQuestStages(HeroesQuest.questName, 2,3,4) + .playerl("What am I supposed to be doing again?") + .npcl("You told me you wanted to get a Master thief's armband! Now pay attention.") + .npcl("Some of the more aspiring thieves in our gang are working on right now is to steal some very valuable candlesticks from Scarface Pete - the pirate leader on Karamja.") + .npcl("His security is excellent, and the target very valuable so that might be enough to get you the rank.") + .npcl("Go talk to our man Alfonse, the waiter in the Shrimp and Parrot.") + .npcl("Use the secret word 'gherkin' to show you're one of us.") + .end() + + + b.onQuestStages(HeroesQuest.questName, 5) + .branch { player -> + return@branch if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .playerl("I have retrieved a candlestick!") + .npcl("Hmmm. Not bad, not bad. Let's see it, make sure it's genuine.") + .linel("You hand Straven the candlestick.") + .playerl("So is this enough to get me a Master Thief armband?") + .npcl("Hmm... I dunno... Aww, go on then. I suppose I'm in a generous mood today.") + .linel("Straven hands you a Master Thief armband.") + .endWith { _, player -> + if (removeItem(player, Items.PETES_CANDLESTICK_1577)) { + addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) + if (getQuestStage(player, HeroesQuest.questName) == 5) { + setQuestStage(player, HeroesQuest.questName, 6) + } + } + } + + branch.onValue(0) + .playerl("What am I supposed to be doing again?") + .npcl("You told me you wanted to get a Master thief's armband! Now pay attention.") + .npcl("Some of the more aspiring thieves in our gang are working on right now is to steal some very valuable candlesticks from Scarface Pete - the pirate leader on Karamja.") + .npcl("His security is excellent, and the target very valuable so that might be enough to get you the rank.") + .npcl("Go talk to our man Alfonse, the waiter in the Shrimp and Parrot.") + .npcl("Use the secret word 'gherkin' to show you're one of us.") + .end() + } + + // I lost the armband and some stupid default shit. + b.onQuestStages(HeroesQuest.questName, 6) + .playerl("I'm afraid I've lost my master thief's armband.") + .npcl("Lucky for you I have a spare. Don't lose it again!") + .endWith { _, player -> + addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt new file mode 100644 index 000000000..14ffa3073 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt @@ -0,0 +1,91 @@ +package content.region.asgarnia.burthorpe.quest.heroesquest + +import core.api.* +import core.game.dialogue.* +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class TrobertDialogue(player: Player? = null) : DialoguePlugin(player){ + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, TrobertDialogueFile(), npc) + return true + } + + override fun newInstance(player: Player?): DialoguePlugin { + return TrobertDialogue(player) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.TROBERT_1884) + } +} + +class TrobertDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + // Technically this won't happen since you have to get past Grubor. + b.onQuestStages(HeroesQuest.questName, 0,1) + .npcl("Welcome to our Brimhaven headquarters. I'm Trobert and I'm in charge here.") + .playerl("Pleased to meet you.") + .npcl("Likewise.") + .end() + + b.onQuestStages(HeroesQuest.questName, 2) + .npcl("Welcome to our Brimhaven headquarters. I'm Trobert and I'm in charge here.") + .options() + .let { optionBuilder -> + val continuePath = b.placeholder() + optionBuilder.option("So can you help me get Scarface Pete's candlesticks?") + .goto(continuePath) + optionBuilder.option_playerl("Pleased to meet you.") + .npcl("Likewise.") + .goto(continuePath) + return@let continuePath.builder() + } + .playerl("So can you help me get Scarface Pete's candlesticks?") + .npcl("Well, we have made some progress there. We know that one of the only keys to Pete's treasure room is carried by Grip, the head guard, so we thought it might be good to get close to him somehow.") + .npcl("Grip was taking on a new deputy called Hartigen, an Asgarnian Black Knight who was deserting the Black Knight Fortress and seeking new employment here on Brimhaven.") + .npcl("We managed to waylay him on the journey here, and steal his I.D. papers. Now all we need is to find somebody willing to impersonate him and take the deputy role to get that key for us.") + .options() + .let { optionBuilder -> + + optionBuilder.option_playerl("I volunteer to undertake that mission!") + .npcl("Good good. Well, here's the ID papers, take them and introduce yourself to the guards at Scarface Pete's mansion, we'll have that treasure in no time.") + .endWith { _, player -> + addItemOrDrop(player, Items.ID_PAPERS_1584) + if(getQuestStage(player, HeroesQuest.questName) == 2) { + setQuestStage(player, HeroesQuest.questName, 3) + } + } + + optionBuilder.option_playerl("Well, good luck then.") + .npcl("Someone will show up eventually.") + .end() + } + + b.onQuestStages(HeroesQuest.questName, 3,4,5) + .branch { player -> + return@branch if (inInventory(player, Items.ID_PAPERS_1584)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("How's it going?") + .playerl("Fine, thanks.") + .end() + branch.onValue(0) + .playerl("I have lost Hartigen's ID papers.") + .npcl("Well, that was careless of you, wasn't it? Fortunately for you, he had a spare. Take this one, but please try to be more careful with this one.") + .endWith { _, player -> + addItemOrDrop(player, Items.ID_PAPERS_1584) + } + } + + b.onQuestStages(HeroesQuest.questName, 6,100) + .npcl("How's it going?") + .playerl("Fine, thanks.") + .end() + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/portsarim/dialogue/GerrantDialogue.java b/Server/src/main/content/region/asgarnia/portsarim/dialogue/GerrantDialogue.java deleted file mode 100644 index 1d00b97d0..000000000 --- a/Server/src/main/content/region/asgarnia/portsarim/dialogue/GerrantDialogue.java +++ /dev/null @@ -1,82 +0,0 @@ -package content.region.asgarnia.portsarim.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the dialogue plugin used for the gerrant npc. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class GerrantDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code GerrantDialogue} {@code Object}. - */ - public GerrantDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code GerrantDialogue} {@code Object}. - * @param player the player. - */ - public GerrantDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new GerrantDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HAPPY, "Welcome! You can buy fishing equipment at my store.", "We'll also buy anything you catch off you."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Choose an option:", "Let's see what you've got then.", "Sorry, I'm not interested."); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HAPPY, "Let's see what you've got then."); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Sorry, I'm not interested."); - stage = 20; - break; - - } - break; - case 10: - end(); - npc.openShop(player); - break; - case 20: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 558 }; - } -} diff --git a/Server/src/main/content/region/karamja/brimhaven/dialogue/AlfonseWaiterDialogue.java b/Server/src/main/content/region/karamja/brimhaven/dialogue/AlfonseWaiterDialogue.java deleted file mode 100644 index 72c201399..000000000 --- a/Server/src/main/content/region/karamja/brimhaven/dialogue/AlfonseWaiterDialogue.java +++ /dev/null @@ -1,92 +0,0 @@ -package content.region.karamja.brimhaven.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the dialogue plugin for the npc alfonse the waiter. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class AlfonseWaiterDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code AlfonseWaiterDialogue} {@code Object}. - */ - public AlfonseWaiterDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code AlfonseWaiterDialogue} {@code Object}. - * @param player the player. - */ - public AlfonseWaiterDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new AlfonseWaiterDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Welcome to the Shrimp and Parrot.", "Would you like to order, sir?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Select an Option", "Yes, please.", "No, thank you.", "Where do you get your Karambwan from?"); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yes, please."); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No, thank you."); - stage = 20; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Where do you get your Karambwan from?"); - stage = 30; - break; - } - break; - case 10: - end(); - npc.openShop(player); - break; - case 20: - end(); - break; - case 30: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "We buy directly off Lubufu, a local fisherman. He", "seems to have a monopoly over Karambwan sales."); - stage = 31; - break; - case 31: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 793 }; - } -} diff --git a/Server/src/main/content/region/karamja/brimhaven/dialogue/GarvDialogue.java b/Server/src/main/content/region/karamja/brimhaven/dialogue/GarvDialogue.java deleted file mode 100644 index 8f995db1e..000000000 --- a/Server/src/main/content/region/karamja/brimhaven/dialogue/GarvDialogue.java +++ /dev/null @@ -1,88 +0,0 @@ -package content.region.karamja.brimhaven.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the garv dialogue plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class GarvDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code GarvDialogue} {@code Object}. - */ - public GarvDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code GarvDialogue} {@code Object}. - * @param player the player. - */ - public GarvDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new GarvDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hello. What do you want?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Select an Option", "Can I go in there?", "I want for nothing!"); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Can I go in there?"); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I want for nothing!"); - stage = 20; - break; - } - break; - case 10: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "No. In there is private."); - stage = 11; - break; - case 11: - end(); - break; - case 20: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "You're one of a very lucky few then."); - stage = 21; - break; - case 21: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 788 }; - } -} diff --git a/Server/src/main/content/region/karamja/brimhaven/dialogue/GruborDialogue.java b/Server/src/main/content/region/karamja/brimhaven/dialogue/GruborDialogue.java deleted file mode 100644 index c181f9399..000000000 --- a/Server/src/main/content/region/karamja/brimhaven/dialogue/GruborDialogue.java +++ /dev/null @@ -1,99 +0,0 @@ -package content.region.karamja.brimhaven.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the grubor dialogue plugin. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class GruborDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code GruborDialogue} {@code Object}. - */ - public GruborDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code GruborDialogue} {@code Object}. - * @param player the player. - */ - public GruborDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new GruborDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Yes? What do you want?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendOptions("Select an Option", "Would you like your hedges trimming?", "I want to come in.", "Do you want to trade?"); - stage = 1; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Would you like your hedges trimming?"); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I want to come in."); - stage = 20; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Do you want to trade?"); - stage = 30; - break; - } - break; - case 10: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Eh? Don't be daft! We don't even HAVE any hehdges!"); - stage = 11; - break; - case 11: - end(); - break; - case 20: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "No, go away."); - stage = 21; - break; - case 21: - end(); - break; - case 30: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "No, I'm busy."); - stage = 31; - break; - case 31: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 789 }; - } -} diff --git a/Server/src/main/content/region/karamja/brimhaven/handlers/BrimhavenListeners.kt b/Server/src/main/content/region/karamja/brimhaven/handlers/BrimhavenListeners.kt index ddb5c270a..e2b43bc28 100644 --- a/Server/src/main/content/region/karamja/brimhaven/handlers/BrimhavenListeners.kt +++ b/Server/src/main/content/region/karamja/brimhaven/handlers/BrimhavenListeners.kt @@ -44,21 +44,6 @@ class BrimhavenListeners : InteractionListener { */ private const val RESTAURANT_REAR_DOOR = Scenery.DOOR_1591 - /** - * Represents the door of the Black Arm Gang office used in the Heroes' Quest. - */ - private const val GANG_OFFICE_DOOR = Scenery.DOOR_2626 - - /** - * Represents the door guarded by Garv on ScarFace Pete's mansion used in the Heroes' Quest. - */ - private const val MANSION_DOOR = Scenery.DOOR_2627 - - /** - * Represents the kitchen door in the Shrimp and Parrot restaurant used in the Heroes' Quest. - */ - private const val RESTAURANT_KITCHEN_DOOR = Scenery.DOOR_2628 - /** * Represents Lubufu's karambwan fishing spot unlocked in Tai Bwo Wannai Trio. */ @@ -108,21 +93,6 @@ class BrimhavenListeners : InteractionListener { return@on true } - on(GANG_OFFICE_DOOR, IntType.SCENERY, "open") { player, _ -> - openDialogue(player, 789, Repository.findNPC(789)!!) - return@on true - } - - on(MANSION_DOOR, IntType.SCENERY, "open") { player, _ -> - openDialogue(player, 788, Repository.findNPC(788)!!, true) - return@on true - } - - on(RESTAURANT_KITCHEN_DOOR, IntType.SCENERY, "open") { player, _ -> - sendMessage(player, "The door is securely closed.") - return@on true - } - on(KARAMBWAN_FISHING_SPOT, IntType.NPC, "fish") { player, _ -> sendNPCDialogue( player, diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java index 101f9366a..027e04ba0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java @@ -1,11 +1,14 @@ package content.region.misthalin.varrock.quest.shieldofarrav; +import content.region.asgarnia.burthorpe.quest.heroesquest.KatrineDialogueFile; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import static core.api.ContentAPIKt.openDialogue; + /** * Represents the katrine NPC dialogue. * @author 'Vexia @@ -50,9 +53,17 @@ public final class KatrineDialogue extends DialoguePlugin { npc = (NPC) args[0]; quest = player.getQuestRepository().getQuest("Shield of Arrav"); switch (quest.getStage(player)) { - case 80: - case 90: case 100: + if (ShieldofArrav.isBlackArm(player)) { + Quest heroesQuest = player.getQuestRepository().getQuest("Heroes' Quest"); + if (0 < heroesQuest.getStage(player) && heroesQuest.getStage(player) < 100) { + openDialogue(player, new KatrineDialogueFile(), npc); + break; + } + } + // Continues below if not during the Heroes' Quest + case 90: + case 80: case 70: if (ShieldofArrav.isPhoenix(player)) { npc("You've got some guts coming here, Phoenix guy!"); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java index ee91ad5d6..90174100c 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java @@ -225,6 +225,22 @@ public class ShieldofArrav extends Quest { player.setAttribute("/save:black-arm-gang", true); } + /** + * Swaps the gang. + * @param player the player. + */ + public static void swapGang(final Player player) { + if(isPhoenix(player)) { + player.setAttribute("/save:black-arm-gang", true); + player.setAttribute("/save:phoenix-gang", false); + } else if(isBlackArm(player)) { + player.setAttribute("/save:black-arm-gang", false); + player.setAttribute("/save:phoenix-gang", true); + } else { + player.setAttribute("/save:phoenix-gang", true); + } + } + /** * Method used to check if the player is part of the phoenix gang. * @param player the player. diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java index 5bb9fc352..f429afc46 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java @@ -5,6 +5,9 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; +import content.region.asgarnia.burthorpe.quest.heroesquest.StravenDialogueFile; + +import static core.api.ContentAPIKt.openDialogue; /** * Represents the dialogue which handles the straven NPC. @@ -46,6 +49,14 @@ public class StravenDialogue extends DialoguePlugin { quest = player.getQuestRepository().getQuest("Shield of Arrav"); switch (quest.getStage(player)) { case 100: + if (ShieldofArrav.isPhoenix(player)) { + Quest heroesQuest = player.getQuestRepository().getQuest("Heroes' Quest"); + if (0 < heroesQuest.getStage(player) && heroesQuest.getStage(player) < 100) { + openDialogue(player, new StravenDialogueFile(), npc); + break; + } + } + // Continues below if not during the Heroes' Quest case 70: if (ShieldofArrav.isPhoenix(player)) { npc("Greetings fellow gang member."); diff --git a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java index c58521aab..22fab5af3 100644 --- a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java +++ b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java @@ -161,7 +161,8 @@ public final class TradeContainer extends Container { String targetMac = target.getDetails().getMacAddress(); String playerHost = player.getDetails().getCompName(); String targetHost = target.getDetails().getCompName(); - if (item.getId() == 11174 || item.getId() == 11173 || item.getId() == 759) { + // Ironman trading exceptions for Shield of Arrav and Heroes Quest + if (item.getId() == 11174 || item.getId() == 11173 || item.getId() == 759 || item.getId() == 1586 || item.getId() == 1577) { return true; } if (player.getIronmanManager().isIronman() || target != null && target.getIronmanManager().isIronman()) { From 6a68cf9d7ca78f34067e0e944d3777508084a5c7 Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 12:56:18 +0000 Subject: [PATCH 168/306] Fixed issue with trees not being able to be health checked --- Server/src/main/content/global/skill/farming/Patch.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/farming/Patch.kt b/Server/src/main/content/global/skill/farming/Patch.kt index c9f90b4a9..8965167db 100644 --- a/Server/src/main/content/global/skill/farming/Patch.kt +++ b/Server/src/main/content/global/skill/farming/Patch.kt @@ -154,7 +154,8 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl PatchType.FRUIT_TREE_PATCH -> setVarbit(player, patch.varbit, plantable!!.value + plantable!!.stages + 20) PatchType.BUSH_PATCH -> setVarbit(player, patch.varbit, 250 + (plantable!!.ordinal - Plantable.REDBERRY_SEED.ordinal)) PatchType.CACTUS_PATCH -> setVarbit(player, patch.varbit, 31) - else -> log(this::class.java, Log.WARN, "Invalid setting of isCheckHealth for patch type: " + patch.type.name) + PatchType.TREE_PATCH -> setVarbit(player, patch.varbit, plantable!!.value + plantable!!.stages) + else -> log(this::class.java, Log.WARN, "Invalid setting of isCheckHealth for patch type: " + patch.type.name + "at" + patch.name) } } else { when(patch.type){ From 9fff4dbb5d6e57294aa2a446123a5e4bd6eabd39 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:02:22 +0000 Subject: [PATCH 169/306] Implemented spade pickup in the Rimmington mine Rewrote the permadeath code to more thoroughly wipe HCIM when they die HCIM permadeath code destroys items dropped on death Cleaned up redundant blast furnace player save code --- .../rimmington/handler/RimmingtonListeners.kt | 29 +++++ Server/src/main/core/api/utils/Permadeath.kt | 102 ++++++++++++++++-- .../core/game/node/entity/player/Player.java | 17 +-- .../player/info/login/PlayerSaveParser.kt | 3 - .../entity/player/info/login/PlayerSaver.kt | 10 -- .../entity/player/link/BankPinManager.java | 14 ++- .../main/core/game/node/item/GroundItem.java | 4 + .../system/command/sets/MiscCommandSet.kt | 2 +- 8 files changed, 138 insertions(+), 43 deletions(-) create mode 100644 Server/src/main/content/region/asgarnia/rimmington/handler/RimmingtonListeners.kt diff --git a/Server/src/main/content/region/asgarnia/rimmington/handler/RimmingtonListeners.kt b/Server/src/main/content/region/asgarnia/rimmington/handler/RimmingtonListeners.kt new file mode 100644 index 000000000..5dc727594 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/rimmington/handler/RimmingtonListeners.kt @@ -0,0 +1,29 @@ +package content.region.asgarnia.rimmington.handler + +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.item.Item +import core.game.node.scenery.Scenery +import org.rs09.consts.Items +import org.rs09.consts.Sounds + +/** + * @author Player Name + */ + +class RimmingtonListeners : InteractionListener { + override fun defineListeners() { + on(9662, IntType.SCENERY, "take") { player, node -> + if (!hasSpaceFor(player, Item(Items.SPADE_952))) { + sendMessage(player, "You don't have enough inventory space to hold that item.") + return@on true + } + animate(player, 535) + playAudio(player, Sounds.PICK2_2582) + addItem(player, Items.SPADE_952) + replaceScenery(node as Scenery, 0, 50) + return@on true + } + } +} diff --git a/Server/src/main/core/api/utils/Permadeath.kt b/Server/src/main/core/api/utils/Permadeath.kt index 0c0ac1e17..c7e5069f4 100644 --- a/Server/src/main/core/api/utils/Permadeath.kt +++ b/Server/src/main/core/api/utils/Permadeath.kt @@ -1,32 +1,72 @@ -package core.api.utils.Permadeath +package core.api.utils -import core.api.* +import content.global.skill.construction.HouseLocation +import content.minigame.blastfurnace.BFPlayerState +import content.minigame.blastfurnace.BlastFurnace +import core.api.isUsingSecondaryBankAccount +import core.api.teleport +import core.api.toggleBankAccount import core.game.node.entity.player.Player import core.game.node.entity.player.VarpManager import core.game.node.entity.player.info.login.PlayerSaver import core.game.node.entity.player.link.IronmanMode import core.game.node.entity.player.link.SavedData +import core.game.node.entity.player.link.SpellBookManager import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.player.link.quest.QuestRepository import core.game.node.entity.skill.Skills +import core.game.node.item.GroundItem +import core.game.node.item.GroundItemManager import core.game.world.map.Location +import java.util.ArrayList fun permadeath(target: Player) { teleport(target, Location.create(3094, 3107, 0)) - target.equipment.clear() + + // Core target.inventory.clear() + target.bank.clear() + target.bankSecondary.clear() + for (i in target.bankPrimary.tabStartSlot.indices) { + target.bankPrimary.tabStartSlot[i] = 0 + } + for (i in target.bankSecondary.tabStartSlot.indices) { + target.bankSecondary.tabStartSlot[i] = 0 + } if (isUsingSecondaryBankAccount(target)) { toggleBankAccount(target) } - target.bank.clear() - target.bankSecondary.clear() - target.skills = Skills(target) - target.clearAttributes() - target.savedData = SavedData(target) - target.questRepository = QuestRepository(target) + target.equipment.clear() target.varpManager = VarpManager(target) target.varpMap.clear() target.saveVarp.clear() + target.timers.clearTimers() + + // Skills + target.skills = Skills(target) + + // Settings can be kept + + // Quests + target.questRepository = QuestRepository(target) + + // Appearance doesn't matter because you're going to tutorial island anyway + + // Spellbook + target.spellBookManager.setSpellBook(SpellBookManager.SpellBook.MODERN) + + // Saved data + target.savedData = SavedData(target) + + // Autocast + target.properties.autocastSpell = null + + // Player monitor is a no-op + + // Music player + target.musicPlayer.clearUnlocked() + + // Familiar manager if (target.familiarManager.hasFamiliar()) { target.familiarManager.dismiss() } @@ -34,6 +74,14 @@ fun permadeath(target: Player) { for (key in petKeys) { target.familiarManager.removeDetails(key) } + + // Bank pin data + target.bankPinManager.doCancelPin() + + // House data + target.houseManager.createNewHouseAt(HouseLocation.NOWHERE) + + // Achievements for (type in DiaryType.values()) { val diary = target.achievementDiaryManager.getDiary(type) for (level in 0 until diary.levelStarted.size) { @@ -42,8 +90,42 @@ fun permadeath(target: Player) { } } } - target.musicPlayer.clearUnlocked() + + // Ironman data target.ironmanManager.mode = IronmanMode.NONE + + // Emote data + target.emoteManager.emotes.clear() + + // Stat manager is a no-op + + // Attributes + target.clearAttributes() + + // Pouches + for (pouch in target.pouchManager.pouches.values) { + pouch.container.clear() + pouch.currentCap = pouch.capacity + pouch.charges = pouch.maxCharges + pouch.remakeContainer() + } + + // Destroy any dropped items to prevent droptrading to yourself after death + val droppedItems = ArrayList(); + for (item in GroundItemManager.getItems()) { + if (item.dropperUid == target.details.uid) { + droppedItems.add(item) + } + } + for (item in droppedItems) { + GroundItemManager.destroy(item) + } + + // grep -R savePlayer: jobs, treasure trails, brawling gloves, slayer manager, barcrawl, ge history will simply not get saved if we don't run the hooks + // Only the Blast Furnace needs to be reset explicitly + BlastFurnace.playerStates[target.details.uid] = BFPlayerState(target) + + // Sayonara PlayerSaver(target).save() target.clear() } diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index a23d472c7..0fb8f6110 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -89,7 +89,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import static core.api.ContentAPIKt.*; -import static core.api.utils.Permadeath.PermadeathKt.permadeath; +import static core.api.utils.PermadeathKt.permadeath; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_DEATHS; import static core.tools.GlobalsKt.colorize; @@ -155,21 +155,6 @@ public class Player extends Entity { */ public boolean useSecondaryBank = false; - /** - * The Blast Furnace Coal Container. - */ - public final Container blastCoal = new Container(225, ContainerType.NEVER_STACK); - - /** - * The Blast Furnace Ore Container. - */ - public final Container blastOre = new Container(28, ContainerType.NEVER_STACK); - - /** - * The Blast Furnace Bars Container. - */ - public final Container blastBars = new Container(28, ContainerType.NEVER_STACK); - /** * The packet dispatcher. */ diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index d9b0105f0..64e4a80e6 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -327,9 +327,6 @@ class PlayerSaveParser(val player: Player) { player.bankPrimary.parse(bank) player.bankSecondary.parse(bankSecondary) player.equipment.parse(equipment) - bBars?.let{player.blastBars.parse(it)} - bOre?.let{player.blastOre.parse(bOre)} - bCoal?.let{player.blastCoal.parse(bCoal)} player.location = JSONUtils.parseLocation(location) if (varpData != null) { diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 7d5318921..8b34bebb4 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -19,7 +19,6 @@ import org.json.simple.JSONObject import java.io.File import java.io.FileWriter import java.io.IOException -import java.lang.Math.ceil import javax.script.ScriptEngineManager import java.util.* @@ -613,15 +612,6 @@ class PlayerSaver (val player: Player){ val bankSecondary = saveContainer(player.bankSecondary) coreData.put("bankSecondary",bankSecondary) - val bBars = saveContainer(player.blastBars) - coreData.put("blastBars",bBars) - - val bOre = saveContainer(player.blastOre) - coreData.put("blastOre",bOre) - - val bCoal = saveContainer(player.blastCoal) - coreData.put("blastCoal",bCoal) - val bankTabs = JSONArray() for(i in player.bankPrimary.tabStartSlot.indices){ val tab = JSONObject() diff --git a/Server/src/main/core/game/node/entity/player/link/BankPinManager.java b/Server/src/main/core/game/node/entity/player/link/BankPinManager.java index b4dc61d26..321b5f8bf 100644 --- a/Server/src/main/core/game/node/entity/player/link/BankPinManager.java +++ b/Server/src/main/core/game/node/entity/player/link/BankPinManager.java @@ -470,17 +470,25 @@ public class BankPinManager { } /** - * Cancels the pin. + * Cancels the pin and shows the correct interface. */ public void cancelPin(String... messages) { + doCancelPin(); + playAudio(player, Sounds.PIN_CANCEL_1042); + openSettings(messages); + } + + /** + * Actually cancels the pin. + */ + public void doCancelPin() { status = PinStatus.NO_PIN; pendingDelay = -1; pin = null; unlocked = false; - playAudio(player, Sounds.PIN_CANCEL_1042); - openSettings(messages); } + /** * Checks if the pin is an easy guess. * @return {@code True} if so. diff --git a/Server/src/main/core/game/node/item/GroundItem.java b/Server/src/main/core/game/node/item/GroundItem.java index dfdfe92f1..ba5c4e272 100644 --- a/Server/src/main/core/game/node/item/GroundItem.java +++ b/Server/src/main/core/game/node/item/GroundItem.java @@ -202,9 +202,13 @@ public class GroundItem extends Item { this.removed = removed; } + /** + * Gets the dropper uid. + */ public int getDropperUid() { return dropperUid; } + @Override public String toString() { return "GroundItem [dropper=" + (dropper != null ? dropper.getUsername() : dropper) + ", ticks=" + ticks + ", decayTime=" + decayTime + ", remainPrivate=" + remainPrivate + ", removed=" + removed + "]"; diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 6911212e1..0fec9ec16 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -6,7 +6,7 @@ import content.minigame.fishingtrawler.TrawlerLoot import content.region.misthalin.draynor.quest.anma.AnmaCutscene import core.ServerConstants import core.api.* -import core.api.utils.Permadeath.permadeath +import core.api.utils.permadeath import core.cache.def.impl.NPCDefinition import core.cache.def.impl.SceneryDefinition import core.cache.def.impl.VarbitDefinition From 4480618748380a9c20dcb1ba078477e591a2148d Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:06:53 +0000 Subject: [PATCH 170/306] Added pirate clothes to store and examine text to Mike --- Server/data/configs/npc_configs.json | 5 +++++ Server/data/configs/shops.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index aa9d10c4a..5e1c318d1 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -72355,6 +72355,11 @@ "name": "Essence Impling", "id": "1032" }, + { + "examine": "Dodgy Mike.", + "name": "Mike", + "id": "3166" + }, { "examine": "An impling with varied tastes.", "name": "Eclectic Impling", diff --git a/Server/data/configs/shops.json b/Server/data/configs/shops.json index 714e32a73..7863aae6e 100644 --- a/Server/data/configs/shops.json +++ b/Server/data/configs/shops.json @@ -564,7 +564,7 @@ "general_store": "false", "id": "65", "title": "Dodgy Mikes Second-hand Clothing", - "stock": "{7114,10,100}" + "stock": "{7114,10,100}-{7122,10,100}-{7128,10,100}-{7134,10,100}-{7110,10,100}-{7126,10,100}-{7132,10,100}-{7138,10,100}-{7116,10,100}-{7124,10,100}-{7130,10,100}-{7112,10,100}-{7136,10,100}" }, { "npcs": "2161", From 67b68553707b82e506e8d7c1be50ff89d5d3c204 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 13:07:39 +0000 Subject: [PATCH 171/306] Implemented Sea Slug quest --- Server/data/configs/ground_spawns.json | 10 +- Server/data/configs/npc_configs.json | 5 + Server/data/configs/npc_spawns.json | 42 +++- .../global/skill/cooking/CookingRewrite.kt | 2 +- .../lightsources/LightSourceLighter.kt | 6 + .../witchhaven/dialogue/BaileyDialogue.kt | 24 +++ .../witchhaven/dialogue/CarolineDialogue.kt | 38 ++-- .../witchhaven/dialogue/HolgartDialogue.kt | 37 +--- .../dialogue/HolgartIslandDialogue.kt | 27 +++ .../dialogue/HolgartPlatformDialogue.kt | 27 +++ .../witchhaven/dialogue/KennithDialogue.kt | 45 ++++ .../witchhaven/dialogue/KentDialogue.kt | 24 +++ .../dialogue/WitchavenVillagerDialogue.kt | 83 ++++++++ .../dialogue/WitchhavenVillageDialogue.kt | 78 ------- .../quest/seaslug/BaileyDialogueFile.kt | 73 +++++++ .../quest/seaslug/CarolineDialogueFile.kt | 70 +++++++ .../quest/seaslug/FishermanDialogue.kt | 102 ++++++++++ .../quest/seaslug/HolgartDialogueFile.kt | 108 ++++++++++ .../seaslug/HolgartIslandDialogueFile.kt | 29 +++ .../seaslug/HolgartPlatformDialogueFile.kt | 41 ++++ .../quest/seaslug/KennithDialogueFile.kt | 75 +++++++ .../quest/seaslug/KentDialogueFile.kt | 47 +++++ .../witchhaven/quest/seaslug/SeaSlug.kt | 187 +++++++++++++++++ .../quest/seaslug/SeaSlugListeners.kt | 192 ++++++++++++++++++ .../core/game/dialogue/FacialExpression.java | 7 +- 25 files changed, 1244 insertions(+), 135 deletions(-) create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/BaileyDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartIslandDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartPlatformDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/KennithDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/KentDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchavenVillagerDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchhavenVillageDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/FishermanDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt create mode 100644 Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json index cf3b5345c..49a0f8786 100644 --- a/Server/data/configs/ground_spawns.json +++ b/Server/data/configs/ground_spawns.json @@ -241,7 +241,7 @@ }, { "item_id": "954", - "loc_data": "{1,2094,3152,0,150}-" + "loc_data": "{1,2094,3152,0,150}-{1,2785,3279,0,150}-{1,2786,3287,0,150}-{1,2786,3286,0,150}-" }, { "item_id": "960", @@ -339,6 +339,14 @@ "item_id": "1422", "loc_data": "{1,3320,3137,0,150}-" }, + { + "item_id": "1467", + "loc_data": "{1,2784,3289,0,0}-" + }, + { + "item_id": "1469", + "loc_data": "{1,2766,3277,0,100}-{1,2766,3289,0,100}-" + }, { "item_id": "1510", "loc_data": "{1,2576,3334,0,100}-" diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 5e1c318d1..52829dd81 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -10473,6 +10473,11 @@ "range_level": "1", "attack_level": "22" }, + { + "examine": "A rather nasty looking crustacean.", + "name": "Sea slug", + "id": "1006" + }, { "examine": "A servant of Zamorak.", "combat_style": "2", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 99aba5be0..cd347d1b0 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -925,7 +925,7 @@ }, { "npc_id": "316", - "loc_data": "{3086,3227,0,0,1}-{3085,3230,0,0,0}-{2986,3176,0,0,4}-{2996,3157,0,0,1}-" + "loc_data": "{3086,3227,0,0,1}-{3085,3230,0,0,0}-{2986,3176,0,0,4}-{2996,3157,0,0,1}-{2790,3273,0,0,1}-{2790,3276,0,0,6}-{2794,3283,0,0,6}-{2795,3279,0,0,3}-" }, { "npc_id": "322", @@ -1995,14 +1995,42 @@ "npc_id": "694", "loc_data": "{2659,3431,0,0,3}-" }, + { + "npc_id": "695", + "loc_data": "{2765,3276,0,1,3}-" + }, { "npc_id": "696", "loc_data": "{2716,3303,0,1,1}-" }, + { + "npc_id": "697", + "loc_data": "{2766,3288,1,0,6}-" + }, { "npc_id": "698", + "loc_data": "{2799,3320,0,1,1}-" + }, + { + "npc_id": "700", "loc_data": "{2716,3303,0,1,1}-" }, + { + "npc_id": "701", + "loc_data": "{2793,3321,0,1,1}-" + }, + { + "npc_id": "702", + "loc_data": "{2774,3273,0,1,0}-{2775,3284,0,1,0}-{2781,3290,1,1,0}-{2785,3284,1,1,0}-" + }, + { + "npc_id": "703", + "loc_data": "{2770,3284,0,1,0}-{2794,3279,0,1,0}-{2768,3285,1,1,0}-{2784,3277,1,1,0}-" + }, + { + "npc_id": "704", + "loc_data": "{2778,3291,0,1,0}-{2773,3282,1,1,0}-{2787,3280,1,1,0}-" + }, { "npc_id": "705", "loc_data": "{3208,3252,0,0,6}-" @@ -2635,6 +2663,10 @@ "npc_id": "1005", "loc_data": "{3057,3905,0,1,3}-" }, + { + "npc_id": "1006", + "loc_data": "{2763,3284,0,1,0}-{2768,3274,0,1,0}-{2768,3288,0,1,0}-{2770,3277,0,1,0}-{2770,3290,0,1,0}-{2771,3279,0,1,0}-{2774,3291,0,1,0}-{2778,3285,0,1,0}-{2781,3278,0,1,0}-{2781,3285,0,1,0}-{2783,3275,0,1,0}-{2784,3279,0,1,0}-{2785,3276,0,1,0}-{2785,3287,0,1,0}-{2788,3274,0,1,0}-{2793,3275,0,1,0}-{2793,3280,0,1,0}-{2768,3282,1,1,0}-{2770,3282,1,1,0}-{2773,3291,1,1,0}-{2780,3283,1,1,0}-{2780,3290,1,1,0}-{2783,3286,1,1,0}-{2784,3279,1,1,0}-{2785,3282,1,1,0}-" + }, { "npc_id": "1010", "loc_data": "{2629,2979,0,1,0}-" @@ -7995,6 +8027,10 @@ "npc_id": "4856", "loc_data": "{2732,3292,0,1,1}-" }, + { + "npc_id": "4871", + "loc_data": "{2782,3276,0,1,0}-" + }, { "npc_id": "4872", "loc_data": "{2740,3310,0,0,0}-" @@ -8019,6 +8055,10 @@ "npc_id": "4887", "loc_data": "{2738,3303,0,1,1}-{2723,3274,0,1,1}-" }, + { + "npc_id": "4891", + "loc_data": "{2768,3286,0,1,0}-{2777,3278,0,1,0}-{2783,3289,0,1,0}-{2784,3277,0,1,0}-{2768,3289,1,1,0}-{2780,3288,1,1,0}-" + }, { "npc_id": "4895", "loc_data": "{2718,3302,0,1,1}-" diff --git a/Server/src/main/content/global/skill/cooking/CookingRewrite.kt b/Server/src/main/content/global/skill/cooking/CookingRewrite.kt index 76d485956..7bc993a8b 100644 --- a/Server/src/main/content/global/skill/cooking/CookingRewrite.kt +++ b/Server/src/main/content/global/skill/cooking/CookingRewrite.kt @@ -66,7 +66,7 @@ class CookingRewrite : InteractionListener { } companion object { - val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3039, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377) + val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3039, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 18170, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377) @JvmStatic fun cook(player: Player, `object`: Scenery?, initial: Int, product: Int, amount: Int) { diff --git a/Server/src/main/content/global/skill/crafting/lightsources/LightSourceLighter.kt b/Server/src/main/content/global/skill/crafting/lightsources/LightSourceLighter.kt index e25677810..81a1a98cc 100644 --- a/Server/src/main/content/global/skill/crafting/lightsources/LightSourceLighter.kt +++ b/Server/src/main/content/global/skill/crafting/lightsources/LightSourceLighter.kt @@ -66,6 +66,12 @@ class LightSourceLighter : UseWithHandler(590,36,38){ lightSource ?: return false + // For Sea Slug Quest - No lighting of any torch on the fishing platform. + if(event.player.location.isInRegion(11059)) { + event.player.sendMessage("Your tinderbox is damp from the sea crossing. It won't work here.") + return true + } + if(!light(event.player,used,lightSource)){ event.player.sendMessage("You need a Firemaking level of at least ${lightSource.levelRequired} to light this.") } diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/BaileyDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/BaileyDialogue.kt new file mode 100644 index 000000000..67d446af2 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/BaileyDialogue.kt @@ -0,0 +1,24 @@ +package content.region.kandarin.witchhaven.dialogue + +import content.region.kandarin.witchhaven.quest.seaslug.BaileyDialogueFile +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class BaileyDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return BaileyDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, BaileyDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.BAILEY_695) + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/CarolineDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/CarolineDialogue.kt index 477aa8020..cc3b0ad95 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/dialogue/CarolineDialogue.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/CarolineDialogue.kt @@ -1,41 +1,29 @@ package content.region.kandarin.witchhaven.dialogue +import content.region.kandarin.witchhaven.quest.seaslug.CarolineDialogueFile +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills import core.plugin.Initializable +import org.rs09.consts.Items import org.rs09.consts.NPCs -/** - * @author qmqz - */ - @Initializable class CarolineDialogue(player: Player? = null) : DialoguePlugin(player){ - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - player(FacialExpression.FRIENDLY,"Hello again.").also { stage = 0 } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - 0 -> npc(FacialExpression.FRIENDLY, "Hello traveller, how are you?").also { stage++ } - 1 -> player(FacialExpression.FRIENDLY, "Not bad thanks, yourself?").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "I'm good. Busy as always looking after Kent and Kennith but no complaints.").also { stage = 99 } - - 99 -> end() - } - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { + override fun newInstance(player: Player): DialoguePlugin { return CarolineDialogue(player) } - + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, CarolineDialogueFile(), npc) + return true + } override fun getIds(): IntArray { return intArrayOf(NPCs.CAROLINE_696) } -} +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartDialogue.kt index 4d99bdf08..5f7432efa 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartDialogue.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartDialogue.kt @@ -1,5 +1,7 @@ package content.region.kandarin.witchhaven.dialogue +import content.region.kandarin.witchhaven.quest.seaslug.HolgartDialogueFile +import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC @@ -7,37 +9,18 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs -/** - * @author qmqz - */ - @Initializable class HolgartDialogue(player: Player? = null) : DialoguePlugin(player){ - fun gender (male : String = "sir", female : String = "madam") = if (player.isMale) male else female - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - player(FacialExpression.FRIENDLY,"Hello there.").also { stage = 0 } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - 0 -> npc(FacialExpression.FRIENDLY, "Well hello " + gender() + ", beautiful day isn't it?").also { stage++ } - 1 -> player(FacialExpression.FRIENDLY, "Not bad I suppose.").also { stage++ } - 2 -> npc(FacialExpression.FRIENDLY, "Just smell that sea air... beautiful.").also { stage++ } - 3 -> player(FacialExpression.FRIENDLY, "Hmm... lovely...").also { stage = 99 } - - 99 -> end() - } - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { + override fun newInstance(player: Player): DialoguePlugin { return HolgartDialogue(player) } - + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, HolgartDialogueFile(), npc) + return true + } override fun getIds(): IntArray { - return intArrayOf(NPCs.HOLGART_4866) + return intArrayOf(NPCs.HOLGART_700) + // return intArrayOf(NPCs.HOLGART_4866) } } diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartIslandDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartIslandDialogue.kt new file mode 100644 index 000000000..883bdd746 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartIslandDialogue.kt @@ -0,0 +1,27 @@ +package content.region.kandarin.witchhaven.dialogue + +import content.region.kandarin.witchhaven.quest.seaslug.HolgartIslandDialogueFile +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +// This is to handle when Holgart is on the fishing platform. +@Initializable +class HolgartIslandDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return HolgartIslandDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, HolgartIslandDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.HOLGART_698) + // return intArrayOf(NPCs.HOLGART_4866) + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartPlatformDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartPlatformDialogue.kt new file mode 100644 index 000000000..3ac3027c9 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/HolgartPlatformDialogue.kt @@ -0,0 +1,27 @@ +package content.region.kandarin.witchhaven.dialogue + +import content.region.kandarin.witchhaven.quest.seaslug.HolgartPlatformDialogueFile +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +// This is to handle when Holgart is on the fishing platform. +@Initializable +class HolgartPlatformDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return HolgartPlatformDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, HolgartPlatformDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.HOLGART_699, NPCs.FISHERMAN_4871) + // return intArrayOf(NPCs.HOLGART_4866) + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/KennithDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/KennithDialogue.kt new file mode 100644 index 000000000..2ad5de63a --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/KennithDialogue.kt @@ -0,0 +1,45 @@ +package content.region.kandarin.witchhaven.dialogue + +import content.region.kandarin.witchhaven.quest.seaslug.KennithDialogueFile +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.NPCs + +class KennithDialogue : InteractionListener { + + override fun defineListeners() { + on(NPCs.KENNITH_4864, IntType.NPC, "talk-to"){ player, npc -> + openDialogue(player, KennithDialogueFile(), npc) + return@on true + } + } + + // Because Kennith is behind the counter + override fun defineDestinationOverrides() { + setDest(IntType.NPC, intArrayOf(NPCs.KENNITH_4864),"talk-to"){ _, _ -> + return@setDest Location.create(2765, 3286, 1) + } + } +} + +// INSTEAD OF THIS as Kennith is unreachable. +//@Initializable +//class KennithDialogue(player: Player? = null) : DialoguePlugin(player){ +// override fun newInstance(player: Player): DialoguePlugin { +// return KennithDialogue(player) +// } +// override fun handle(interfaceId: Int, buttonId: Int): Boolean { +// // Fallback to default. Always the start of Sea Slug +// openDialogue(player!!, KennithDialogueFile(), npc) +// return true +// } +// override fun getIds(): IntArray { +// // Base is CAROLINE_697 (Should be named KENNITH_697) +// return intArrayOf(NPCs.CAROLINE_697, NPCs.KENNITH_4864) +// } +//} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/KentDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/KentDialogue.kt new file mode 100644 index 000000000..25b3c447e --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/KentDialogue.kt @@ -0,0 +1,24 @@ +package content.region.kandarin.witchhaven.dialogue + +import content.region.kandarin.witchhaven.quest.seaslug.KentDialogueFile +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class KentDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return KentDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, KentDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + // Base is CAROLINE_697 (Should be named KENNITH_697) + return intArrayOf(NPCs.KENT_701) + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchavenVillagerDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchavenVillagerDialogue.kt new file mode 100644 index 000000000..8bb49bd9b --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchavenVillagerDialogue.kt @@ -0,0 +1,83 @@ +package content.region.kandarin.witchhaven.dialogue + +import core.api.openDialogue +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class WitchavenVillagerDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return WitchavenVillagerDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, WitchavenVillagerDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.WITCHAVEN_VILLAGER_4883, NPCs.WITCHAVEN_VILLAGER_4884, + NPCs.WITCHAVEN_VILLAGER_4885, NPCs.WITCHAVEN_VILLAGER_4886, + NPCs.WITCHAVEN_VILLAGER_4887, NPCs.WITCHAVEN_VILLAGER_4888) + } +} + +class WitchavenVillagerDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .player(FacialExpression.FRIENDLY, "Hello there.") + .branch { player -> + return@branch (0 .. 4).random() + }.let { branch -> + branch.onValue(0) + .npcl("What have you got to be so cheerful about?") + .playerl("Well, it's another nice day.") + .npcl("Ha! Try worrying about how you feed a family with no job. Then tell me how nice the day is!") + .playerl("Okay, I guess I've caught you at a bad time. Goodbye.") + .end() + + branch.onValue(1) + .npcl("Hmm? Oh, hello there.") + .playerl("Are you okay? You seem a bit preoccupied.") + .npcl("It's nothing stranger. No need to concern yourself.") + .end() + + branch.onValue(2) + .npcl("Spare a coin mister?") + .playerl("What do you need it for?") + .npcl("For a poor unemployed fisherman what needs to eat.") + .playerl("Why don't you just fish for some food?") + .npcl("Err... Goodbye mister.") + .end() + + branch.onValue(3) + .npcl("Can you believe they did this to us?") + .playerl("Wha...") + .npcl("I mean, what did they think would happen?") + .playerl("Who...") + .npcl("Building that whacking great Fishing Platform just off the coast.") + .playerl("Fish...") + .npcl("Dratted thing stole all of our trade.") + .playerl("Excuse...") + .npcl("I'm sorry, I'm too angry to speak right now. Goodbye") + .end() + + branch.onValue(4) + .npcl("With our nets and gear we're faring,") + .npcl("On the wild and wasteful ocean,") + .npcl("It's there on the deep that we harvest and reap our bread,") + .npcl("As we hunt the bonny shoals of herring.") + .playerl("That's a lovely song.") + .npcl("Aye lad, and sing it every day we did.") + .npcl("'Till the Fishing Platform came and ruined everything.") + .playerl("Oh, I'm sorry.") + .npcl("No need lad, it not be your fault.") + .end() + } + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchhavenVillageDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchhavenVillageDialogue.kt deleted file mode 100644 index 38b0f00e8..000000000 --- a/Server/src/main/content/region/kandarin/witchhaven/dialogue/WitchhavenVillageDialogue.kt +++ /dev/null @@ -1,78 +0,0 @@ -package content.region.kandarin.witchhaven.dialogue - -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import org.rs09.consts.NPCs - -/** - * @author qmqz - */ - -@Initializable -class WitchhavenVillageDialogue(player: Player? = null) : DialoguePlugin(player){ - - private val conversations = arrayOf (0, 7, 11, 19, 24) - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - player(FacialExpression.FRIENDLY, "Hello there.").also { stage = conversations.random() } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - - 0 -> sendDialogue("Their eyes are staring vacantly into space.").also { stage++ } - 1 -> npc(FacialExpression.NEUTRAL, "Ye mariners all, as ye pass by,").also { stage++ } - 2 -> npc(FacialExpression.NEUTRAL, "Come in and drink if you are dry,").also { stage++ } - 3 -> npc(FacialExpression.NEUTRAL, "Come spend, me lads, your money brisk,").also { stage++ } - 4 -> npc(FacialExpression.NEUTRAL, "And pop your nose in a jug of this.").also { stage++ } - 5 -> player(FacialExpression.NEUTRAL, "You're not fooling anyone you know.").also { stage++ } - 6 -> npc(FacialExpression.NEUTRAL, "We fooled you easily enough.").also { stage = 99 } - - 7 -> sendDialogue("Their eyes are staring vacantly into space.").also { stage++ } - 8 -> npc(FacialExpression.NEUTRAL, "Free. She is free...").also { stage++ } - 9 -> player(FacialExpression.NEUTRAL, "What?").also { stage++ } - 10 -> npc(FacialExpression.NEUTRAL, "The mother is free.").also { stage = 99 } - - 11 -> sendDialogue("Their eyes are staring vacantly into space.").also { stage++ } - 12 -> npc(FacialExpression.NEUTRAL, "You! You did it!").also { stage++ } - 13 -> player(FacialExpression.NEUTRAL, "I didn't mean to!").also { stage++ } - 14 -> npc(FacialExpression.NEUTRAL, "You killed him!").also { stage++ } - 15 -> player(FacialExpression.NEUTRAL, "It was an accide... Killed who?").also { stage++ } - 16 -> npc(FacialExpression.NEUTRAL, "Our Prince, you killed our Prince.").also { stage++ } - 17 -> player(FacialExpression.NEUTRAL, "Oh that, yes I did.").also { stage++ } - 18 -> npc(FacialExpression.NEUTRAL, "Leave us alone.").also { stage = 99 } - - 19 -> sendDialogue("Their eyes are staring vacantly into space.").also { stage++ } - 20 -> npc(FacialExpression.NEUTRAL, "Soon now... So soon...").also { stage++ } - 21 -> npc(FacialExpression.NEUTRAL, "The stars are almost right.").also { stage++ } - 22 -> player(FacialExpression.NEUTRAL, "For what?").also { stage++ } - 23 -> npc(FacialExpression.NEUTRAL, ". . .").also { stage = 99 } - - 24 -> sendDialogue("Their eyes are staring vacantly into space.").also { stage++ } - 25 -> npc(FacialExpression.NEUTRAL, "Ahh, our saviour.").also { stage++ } - 26 -> player(FacialExpression.NEUTRAL, "Please don't remind me.").also { stage++ } - 27 -> npc(FacialExpression.NEUTRAL, "Do not worry, soon your regret will be gone.").also { stage++ } - 28 -> player(FacialExpression.NEUTRAL, "If you think you will get to me...").also { stage++ } - 29 -> npc(FacialExpression.NEUTRAL, "All in good time.").also { stage = 99 } - - - 99 -> end() - } - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { - return WitchhavenVillageDialogue(player) - } - - override fun getIds(): IntArray { - return intArrayOf(NPCs.WITCHAVEN_VILLAGER_4883, NPCs.WITCHAVEN_VILLAGER_4884, - NPCs.WITCHAVEN_VILLAGER_4885, NPCs.WITCHAVEN_VILLAGER_4886, - NPCs.WITCHAVEN_VILLAGER_4887, NPCs.WITCHAVEN_VILLAGER_4888) - } -} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt new file mode 100644 index 000000000..baeaea137 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt @@ -0,0 +1,73 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class BaileyDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0,1,2,3,4) + .playerl(FacialExpression.FRIENDLY, "Hello there.") + .npcl(FacialExpression.SCARED, "What? Who are you? Come inside quickly!") + .npcl(FacialExpression.SCARED, "What are you doing here?") + .playerl("I'm trying to find out what happened to a boy named Kennith.") + .npcl("Oh you mean Kent's son. He's around somewhere, probably hiding if he knows what's good for him.") + .playerl(FacialExpression.THINKING, "Hiding from what? What's got you so frightened?") + .npcl("Haven't you seen all those things out there?") + .playerl(FacialExpression.THINKING, "The sea slugs?") + .npcl(FacialExpression.SUSPICIOUS, "It all began about a week ago. We pulled up a haul of deep sea flatfish. Mixed in with them we found these slug things, but thought nothing of it.") + .npcl(FacialExpression.SUSPICIOUS, "Not long after that my friends began to change, now they spend all day pulling in hauls of fish, only to throw back the fish and keep those nasty sea slugs.") + .npcl(FacialExpression.SUSPICIOUS, "What am I supposed to do with those? I haven't figured out how to kill one yet. If I put them near the stove they squirm and jump away.") + .playerl(FacialExpression.THINKING, "I doubt they would taste too good.") + .npcl(FacialExpression.ANGRY, "This is no time for humour.") + .playerl("I'm sorry, I didn't mean to upset you.") + .npcl(FacialExpression.SCARED, "That's okay. I just can't shake the feeling that this is the start of something... Terrible.") + .end() + + b.onQuestStages(SeaSlug.questName, 5) + .playerl("Hello.") + .npcl(FacialExpression.EXTREMELY_SHOCKED, "Oh, thank the gods it's you. They've all gone mad I tell you, one of the fishermen tried to throw me into the sea!") + .playerl("They're all being controlled by the sea slugs.") + .npcl("I figured as much.") + .playerl("I need to get Kennith off this platform, but I can't get past the fishermen.") + .npcl("The sea slugs are scared of heat... I figured that out when I tried to cook them.") + .npcl("Here.") + .betweenStage { _, player, _, _ -> + addItemOrDrop(player, Items.UNLIT_TORCH_596) + } + .iteml(Items.UNLIT_TORCH_596, "Bailey gives you a torch.") + .npcl("I doubt the fishermen will come near you if you can get this torch lit. The only problem is all the wood and flint are damp... I can't light a thing!") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 5) { + setQuestStage(player, SeaSlug.questName, 6) + } + } + + // We aren't going to give you a spare torch. Go get an unlit torch somewhere else. + b.onQuestStages(SeaSlug.questName, 6,7,8) + .playerl("Hello.") + .npcl("Oh, thank the gods it's you. They've all gone mad I tell you, one of the fishermen tried to throw me into the sea!") + .playerl("They're all being controlled by the sea slugs.") + .npcl("I figured as much.") + .playerl("I need to get Kennith off this platform, but I can't get past the fishermen.") + .npcl("The sea slugs are scared of heat... I figured that out when I tried to cook them.") + .npcl("I doubt the fishermen will come near you if you can get this torch lit. The only problem is all the wood and flint are damp... I can't light a thing!") + .end() + + b.onQuestStages(SeaSlug.questName, 9,10,100) + .playerl("I've managed to light the torch.") + .npcl("Well done traveller, you'd better get Kennith out of here soon. The fishermen are becoming stranger by the minute, and they keep pulling up those blasted sea slugs.") + .playerl("Don't worry I'm working on it.") + .npcl("Just be sure to watch your back. The fishermen seem to have taken notice of you.") + .end() + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt new file mode 100644 index 000000000..072778cb0 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt @@ -0,0 +1,70 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression +import core.game.node.entity.skill.Skills + +class CarolineDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0) + .playerl(FacialExpression.FRIENDLY, "Hello there.") + .npcl(FacialExpression.SAD, "Is there any chance you could help me?") + .playerl(FacialExpression.THINKING, "What's wrong?") + .npcl("It's my husband, he works on a fishing platform. Once a month he takes our son, Kennith, out with him.") + .npcl(FacialExpression.THINKING, "They usually write to me regularly, but I've heard nothing all week. It's very strange.") + .playerl("Maybe the post was lost!") + .npcl(FacialExpression.THINKING, "Maybe, but no-one's heard from the other fishermen on the platform. Their families are becoming quite concerned.") + .branch { player -> + return@branch if (hasLevelStat(player, Skills.FIREMAKING, 30)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .npcl("However, I don't think you are ready to visit the platform.") + .line("You need Level 30 Firemaking to start the Sea Slug quest.") + .end() + return@let branch.onValue(1) + } + .npcl(FacialExpression.HALF_THINKING, "Is there any chance you could visit the platform and find out what's going on?") + .options().let { optionBuilder -> + optionBuilder.option_playerl("I suppose so, how do I get there?") + .npcl("That's very good of you @name. My friend Holgart will take you there.") + .playerl("Ok, I'll go and see if they're ok.") + .npcl("I'll reward you for your time. It'll give me peace of mind to know Kennith and my husband, Kent, are safe.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 0) { + setQuestStage(player, SeaSlug.questName, 1) + } + } + optionBuilder.option_playerl("I'm sorry, I'm too busy.") + .npcl(FacialExpression.SAD, "That's a shame.") + .playerl("Bye.") + .npcl("Bye.") + .end() + } + + b.onQuestStages(SeaSlug.questName, 1,2,3,4,5,6,7,8,9,10) + .playerl("Hello Caroline.") + .npcl("Brave @name, have you any news about my son and his father?") + .playerl("I'm working on it now Caroline.") + .npcl("Please bring them back safe and sound.") + .playerl("I'll do my best.") + .end() + + b.onQuestStages(SeaSlug.questName, 11) + .playerl("Hello.") + .npcl("Brave @name, you've returned!") + .npcl("Kennith told me about the strange goings-on at the platform. I had no idea it was so serious.") + .npcl("I could have lost my son and my husband if it wasn't for you.") + .playerl("We found Kent stranded on an island.") + .npcl("Yes. Holgart told me and sent a rescue party out. Kent's back home now, resting with Kennith. I don't think he'll be doing any fishing for a while.") + .npcl("Here, take these Oyster pearls as a reward. They're worth quite a bit and can be used to make lethal crossbow bolts.") + .playerl(FacialExpression.FRIENDLY, "Thanks!") + .npcl(FacialExpression.FRIENDLY, "Thank you. Take care of yourself @name.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 11) { + finishQuest(player, SeaSlug.questName) + } + } + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/FishermanDialogue.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/FishermanDialogue.kt new file mode 100644 index 000000000..ba344e520 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/FishermanDialogue.kt @@ -0,0 +1,102 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.* +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class FishermanDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun newInstance(player: Player): DialoguePlugin { + return FishermanDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + // Fallback to default. Always the start of Sea Slug + openDialogue(player!!, FishermanDialogueFile(), npc) + return true + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.FISHERMAN_702, NPCs.FISHERMAN_703, NPCs.FISHERMAN_704) + } +} + +class FishermanDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .player(FacialExpression.FRIENDLY, "Hello there.") + .line("Their eyes are staring vacantly into space.") + .branch { player -> + return@branch (1 .. 1).random() + }.let { branch -> + branch.onValue(0) + .npc(FacialExpression.AMAZED, "Ye mariners all, as ye pass by,") + .npc(FacialExpression.AMAZED, "Come in and drink if you are dry,") + .npc(FacialExpression.AMAZED, "Come spend, me lads, your money brisk,") + .npc(FacialExpression.AMAZED, "And pop your nose in a jug of this.") + .player("You're not fooling anyone you know.") + .npc(FacialExpression.AMAZED, "We fooled you easily enough.") + .end() + + branch.onValue(1) + .npcl(FacialExpression.AMAZED,"You are not part of our family...") + .playerl("Umm. Not last time I checked.") + .npcl(FacialExpression.AMAZED,"Soon you will be... Soon you will...") + .end() + + branch.onValue(2) + .npcl(FacialExpression.AMAZED,"Keep away human... Leave or face the deep blue...") + .playerl("Pardon?") + .npcl(FacialExpression.AMAZED,"You will all end up in the blue... Deep deep under the blue...") + .end() + + branch.onValue(3) + .npcl(FacialExpression.AMAZED,"Lost to us.. She is Lost to us...") + .playerl("Who is lost?") + .npcl(FacialExpression.AMAZED,"Trapped by the light... Lost and trapped...") + .playerl("Ermm... So you don't want to tell me then?") + .npcl(FacialExpression.AMAZED,"Trapped... In stone and darkness...") + .end() + + branch.onValue(4) + .npcl(FacialExpression.AMAZED,"Must find family...") + .playerl("What?") + .npcl(FacialExpression.AMAZED,"Soon we will all be together...") + .playerl("Are you ok?") + .npcl(FacialExpression.AMAZED,"Must find family... They are all under the blue... Deep deep under the blue...") + .playerl("Ermm... I'll leave you to it then.") + .end() + + branch.onValue(5) + .npcl(FacialExpression.AMAZED,"Free of the deep blue we are...") + .npcl(FacialExpression.AMAZED,"We must find...") + .playerl("Yes?") + .npcl(FacialExpression.AMAZED,"a new home...") + .npcl(FacialExpression.AMAZED,"We must leave this place...") + .playerl("Where will you go?") + .npcl(FacialExpression.AMAZED,"Away.. Away to her...") + .playerl("Riiight.") + .end() + + branch.onValue(6) + .npcl(FacialExpression.AMAZED,"Below the deep, deep blue she waits...") + .playerl("Who waits?") + .npcl(FacialExpression.AMAZED,"They came to her with fire and faith...") + .playerl("Who? Who came to who?") + .npcl(FacialExpression.AMAZED,"Too many... Too many...") + .playerl("Too many what? Make sense!") + .npcl(FacialExpression.AMAZED,"Locked away for all eternity...") + .playerl("You'd better start making sense Sonny Jim or I'll...") + .npcl(FacialExpression.AMAZED,"Free... Soon to be free...") + .end() + + branch.onValue(7) + .npcl(FacialExpression.AMAZED,"Must escape the blue.. Deep deep blue") + .playerl("Pardon?") + .npcl(FacialExpression.AMAZED,"Family... Under the blue... Must escape the blue...") + .end() + } + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt new file mode 100644 index 000000000..4706357fe --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt @@ -0,0 +1,108 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import content.region.asgarnia.falador.quest.recruitmentdrive.RecruitmentDrive +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Components +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class HolgartDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0) + .playerl(FacialExpression.FRIENDLY, "Hello.") + .npcl(FacialExpression.FRIENDLY, "Well hello @g[m'lad,m'laddy]. Beautiful day isn't it?") + .playerl("Not bad I suppose.") + .npcl("Just smell that sea air... beautiful.") + .playerl(FacialExpression.THINKING, "Hmm... lovely...") + .end() + + b.onQuestStages(SeaSlug.questName, 1) + .npcl(FacialExpression.FRIENDLY, "Hello, m'hearty.") + .playerl("I would like a ride on your boat to the fishing platform.") + .npcl(FacialExpression.SAD, "I'm afraid it isn't sea worthy, it's full of holes. To fill the holes I'll need some swamp paste.") + .playerl(FacialExpression.THINKING, "Swamp paste?") + .npcl("Yes, swamp tar mixed with flour and heated over a fire.") + .branch { player -> + return@branch if (inInventory(player, Items.SWAMP_PASTE_1941)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .playerl("Where can I find swamp tar?") + .npcl("Unfortunately the only supply of swamp tar is in the swamps below Lumbridge. It's too far for an old man like me to travel.") + .npcl("If you make me some swamp paste I'll give you a ride in my boat.") + .playerl("I'll see what I can do.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 1) { + setQuestStage(player, SeaSlug.questName, 2) + } + } + branch.onValue(1) + .npcl("In fact, unless me nose be mistaken, you've got some in yer pack.") + .playerl("Oh yes, I forgot about that stuff. Can you use it?") + .npcl("Aye @g[lad,lass]. That be perfect.") + .betweenStage { _, player, _, _ -> + removeItem(player, Items.SWAMP_PASTE_1941) + } + .iteml(Items.SWAMP_PASTE_1941, "You give Holgart the swamp paste.") + // Cutscene + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 1) { + setQuestStage(player, SeaSlug.questName, 3) + } + } + } + + b.onQuestStages(SeaSlug.questName, 2) + .playerl(FacialExpression.FRIENDLY, "Hello.") + .npcl("Hello, m'hearty. Did you manage to make some swamp paste?") + .branch { player -> + return@branch if (inInventory(player, Items.SWAMP_PASTE_1941)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .playerl("I'm afraid not.") + .npcl("It's simply swamp tar mixed with flour heated over a fire. Unfortunately the only supply of swamp tar is in the swamps below Lumbridge.") + .npcl("I can't fix my row boat without it.") + .playerl("Ok, I'll try to find some.") + .end() + branch.onValue(1) + .playerl("Yes, I have some here.") + .betweenStage { _, player, _, _ -> + removeItem(player, Items.SWAMP_PASTE_1941) + } + .iteml(Items.SWAMP_PASTE_1941, "You give Holgart the swamp paste.") + // Cutscene + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 2) { + setQuestStage(player, SeaSlug.questName, 3) + } + } + + } + + + b.onQuestStages(SeaSlug.questName, 3,4,5,6,7,8,9,10,11,100) + .playerl(FacialExpression.FRIENDLY, "Hello, Holgart.") + .npcl("Hello again land lover. There's some strange goings on, on that platform, I tell you.") + .options().let { optionBuilder -> + optionBuilder.option("Will you take me there?") + .playerl(FacialExpression.THINKING, "Will you take me there?") + .npcl("Of course m'hearty. If that's what you want.") + .endWith() { df, player -> + SeaSlugListeners.seaslugBoatTravel(player, 0) + } + + optionBuilder.option_playerl("I'm keeping away from there.") + .npcl("Fair enough m'hearty.") + .end() + } + + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt new file mode 100644 index 000000000..513c07456 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt @@ -0,0 +1,29 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class HolgartIslandDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0,1,2,3,5,6,7,8,9,10,11,100) + .playerl("We'd better get back to the platform so we can see what's going on.") + .npcl(FacialExpression.SUSPICIOUS, "You're right. It all sounds pretty creepy.") + .endWith() { df, player -> + SeaSlugListeners.seaslugBoatTravel(player, 3) + } + b.onQuestStages(SeaSlug.questName, 4) + .playerl("Where are we?") + .npc("Someway off mainland still. You'd better see if me old", "matey's okay.") + .end() + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt new file mode 100644 index 000000000..8bd93bfe9 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt @@ -0,0 +1,41 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression + +class HolgartPlatformDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0,1,2,3,5,6,7,8,9,10,100) + .playerl(FacialExpression.FRIENDLY, "Hey, Holgart.") + .npcl("Have you had enough of this place yet? It's really starting to scare me.") + .options().let { optionBuilder -> + optionBuilder.option_playerl("Okay, let's go back.") + .endWith() { df, player -> + SeaSlugListeners.seaslugBoatTravel(player, 1) + } + optionBuilder.option_playerl("No, I'm going to stay a while.") + .npcl("Okay... you're the boss.") + .end() + } + + b.onQuestStages(SeaSlug.questName, 4) + .playerl("Holgart, something strange is going on here.") + .npcl("You're telling me, none of the sailors seem to remember who I am.") + .playerl("Apparently Kennith's father left for help a couple of days ago.") + .npcl("That's a worry, no-one's heard from him on shore. Come on, we'd better go look for him.") + .endWith() { df, player -> + SeaSlugListeners.seaslugBoatTravel(player, 2) + } + + b.onQuestStages(SeaSlug.questName, 11) + .playerl("Did you get the kid back to shore?") + .npcl("Yes, he's safe and sound with his parents. Your turn to return to land now adventurer.") + .playerl("Looking forward to it.") + .endWith() { df, player -> + SeaSlugListeners.seaslugBoatTravel(player, 1) + } + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt new file mode 100644 index 000000000..f67bfbe42 --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt @@ -0,0 +1,75 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class KennithDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0,1,2,3) + .playerl(FacialExpression.THINKING, "Are you okay young one?") + .npcl(FacialExpression.CHILD_SAD, "No, I want daddy!") + .playerl("Where is your father?") + .npcl(FacialExpression.CHILD_SAD, "He went to get help days ago.") + .npcl(FacialExpression.CHILD_SAD, "The nasty fishermen tried to throw me and daddy into the sea. So he told me to hide here.") + .playerl("That's good advice, you stay here and I'll go try and find your father.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 3) { + setQuestStage(player, SeaSlug.questName, 4) + } + } + b.onQuestStages(SeaSlug.questName, 4,5,6) + .playerl(FacialExpression.THINKING, "Are you okay?") + .npcl(FacialExpression.CHILD_SAD, "I want to see daddy!") + .playerl("I'm working on it.") + .end() + + b.onQuestStages(SeaSlug.questName, 7) + .playerl("Hello Kennith, are you okay?") + .npcl(FacialExpression.CHILD_SAD, "No, I want my daddy.") + .playerl("You'll be able to see him soon. First we need to get you back to land, come with me to the boat.") + .npcl(FacialExpression.CHILD_SHOCKED, "No!") + .playerl("What, why not?") + .npcl(FacialExpression.CHILD_SHOCKED, "I'm scared of those nasty sea slugs. I won't go near them.") + .playerl("Okay, you wait here and I'll go figure another way to get you out.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 7) { + setQuestStage(player, SeaSlug.questName, 8) + } + } + + b.onQuestStages(SeaSlug.questName, 8) + // This stage is unfortunately left out. You can't interact with Kennith authentically. + .end() + + b.onQuestStages(SeaSlug.questName, 9) + .playerl("Kennith, I've made an opening in the wall. You can come out through there.") + .npcl(FacialExpression.CHILD_THINKING, "Are there any sea slugs on the other side?") + .playerl("Not one.") + .npcl(FacialExpression.CHILD_THINKING, "How will I get downstairs?") + .playerl("I'll figure that out in a moment.") + .npcl(FacialExpression.CHILD_NORMAL, "Ok, when you have I'll come out.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 9) { + setQuestStage(player, SeaSlug.questName, 10) + } + } + + b.onQuestStages(SeaSlug.questName, 10) + // This stage is also unfortunately left out. You can't interact with Kennith authentically. + .end() + + b.onQuestStages(SeaSlug.questName, 11,100) + // Kennith is varp swapped out, so is no longer here. + .end() + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt new file mode 100644 index 000000000..4c0174d2a --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt @@ -0,0 +1,47 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class KentDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(SeaSlug.questName, 0,1,2,3,4,5,6) + .npcl("Oh thank Saradomin! I thought I'd be left out here forever.") + .playerl("Your wife sent me out to find you and your boy. Kennith's fine by the way, he's on the platform.") + .npcl("I knew the row boat wasn't sea worthy. I couldn't risk bringing him along but you must get him off that platform.") + .playerl("What's going on here?") + .npcl("Five days ago we pulled in a huge catch. As well as fish we caught small slug like creatures, hundreds of them.") + .npcl("That's when the fishermen began to act strange.") + .npcl("It was the sea slugs, they attack themselves to your body and somehow take over the mind of the carrier.") + .npcl("I told Kennith to hide until I returned but I was washed up here.") + .npcl("Please go back and get my boy, you can send help for me later.") + .npcl(FacialExpression.EXTREMELY_SHOCKED, "@name wait!") + .betweenStage { _, player, _, _ -> + visualize(npc!!, 4807, 790) + sendMessage(player, "*slooop*") + sendMessage(player, "He pulls a sea slug from under your top.") + } + .npcl("A few more minutes and that thing would have full control of your body.") + .playerl(FacialExpression.EXTREMELY_SHOCKED, "Yuck! Thanks Kent.") + .endWith() { df, player -> + if(getQuestStage(player, SeaSlug.questName) == 4) { + setQuestStage(player, SeaSlug.questName, 5) + } + } + + b.onQuestStages(SeaSlug.questName, 5,6,7,8,9,10,11,100) + .playerl("Hello.") + .npcl("Oh my, I must get back to shore.") + .end() + + } +} diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt new file mode 100644 index 000000000..2bce4e52c --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt @@ -0,0 +1,187 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import content.region.morytania.quest.creatureoffenkenstrain.CreatureOfFenkenstrain +import core.api.* +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items + +/** + * Sea Slug Quest + * + * Note that the varp 159 controls the quest AND some environments: + * The BADLY_REPAIRED_WALL_18381 disappears after varp 159 is set to 9 + * KENNITH_4864 disappears after varp 159 is set to 11 + * KENNITH_4865 (but ID 4864) appears after varp 159 is set to 11 + * + * https://www.youtube.com/watch?v=lf83SACuIDw (This is amazing) + * https://www.youtube.com/watch?v=VnghpKbUqKw + * https://www.youtube.com/watch?v=thHuATlGYag + * https://www.youtube.com/watch?v=VR91Rbyuou4 (This has many other unvisited paths) + */ +@Initializable +class SeaSlug : Quest("Sea Slug", 109, 108, 1,159, 0, 1, 12) { + + companion object { + const val questName = "Sea Slug" + const val questVarp = 159 + } + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player, questName) > 0 + + if (!started) { + line(player, "I can start this quest by speaking to !!Caroline?? who is !!East??", line++, false) + line(player, "!!of Ardougne??.", line++, false) + line++ + line(player, "Requirements:", line++, false) + // I think this is an old line. I saw it being the other line for 30 Firemaking reqs. + line(player, "You'll need level 30 !!Firemaking??", line++, hasLevelStat(player, Skills.FIREMAKING, 30)) + // line(player, "!!Level 30 Firemaking??", line++, hasLevelStat(player, Skills.FIREMAKING, 30)) + } else { + line(player, "I have spoken to Caroline and agreed to help", line++, true) + line++ + + if (stage >= 3) { + line(player, "I gave Holgart the Swamp Paste and his boat is now ready", line++, true) + line(player, "to take me to the Fishing Platform", line++, true) + } else if (stage >= 2) { + // authentic from https://www.youtube.com/watch?v=VnghpKbUqKw + line(player, "I've spoken to !!Holgart?? but his boat is broken", line++, false) + line(player, "He needs me to bring him some !!Swamp Paste??", line++, false) + line++ + line(player, "I can make !!Swamp Paste?? by mixing !!Swamp Tar?? with !!Flour?? and", line++, false) + line(player, "then heating the mixture on a !!Fire??", line++, false) + line(player, "I can find !!Swamp Tar?? in the !!Swamp South of Lumbridge??", line++, false) + line++ + line(player, "I need to get to the !!Fishing Platform?? and find out what's", line++, false) + line(player, "happened to Kent and Kennith", line++, false) + } else if (stage >= 1) { + // derived + line(player, "I need to speak to !!Holgart??.", line++, false) + } + + if (stage >= 5) { + line++ + line(player, "I've found Kennith, he's hiding behind some boxes.", line++, true) + line++ + line(player, "I've found Kent on a small island", line++, true) + } else if (stage >= 4) { + line++ + line(player, "I've found Kennith, he's hiding behind some boxes.", line++, true) + line++ + line(player, "I need to find !!Kent??", line++, false) + } else if (stage >= 3) { + line++ + line(player, "I need to find !!Kent?? and !!Kennith??", line++, false) + } + + if (stage >= 9) { + line++ + line(player, "!!Kent?? has asked me to help !!Kennith?? escape", line++, true) + } else if (stage >= 5) { + line++ + line(player, "!!Kent?? has asked me to help !!Kennith?? escape", line++, false) + } + + if (stage >= 9) { + line(player, "After speaking to Bailey, I found that Sea Slugs are", line++, true) + line(player, "afraid of heat.", line++, true) + line(player, "I should find a way of lighting this damp torch.", line++, true) + } else if (stage >= 6) { + line(player, "After speaking to !!Bailey??, I found that Sea Slugs are", line++, false) + line(player, "afraid of heat.", line++, false) + line(player, "I should find a way of lighting this damp torch.", line++, false) + } + + if (stage >= 8) { + // Disappears + } else if (stage >= 7) { + // Derived + line(player, "I should talk to !!Kennith??", line++, false) + } + + if (stage >= 9) { + line(player, "I've created an opening to let Kennith escape", line++, true) + } else if (stage >= 8) { + // Derived + line(player, "I need to find a way to get !!Kennith?? out", line++, false) + } + + if (stage >= 10) { + line++ + line(player, "Kennith can't get downstairs without some help", line++, true) + } else if (stage >= 9) { + // Derived + line++ + line(player, "I should talk to !!Kennith?? again", line++, false) + } + + + if (stage >= 11) { + line++ + line(player, "I've used the Crane to lower Kennith into the boat", line++, true) + } else if (stage >= 10) { + line++ + line(player, "!!Kennith?? won't go near the !!Sea Slugs??", line++, false) + line(player, "I need to find another way to get him out", line++, false) + } + + if (stage >= 100) { + line++ + line(player, "I've spoken to Caroline and she thanked me for", line++, true) + line(player, "rescuing her family from the Sea Slugs", line++, true) + } else if (stage >= 11) { + line++ + line(player, "I need to take the boat back to shore and talk to !!Caroline??", line++, false) + } + + if (stage >= 100) { + line++ + line(player,"QUEST COMPLETE!", line) + } + } + + } + + override fun reset(player: Player) { + // removeAttribute(player, attributeTalkedToHolgart) + } + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed Sea Slug!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.SEA_SLUG_1466,230,277,5) + + drawReward(player, "1 Quest Point", ln++) + drawReward(player, "7175 Fishing XP", ln++) + drawReward(player, "Oyster pearls", ln++) + + rewardXP(player, Skills.FISHING, 7175.0) + addItemOrDrop(player, Items.OYSTER_PEARLS_413) + } + + override fun setStage(player: Player, stage: Int) { + super.setStage(player, stage) + this.updateVarps(player) + } + + override fun updateVarps(player: Player) { + // The quest stages are perfectly aligned with the varp since the varp controls npcs and sceneries + if (getQuestStage(player, questName) >= 12) { + setVarp(player, questVarp, 12, true) // Except for stage 100 which is varp set to 12 obviously. + } else { + setVarp(player, questVarp, getQuestStage(player, questName), true) + } + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt new file mode 100644 index 000000000..85c2838ee --- /dev/null +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt @@ -0,0 +1,192 @@ +package content.region.kandarin.witchhaven.quest.seaslug + +import core.api.* +import core.game.global.action.ClimbActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.combat.ImpactHandler +import core.game.node.entity.combat.ImpactHandler.HitsplatType +import core.game.node.entity.player.Player +import core.game.world.map.Location +import org.rs09.consts.Components +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class SeaSlugListeners : InteractionListener { + + companion object { + + // The boat travels are animated nicely for you by un-hiding child 10 - 13 + val BOAT_TRAVEL_CHILD = arrayOf(10, 11, 12, 13) + val BOAT_TRAVEL_TICKS = arrayOf(5, 9, 8, 7) + val BOAT_TRAVEL_DESTINATION = arrayOf( + Location(2782, 3273), // From LAND to PLATFORM + Location(2721, 3304), // From PLATFORM to LAND + Location(2800, 3320), // From PLATFORM to ISLAND + Location(2782, 3273), // From ISLAND to PLATFORM + ) + val BOAT_TRAVEL_DIALOGUE = arrayOf( + "You arrive at the fishing platform.", // From LAND to PLATFORM + "The boat arrives at Witchaven.", // From PLATFORM to LAND + "You arrive on a small island.", // From PLATFORM to ISLAND + "You arrive at the fishing platform.", // From ISLAND to PLATFORM + ) + + fun seaslugBoatTravel(player: Player, travelIndex: Int) { + if (travelIndex == 0) { + // Prevent bringing lit torches. + while(removeItem(player, Items.LIT_TORCH_594)) { + sendMessage(player, "Your torch goes out on the crossing.") + addItemOrDrop(player, Items.UNLIT_TORCH_596) + } + } + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when(stage){ + 0 -> { + closeOverlay(player) + openOverlay(player, Components.FADE_TO_BLACK_120) + lock(player, 2) + return@queueScript delayScript(player, 1) + } + 1 -> { + teleport(player, BOAT_TRAVEL_DESTINATION[travelIndex]) + openOverlay(player, Components.SEASLUG_BOAT_TRAVEL_461) + setComponentVisibility(player, Components.SEASLUG_BOAT_TRAVEL_461, BOAT_TRAVEL_CHILD[travelIndex], false) + lock(player, BOAT_TRAVEL_TICKS[travelIndex]) + return@queueScript delayScript(player, BOAT_TRAVEL_TICKS[travelIndex]) + } + 2 -> { + sendDialogue(player, BOAT_TRAVEL_DIALOGUE[travelIndex]) + player.interfaceManager.closeOverlay() + openOverlay(player, Components.FADE_FROM_BLACK_170) + return@queueScript stopExecuting(player) + } + } + return@queueScript stopExecuting(player) + } + } + + } + override fun defineListeners() { + // https://www.youtube.com/watch?v=VR91Rbyuou4 + // Your tinderbox is damp from the sea crossing. It won't light here. + // Your torch goes out on the crossing. + + onUseWith(IntType.ITEM, Items.SWAMP_TAR_1939, Items.POT_OF_FLOUR_1933){ player, used, with -> + if(removeItem(player, used) && removeItem(player, with)) { + sendMessage(player, "You mix the flour with the swamp tar.") + sendMessage(player, "It mixes into a paste.") + addItemOrDrop(player, Items.EMPTY_POT_1931) + addItemOrDrop(player, Items.RAW_SWAMP_PASTE_1940) + } + return@onUseWith true + } + + // You can only cook it using firewood. + // sendMessage(player, "You can't cook that in a range.") + onUseWith(SCENERY, Items.RAW_SWAMP_PASTE_1940, Scenery.FIRE_2732) { player, used, with -> + if(removeItem(player, used)) { + sendMessage(player, "You warm the paste over the fire. It thickens into a sticky goo.") + addItemOrDrop(player, Items.SWAMP_PASTE_1941) + } + return@onUseWith true + } + + + on(Scenery.LADDER_18324, IntType.SCENERY, "climb-up") { player, _ -> + if (getQuestStage(player, SeaSlug.questName) in 5..6) { + if (getQuestStage(player, SeaSlug.questName) == 6 && inInventory(player, Items.LIT_TORCH_594)) { + setQuestStage(player, SeaSlug.questName, 7) + ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location(2784, 3285, 1)) + } else { + animate(player, 4785) + sendMessage(player, "You attempt to climb up the ladder.") + sendMessage(player, "The fisherman approach you...") + sendMessage(player, "and smack you on the head with a fishing rod!") + sendMessage(player, "Ouch!") + sendChat(player, "Ouch!") + player.impactHandler.manualHit(player, 4, ImpactHandler.HitsplatType.NORMAL) + } + } else { + ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location(2784, 3285, 1)) + } + return@on true + } + on(Scenery.LADDER_18325, IntType.SCENERY, "climb-down") { player, _ -> + ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, Location(2784, 3287, 0)) + return@on true + } + + on(Scenery.BADLY_REPAIRED_WALL_18381, IntType.SCENERY, "kick") { player, _ -> + if(getQuestStage(player, SeaSlug.questName) == 8) { + animate(player, 4804) + sendMessage(player, "You kick the loose panel.") + sendMessage(player, "The wood is rotted and crumbles away...") + sendMessage(player, "... leaving an opening big enough for Kennith to climb through.") + setQuestStage(player, SeaSlug.questName, 9) + } else { + // https://youtu.be/OM-akv7oIZ0 2:41 + sendMessage(player, "You kick the loose panel...") + sendMessage(player, "... but nothing interesting happens.") + } + return@on true + } + + on(Scenery.CRANE_18327, IntType.SCENERY, "rotate") { player, node -> + if(getQuestStage(player, SeaSlug.questName) == 10) { + // This is supposed to be a cutscene, but goddamn do I hate programming cutscenes. + lock(player, 6) + player.dialogueInterpreter.sendPlainMessage(true, "Kennith scrambles through the broken wall...") + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CRANE_18326, 6) + animateScenery(node as core.game.node.scenery.Scenery, 4798) + setQuestStage(player, SeaSlug.questName, 11) + queueScript(player, 6, QueueStrength.SOFT) { stage: Int -> + sendDialogue(player, "Down below, you see Holgart collect the boy from the crane and lead him away to safety.") + return@queueScript stopExecuting(player) + } + } else { + sendMessage(player, "You rotate the crane around.") + animateScenery(node as core.game.node.scenery.Scenery, 4796) + } + return@on true + } + + onUseWith(IntType.ITEM, Items.DAMP_STICKS_1467, Items.BROKEN_GLASS_1469){ player, used, with -> + if(removeItem(player, used)) { + visualize(player, 4809, 791) + addItemOrDrop(player, Items.DRY_STICKS_1468) + } + return@onUseWith true + } + + onUseWith(IntType.ITEM, Items.DRY_STICKS_1468, Items.UNLIT_TORCH_596){ player, bolt, tip -> + addItemOrDrop(player, Items.LIT_TORCH_594) + return@onUseWith true + } + + on(Items.DRY_STICKS_1468, ITEM, "rub-together") { player, _ -> + sendMessage(player, "You rub together the dry sticks and the sticks catch alight.") + if(removeItem(player, Items.UNLIT_TORCH_596)) { + sendMessage(player, "You place the smouldering twigs to your torch.") + sendMessage(player, "Your torch lights.") + addItemOrDrop(player, Items.LIT_TORCH_594) + } + return@on true + } + + + on(NPCs.SEA_SLUG_1006, IntType.NPC, "take") { player, _ -> + sendMessage(player, "You pick up the sea slug.") + sendMessage(player, "It sinks its teeth deep into your hand.") + sendMessage(player, "You drop the sea slug.") + sendChat(player, "Ouch!") + impact(player, 3, HitsplatType.NORMAL) + return@on true + } + + } + + +} \ No newline at end of file diff --git a/Server/src/main/core/game/dialogue/FacialExpression.java b/Server/src/main/core/game/dialogue/FacialExpression.java index e3011a5a3..2d6277815 100644 --- a/Server/src/main/core/game/dialogue/FacialExpression.java +++ b/Server/src/main/core/game/dialogue/FacialExpression.java @@ -90,6 +90,9 @@ public enum FacialExpression { //9855-9857 are like disgusted? does it just repeat after this? //Child Chathead? + CHILD_ANGRY(7168), + CHILD_SIDE_EYE(7169), + CHILD_THINKING_2(7170), CHILD_EVIL_LAUGH(7171), CHILD_FRIENDLY(7172), CHILD_NORMAL(7173), @@ -98,8 +101,8 @@ public enum FacialExpression { CHILD_THINKING(7176), CHILD_SAD(7177), CHILD_GUILTY(7178), - CHILD_SUSPICIOUS(7179); //TODO: More? - + CHILD_SUSPICIOUS(7179), + CHILD_SHOCKED(7180); //TODO: More? /** From c6b508b3ed34a52b4628f89e22082c01bbd8cd98 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 13:07:49 +0000 Subject: [PATCH 172/306] Lucien now gives a pendant after Temple of Ikov completion --- .../quest/templeofikov/LucienDialogue.kt | 18 ++++++++++++++++-- .../quest/templeofikov/LucienEndingDialogue.kt | 2 ++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt index c6b3c93d2..d751c08a7 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt @@ -27,8 +27,22 @@ class LucienDialogue (player: Player? = null) : DialoguePlugin(player) { class LucienDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { b.onQuestStages(TempleOfIkov.questName, 100) - .endWith { _, player -> - sendMessage(player, "You have completed the Temple of Ikov quest.") + .playerl("I thought I killed you?!") + .npcl("Ha! Ha! Ha!") + .npcl("You can not kill me human!") + .branch { player -> + return@branch if (inInventory(player, Items.PENDANT_OF_LUCIEN_86)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .end() + branch.onValue(0) + .playerl("I've lost the pendant you gave me.") + .npcl("Have another, it will remind you of my power!") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.PENDANT_OF_LUCIEN_86) + } + .item(Items.PENDANT_OF_LUCIEN_86, "Lucien has given you another pendant!") + .end() } b.onQuestStages(TempleOfIkov.questName, 1,2,3,4,5,6,7) .npcl("I told you not to meet me here again!") diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt index 48cf0b890..c2d974bc5 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt @@ -25,6 +25,8 @@ class LucienEndingDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { b.onQuestStages(TempleOfIkov.questName, 100) .endWith { _, player -> + // After quest is over: https://www.youtube.com/watch?v=81DXjfsFcMM + sendMessage(player, "You feel that fighting this individual will be of little practical use.") sendMessage(player, "You have completed the Temple of Ikov quest.") } b.onQuestStages(TempleOfIkov.questName, 1,2,3,4,5,6,7) From 27f2d457ea4d628f2a01c760531817d2c707dd80 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:08:20 +0000 Subject: [PATCH 173/306] Fixed issues in Jarvald's dialogue --- .../fremennik/rellekka/dialogue/JarvaldDialogue.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt index cdf685e13..289ae1bd0 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt @@ -172,11 +172,10 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { 1 -> sail(true) 2 -> player("No, actually I have some stuff to do here first.").also { stage = 43 } } - 140 -> player("Hey, I have to say, that's a fine looking","hat you are wearing there.").also { stage++ } - 141 -> npc("Aye, that it is ${fremname}!","Skulgrimen fashioned it for me from the carcass of","one of the monsters on Waterbirth Island after our last hunt!").also { stage++ } - 142 -> npc("I hope to kill enough creatures to fashion","some fine armour as well","when next we leave!").also { stage++ } - 143 -> options("Waterbirth Island?", "Can I come?", "Ok, 'bye.").also { stage++ } - 144 -> when (buttonID) { + 140 -> npc("Aye, that it is ${fremname}!","Skulgrimen fashioned it for me from the carcass of one","of the monsters on Waterbirth Island after our last hunt!").also { stage++ } + 141 -> npc("I hope to kill enough creatures to fashion some fine","armour as well when next we leave!").also { stage++ } + 142 -> options("Waterbirth Island?", "Can I come?", "Ok, 'bye.").also { stage++ } + 143 -> when (buttonID) { 1 -> npc("You have not ever travelled to Waterbirth Island, ${fremname}?","I am surprised, it is a place of outstanding natural beauty.").also { stage = 108 } 2 -> player("Can I come?").also { stage = 130 } 3 -> player("Wow, you Fremenniks sure know how to party.","Well, see ya around.").also { stage = END_DIALOGUE } From 4039c0123b903bda726e4b6938a707e570b6450f Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 13:12:58 +0000 Subject: [PATCH 174/306] Correctly limited quest log and achievement diary scrolling --- .../asgarnia/taverley/quest/WolfWhistle.java | 2 ++ .../kandarin/quest/templeofikov/TempleOfIkov.kt | 5 +++-- .../digsite/quest/thedigsite/TheDigSite.kt | 2 ++ .../varrock/quest/allfiredup/AllFiredUp.kt | 6 ++++-- .../CreatureOfFenkenstrain.kt | 2 ++ .../player/link/diary/AchievementDiary.java | 7 +++---- .../game/node/entity/player/link/quest/Quest.java | 15 ++++++++++++++- 7 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java index 04b8a788f..cb1c137e2 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java @@ -37,6 +37,7 @@ public class WolfWhistle extends Quest { if(stage == 0){ line(player, "I can begin this quest by talking to !!Pikkupstix??, who lives in", line++, false); line(player, "!!Taverly??.", line++, false); + limitScrolling(player, line, true); } else { if (stage >= 10) { line(player, "Having spoken to !!Pikkupstix??, it seems that all I have to do", line++, stage >= 20); @@ -146,6 +147,7 @@ public class WolfWhistle extends Quest { line(player, "275 gold charms", line++); line(player, "and 276 Summoning XP", line++); } + limitScrolling(player, line, false); } } diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt index 0edb793e8..632710b24 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt @@ -1,8 +1,8 @@ package content.region.kandarin.quest.templeofikov import core.api.* -import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items @@ -59,6 +59,7 @@ class TempleOfIkov : Quest("Temple of Ikov", 121, 120, 1,26, 0, 1, 80 /* 80 or 9 line(player, "Level 42 !!Thieving??", line++, hasLevelStat(player, Skills.THIEVING, 42)) line(player, "Level 40 !!Ranged??", line++, hasLevelStat(player, Skills.RANGE, 40)) line(player, "Ability to defeat a level 84 enemy with Ranged.", line++, false) + limitScrolling(player, line, true) } else { if (stage >= 2) { line(player, "Lucien has asked me to retrieve the !!Staff of Armadyl?? from", line++, true) @@ -165,8 +166,8 @@ class TempleOfIkov : Quest("Temple of Ikov", 121, 120, 1,26, 0, 1, 80 /* 80 or 9 line++ line(player,"QUEST COMPLETE!", line) } + limitScrolling(player, line, false) } - } override fun reset(player: Player) { diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt index 8e15ec769..be91947b9 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt @@ -93,6 +93,7 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { line(player, "Level 10 Agility", line++, hasLevelStat(player, Skills.AGILITY, 10)) line(player, "Level 10 Herblore", line++, hasLevelStat(player, Skills.HERBLORE, 10)) line(player, "Level 25 Thieving", line++, hasLevelStat(player, Skills.THIEVING, 25)) + limitScrolling(player, line, true) } else { line(player, "I should speak to an examiner about taking Earth Science", line++, true) line(player, "Exams.", line++, true) @@ -362,6 +363,7 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { line++ line(player,"QUEST COMPLETE!", line) } + limitScrolling(player, line, false) } } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt index b97a4fd07..f3e992ffc 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt @@ -1,13 +1,13 @@ package content.region.misthalin.varrock.quest.allfiredup +import content.minigame.allfiredup.AFUBeacon +import core.api.setVarbit import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items -import content.minigame.allfiredup.AFUBeacon -import core.api.* /** * Represents the "All Fired Up" quest. @@ -30,6 +30,7 @@ class AllFiredUp : Quest("All Fired Up", 157, 156, 1){ line(player, "To start this quest, I require:", line++) line(player, "!!43 Firemaking??", line++, player.skills.getLevel(Skills.FIREMAKING) >= 43) line(player, "!!Completion of Priest in Peril??", line++, player.questRepository.isComplete("Priest in Peril")) + limitScrolling(player, line, true) } else { line(player, "I have agreed to help King Roald test the beacon network", line++, true) line(player, "that he hopes will serve as an early warning system,", line++, true) @@ -133,6 +134,7 @@ class AllFiredUp : Quest("All Fired Up", 157, 156, 1){ line++ line(player,"QUEST COMPLETE!", line) } + limitScrolling(player, line, false) } } diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt index 4b35fb36b..0959d87e6 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt @@ -58,6 +58,7 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line(player, "I also need to have completed the following quests:", line++, false) line(player, "Priest in Peril", line++, isQuestComplete(player, "Priest in Peril")) line(player, "Restless Ghost", line++, isQuestComplete(player, "The Restless Ghost")) + limitScrolling(player, line, true) } else { line(player, "I read the signpost in Canifis, which tells of a butler", line++, true) line(player, "position that is available at the castle to the northeast.", line++, true) @@ -123,6 +124,7 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line++ line(player,"QUEST COMPLETE!", line) } + limitScrolling(player, line, false) } } diff --git a/Server/src/main/core/game/node/entity/player/link/diary/AchievementDiary.java b/Server/src/main/core/game/node/entity/player/link/diary/AchievementDiary.java index 81b80bd7b..ddcdddeaf 100644 --- a/Server/src/main/core/game/node/entity/player/link/diary/AchievementDiary.java +++ b/Server/src/main/core/game/node/entity/player/link/diary/AchievementDiary.java @@ -114,13 +114,12 @@ public class AchievementDiary { } child++; } - // sendString(player, builder.toString(), 11); - //Changes the size of the scroll bar - //player.getPacketDispatch().sendRunScript(1207, "i", new Object[] { 330 }); - //sendString(player, builder.toString(), 11); if (!player.getInterfaceManager().isOpened()) { player.getInterfaceManager().open(new Component(DIARY_COMPONENT)); } + // Changes the size of the scroll bar (see 1207.cs2 for more) + // (args1: 1 is to start from top of scroll) (args0: child-12 lines to display) + player.getPacketDispatch().sendRunScript(1207, "ii", 1, child - 10); } /** diff --git a/Server/src/main/core/game/node/entity/player/link/quest/Quest.java b/Server/src/main/core/game/node/entity/player/link/quest/Quest.java index 8b50bdac2..b4fab393c 100644 --- a/Server/src/main/core/game/node/entity/player/link/quest/Quest.java +++ b/Server/src/main/core/game/node/entity/player/link/quest/Quest.java @@ -1,6 +1,5 @@ package core.game.node.entity.player.link.quest; -import core.game.component.CloseEvent; import core.game.component.Component; import core.game.node.entity.player.Player; import core.plugin.Plugin; @@ -215,6 +214,20 @@ public abstract class Quest implements Plugin { player.getPacketDispatch().sendString(crossed ? "" + send + "" : send, JOURNAL_COMPONENT, line); } + /** + * Limits the quest log scroll to the number of lines minus 9. + * Assumes that you start at line = 11 or line = 12. + * Call this function at the end of the drawJournal function like: limitScroll(player, line); + * @param player The player. + * @param line The number of lines to scroll. Due to sendRunScript, it handles less than 12 lines pretty well. + * @param startFromTop Whether to open the log at the top, defaults to opening the log at the very bottom. + */ + public void limitScrolling(Player player, int line, boolean startFromTop) { + // sendRunScript reverses the objects you pass in + // (args1: 0 is to start from bottom of scroll) (args0: child-12 lines to display) + player.getPacketDispatch().sendRunScript(1207, "ii", startFromTop ? 1 : 0, line - 9); // -9 to give text some padding instead of line - 11 or 12 + } + /** * Draws text on the quest reward component. * @param player The player. From 93890769e153296d2c3bc9a181802683faf06f24 Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:14:04 +0000 Subject: [PATCH 175/306] Significantly improved slayer tasks implementation More authentic tasks Better dialogue and hints New tasks added in preparation for when relevant quests are implemented --- Server/data/configs/drop_tables.json | 15 +- .../main/content/data/EnchantedJewellery.kt | 3 +- .../handlers/item/EnchantedGemListener.kt | 4 +- .../content/global/skill/slayer/Master.java | 192 +++++++--------- .../skill/slayer/SlayerMasterDialogue.java | 7 +- .../global/skill/slayer/SlayerUtils.kt | 38 +++- .../content/global/skill/slayer/Tasks.java | 214 ++++++++++-------- .../content/global/skill/slayer/unused-tasks | 92 -------- .../system/command/sets/SlayerCommandSet.kt | 3 +- 9 files changed, 255 insertions(+), 313 deletions(-) delete mode 100644 Server/src/main/content/global/skill/slayer/unused-tasks diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index ec5ee681a..8a31d8263 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -39893,7 +39893,20 @@ ] }, { - "default": [], + "default": [ + { + "minAmount": "1", + "weight": "1.0", + "id": "532", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "9080", + "maxAmount": "1" + } + ], "charm": [ { "minAmount": "1", diff --git a/Server/src/main/content/data/EnchantedJewellery.kt b/Server/src/main/content/data/EnchantedJewellery.kt index d5b300e93..c34a0ffb6 100644 --- a/Server/src/main/content/data/EnchantedJewellery.kt +++ b/Server/src/main/content/data/EnchantedJewellery.kt @@ -2,6 +2,7 @@ package content.data import content.global.skill.magic.TeleportMethod import content.global.skill.slayer.SlayerManager.Companion.getInstance +import content.global.skill.slayer.SlayerUtils import core.ServerConstants import core.api.* import core.game.event.TeleportEvent @@ -304,7 +305,7 @@ enum class EnchantedJewellery( return } sendNPCDialogue(player, slayerManager.master!!.npc, "You're currently " + - "assigned to kill ${getSlayerTaskName(player).lowercase(Locale.getDefault())}'s; " + + "assigned to kill ${SlayerUtils.pluralise(getSlayerTaskName(player))} " + "only ${getSlayerTaskKillsRemaining(player)} more to go.", core.game.dialogue.FacialExpression.FRIENDLY) // Slayer tracker UI setVarp(player, 2502, slayerManager.flags.taskFlags shr 4) diff --git a/Server/src/main/content/global/handlers/item/EnchantedGemListener.kt b/Server/src/main/content/global/handlers/item/EnchantedGemListener.kt index 01d999e00..252dbe2ff 100644 --- a/Server/src/main/content/global/handlers/item/EnchantedGemListener.kt +++ b/Server/src/main/content/global/handlers/item/EnchantedGemListener.kt @@ -1,5 +1,6 @@ package content.global.handlers.item +import content.global.skill.slayer.SlayerUtils import core.api.* import content.global.skill.slayer.Tasks import org.rs09.consts.Items @@ -41,7 +42,8 @@ class EnchantedGemDialogue() : DialogueFile() { if(getSlayerTask(player!!) == Tasks.JAD) { npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill TzTok-Jad!") } else { - npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${getSlayerTaskName(player!!)}s; only ${getSlayerTaskKillsRemaining(player!!)} more to go.") + npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${SlayerUtils.pluralise( + getSlayerTaskName(player!!))}; only ${getSlayerTaskKillsRemaining(player!!)} more to go.") } setVarp(player!!, 2502, getSlayerTaskFlags(player!!) shr 4) stage = 1 diff --git a/Server/src/main/content/global/skill/slayer/Master.java b/Server/src/main/content/global/skill/slayer/Master.java index 0a3d3619d..ad728467c 100644 --- a/Server/src/main/content/global/skill/slayer/Master.java +++ b/Server/src/main/content/global/skill/slayer/Master.java @@ -10,36 +10,38 @@ import java.util.List; /** * A non-garbage way of representing slayer masters + * Source for task amounts: ... + * Need to add a source for weights * @author ceik + * @author gregf */ public enum Master { - TURAEL(8273, 0, 0, new int[]{15, 50}, new int[]{0, 0, 0}, + TURAEL(8273, 3, 0, new int[]{15, 50}, new int[]{0, 0, 0}, new Task(Tasks.BANSHEE, 8), new Task(Tasks.BATS, 7), - new Task(Tasks.BIRDS, 6), new Task(Tasks.BEARS, 7), - new Task(Tasks.CAVE_BUG, 8), + new Task(Tasks.BIRDS, 6), + new Task(Tasks.CAVE_BUG, 8), new Task(Tasks.CAVE_CRAWLERS, 8), new Task(Tasks.CAVE_SLIMES, 8), new Task(Tasks.COWS, 8), new Task(Tasks.CRAWLING_HAND, 8), + new Task(Tasks.DESERT_LIZARDS, 8), new Task(Tasks.DOG, 7), new Task(Tasks.DWARF, 7), new Task(Tasks.GHOSTS, 7), new Task(Tasks.GOBLINS, 7), new Task(Tasks.ICE_FIENDS, 8), new Task(Tasks.KALPHITES, 6), - new Task(Tasks.DESERT_LIZARDS, 8), new Task(Tasks.MINOTAURS, 7), new Task(Tasks.MONKEYS, 6), - new Task(Tasks.RATS, 7), - new Task(Tasks.SCORPIONS, 7), + new Task(Tasks.SCORPIONS, 7), new Task(Tasks.SKELETONS, 7), new Task(Tasks.SPIDERS, 6), new Task(Tasks.WOLVES, 7), new Task(Tasks.ZOMBIES, 7)), - MAZCHNA(8274, 20, 0, new int[]{30, 70}, new int[]{2, 5, 15}, + MAZCHNA(8274, 20, 0, new int[]{40, 70}, new int[]{2, 5, 15}, new Task(Tasks.BANSHEE, 8), new Task(Tasks.BATS,7), new Task(Tasks.BEARS,6), @@ -59,221 +61,191 @@ public enum Master { new Task(Tasks.HOBGOBLINS, 7), new Task(Tasks.ICE_WARRIOR, 7), new Task(Tasks.KALPHITES,6), - //new Task(Tasks.KILLERWATTS, 6), - //new Task(Tasks.MOGRES, 8), + new Task(Tasks.MOGRES, 8), new Task(Tasks.PYREFIENDS, 8), new Task(Tasks.ROCK_SLUGS,8), - new Task(Tasks.SCORPIONS,7), new Task(Tasks.SHADE,8), new Task(Tasks.SKELETONS, 7), new Task(Tasks.VAMPIRES, 6), - //new Task(Tasks.WALL_BEASTS,7), + // new Task(Tasks.WALL_BEASTS,7), new Task(Tasks.WOLVES, 7), new Task(Tasks.ZOMBIES,7)), - VANNAKA(1597, 40, 0, new int[]{30, 80}, new int[]{4, 20, 60}, + VANNAKA(1597, 40, 0, new int[]{60, 120}, new int[]{4, 20, 60}, new Task(Tasks.ABERRANT_SPECTRES, 8), - new Task(Tasks.ABYSSAL_DEMONS, 5), new Task(Tasks.ANKOU,7), new Task(Tasks.BANSHEE,6), - new Task(Tasks.BASILISKS,8), - new Task(Tasks.BLOODVELDS,8), + new Task(Tasks.BASILISKS,8), new Task(Tasks.BLUE_DRAGONS,7), + new Task(Tasks.BLOODVELDS,8), new Task(Tasks.BRINE_RATS,7), - new Task(Tasks.BRONZE_DRAGONS,7), new Task(Tasks.CAVE_BUG,7), new Task(Tasks.CAVE_CRAWLERS,7), new Task(Tasks.CAVE_SLIMES,7), new Task(Tasks.COCKATRICES,8), new Task(Tasks.CRAWLING_HAND,6), - new Task(Tasks.CROCODILES,6), - new Task(Tasks.DAGANNOTHS, 7), + new Task(Tasks.CROCODILES,6, new Integer[]{30, 60}), + new Task(Tasks.DAGANNOTHS, 7), + new Task(Tasks.DESERT_LIZARDS,7, new Integer[]{30, 60}), new Task(Tasks.DUST_DEVILS,8), - new Task(Tasks.EARTH_WARRIORS,6), - new Task(Tasks.ELVES, 7), + new Task(Tasks.EARTH_WARRIORS,6, new Integer[]{30, 60}), + new Task(Tasks.ELVES, 7, new Integer[]{30, 60}), //new Task(Tasks.FEVER_SPIDERS,7), new Task(Tasks.FIRE_GIANTS,7), - new Task(Tasks.GARGOYLES, 5), new Task(Tasks.GHOULS,7), - new Task(Tasks.GREEN_DRAGONS,6), + new Task(Tasks.GREEN_DRAGONS,6, new Integer[]{30, 60}), new Task(Tasks.HARPIE_BUG_SWARMS,8), new Task(Tasks.HELLHOUNDS,7), new Task(Tasks.HILL_GIANTS,7), - new Task(Tasks.HOBGOBLINS,7), - new Task(Tasks.ICE_GIANTS,7), + new Task(Tasks.ICE_GIANTS,7, new Integer[]{30, 60}), new Task(Tasks.ICE_WARRIOR,7), new Task(Tasks.INFERNAL_MAGES,8), new Task(Tasks.JELLIES,8), new Task(Tasks.JUNGLE_HORRORS, 8), new Task(Tasks.KALPHITES,7), - //new Task(Tasks.KILLERWATTS,6), + // new Task(Tasks.KILLERWATTS,6), new Task(Tasks.KURASKS,7), - new Task(Tasks.DESERT_LIZARDS,7), - new Task(Tasks.LESSER_DEMONS,7), + new Task(Tasks.LESSER_DEMONS,7), //new Task(Tasks.MOGRES,7), - //new Task(Tasks.MOLANISKS,7), + // new Task(Tasks.MOLANISKS,7), new Task(Tasks.MOSS_GIANTS,7), - new Task(Tasks.NECHRYAELS, 5), new Task(Tasks.OGRES,7), new Task(Tasks.OTHERWORDLY_BEING,8), new Task(Tasks.PYREFIENDS,8), new Task(Tasks.ROCK_SLUGS,7), + // new Task(Tasks.SEA_SNAKES,6), new Task(Tasks.SHADE,8), - //new Task(Tasks.SEA_SNAKES,6), - //new Task(Tasks.SHADOW_WARRIORS, 8), - new Task(Tasks.SPIRTUAL_MAGES,3), - new Task(Tasks.SPIRTUAL_RANGERS, 3), - new Task(Tasks.SPIRTUAL_WARRIORS,3), - //new Task(Tasks.TERROR_DOGS,6), + // new Task(Tasks.SHADOW_WARRIORS, 8), new Task(Tasks.TROLLS,7), new Task(Tasks.TUROTHS, 8), new Task(Tasks.VAMPIRES,7), - //new Task(Tasks.WALL_BEAST,6), - new Task(Tasks.WEREWOLFS,7)), + // new Task(Tasks.WALL_BEASTS,6), + new Task(Tasks.WEREWOLVES,7)), CHAELDAR(1598, 70, 0, new int[]{110, 170}, new int[]{10, 50, 150}, new Task(Tasks.ABERRANT_SPECTRES,8), new Task(Tasks.ABYSSAL_DEMONS,12), - new Task(Tasks.AVIANSIES,9), new Task(Tasks.BANSHEE, 5), new Task(Tasks.BASILISKS,7), - new Task(Tasks.BLACK_DEMONS,10), - new Task(Tasks.BLOODVELDS,8), new Task(Tasks.BLUE_DRAGONS,8), + new Task(Tasks.BLOODVELDS,8), new Task(Tasks.BRINE_RATS,7), - new Task(Tasks.BRONZE_DRAGONS,11), + new Task(Tasks.BRONZE_DRAGONS,11, new Integer[]{30, 60}), + new Task(Tasks.CAVE_BUG, 5), new Task(Tasks.CAVE_CRAWLERS, 5), new Task(Tasks.CAVE_HORRORS,10), new Task(Tasks.CAVE_SLIMES,6), new Task(Tasks.COCKATRICES,6), + new Task(Tasks.CRAWLING_HAND, 5), + new Task(Tasks.CROCODILES, 5, new Integer[]{30, 60}), new Task(Tasks.DAGANNOTHS,11), + new Task(Tasks.DESERT_LIZARDS, 5, new Integer[]{30, 60}), new Task(Tasks.DUST_DEVILS,9), - new Task(Tasks.ELVES,8), + new Task(Tasks.ELVES,8, new Integer[]{60, 90}), //new Task(Tasks.FEVER_SPIDERS,7), new Task(Tasks.FIRE_GIANTS, 12), new Task(Tasks.GARGOYLES,11), new Task(Tasks.GREATER_DEMONS,9), new Task(Tasks.HARPIE_BUG_SWARMS,6), - new Task(Tasks.HELLHOUNDS,9), + new Task(Tasks.HELLHOUNDS,9), + new Task(Tasks.IRON_DRAGONS,12, new Integer[]{30, 60}), new Task(Tasks.INFERNAL_MAGES,7), - new Task(Tasks.IRON_DRAGONS,12), new Task(Tasks.JELLIES, 10), new Task(Tasks.JUNGLE_HORRORS,10), new Task(Tasks.KALPHITES,11), new Task(Tasks.KURASKS, 12), new Task(Tasks.LESSER_DEMONS,9), - new Task(Tasks.DESERT_LIZARDS, 5), - //new Task(Tasks.MOGRES,6), - //new Task(Tasks.MOLANISKS,6), - //new Task(Tasks.MUTATED_ZYGOMITES,7), + new Task(Tasks.MOGRES,6), + // new Task(Tasks.MOLANISKS,6), + //new Task(Tasks.MUTATED_ZYGOMITES,7, new Integer[]{30, 60}), new Task(Tasks.NECHRYAELS, 12), new Task(Tasks.PYREFIENDS,6), new Task(Tasks.ROCK_SLUGS, 5), - //new Task(Tasks.SHADOW_WARRIORS,8), - new Task(Tasks.SKELETAL_WYVERN,7), + // new Task(Tasks.SHADOW_WARRIORS,8), new Task(Tasks.SPIRTUAL_WARRIORS,4), new Task(Tasks.SPIRTUAL_RANGERS,4), new Task(Tasks.SPIRTUAL_MAGES,4), - new Task(Tasks.STEEL_DRAGONS,9), new Task(Tasks.TROLLS,11), new Task(Tasks.TUROTHS, 10)), - //new Task(Tasks.WALL_BEASTS,6), + // new Task(Tasks.WALL_BEASTS,6, new Integer[]{10, 20}), + // new Task(Tasks.WARPED_TERROR_BIRD, 5), + // new Task(Tasks.WARPED_TORTOISE, 5) - SUMONA(7780, 90, 35, new int[]{50, 185}, new int[]{12, 60, 180}, + SUMONA(7780, 85, 35, new int[]{120, 185}, new int[]{12, 60, 180}, new Task(Tasks.ABERRANT_SPECTRES, 15), new Task(Tasks.ABYSSAL_DEMONS, 10), - new Task(Tasks.AVIANSIES, 7), + new Task(Tasks.AVIANSIES, 10), new Task(Tasks.BANSHEE, 15), new Task(Tasks.BASILISKS, 15), new Task(Tasks.BLACK_DEMONS, 10), - new Task(Tasks.BLOODVELDS, 10), new Task(Tasks.BLUE_DRAGONS, 5), + new Task(Tasks.BLOODVELDS, 10), new Task(Tasks.CAVE_CRAWLERS, 15), new Task(Tasks.CAVE_HORRORS, 15), - new Task(Tasks.CROCODILES, 4), new Task(Tasks.DAGANNOTHS, 10), - new Task(Tasks.DESERT_LIZARDS, 4), new Task(Tasks.DUST_DEVILS, 15), - new Task(Tasks.ELVES, 10), + new Task(Tasks.ELVES, 10, new Integer[]{60, 90}), new Task(Tasks.FIRE_GIANTS, 10), new Task(Tasks.GARGOYLES, 10), new Task(Tasks.GREATER_DEMONS, 10), new Task(Tasks.HELLHOUNDS, 10), - new Task(Tasks.IRON_DRAGONS, 7), + new Task(Tasks.IRON_DRAGONS, 7, new Integer[]{30, 60}), new Task(Tasks.KALPHITES, 10), new Task(Tasks.KURASKS, 15), new Task(Tasks.NECHRYAELS, 10), - // newTask(Tasks.RED_DRAGONS, 5), - new Task(Tasks.SCORPIONS, 4), + new Task(Tasks.RED_DRAGONS, 5), + // new Task(Tasks.SCABARITES, 9, new Integer[]{30, 60}), new Task(Tasks.SPIRTUAL_MAGES, 10), new Task(Tasks.SPIRTUAL_WARRIORS, 10), - // new Task(Tasks.TERROR_DOGS, 10), + // new Task(Tasks.TERROR_DOGS, 10, new Integer[]{30, 60}), new Task(Tasks.TROLLS, 10), - new Task(Tasks.TUROTHS, 15), - new Task(Tasks.VAMPIRES, 10)), - //new Task(Tasks.WARPED_TORTOISE, 15)), + new Task(Tasks.TUROTHS, 15)), + // new Task(Tasks.WARPED_TORTOISE, 15)), - DURADEL(8275, 100, 50, new int[]{50, 199}, new int[]{15, 75, 225}, + DURADEL(8275, 100, 50, new int[]{130, 200}, new int[]{15, 75, 225}, new Task(Tasks.ABERRANT_SPECTRES,7), new Task(Tasks.ABYSSAL_DEMONS,12), - new Task(Tasks.ANKOU,5), - new Task(Tasks.AVIANSIES,8), - new Task(Tasks.BLACK_DEMONS,8), - new Task(Tasks.BLACK_DRAGONS,9), + new Task(Tasks.AVIANSIES, 10), + new Task(Tasks.BLACK_DEMONS,8), + new Task(Tasks.BLACK_DRAGONS,9, new Integer[]{40, 80}), new Task(Tasks.BLOODVELDS,8), - new Task(Tasks.BLUE_DRAGONS,4), - new Task(Tasks.CAVE_HORRORS,4), - new Task(Tasks.DAGANNOTHS,9), + new Task(Tasks.DAGANNOTHS,9), new Task(Tasks.DARK_BEASTS,11), new Task(Tasks.DUST_DEVILS,5), - new Task(Tasks.ELVES,4), - new Task(Tasks.FIRE_GIANTS,7), + new Task(Tasks.FIRE_GIANTS,7), new Task(Tasks.GARGOYLES,8), + new Task(Tasks.GORAKS,9), new Task(Tasks.GREATER_DEMONS,9), new Task(Tasks.HELLHOUNDS, 10), - new Task(Tasks.IRON_DRAGONS,5), + new Task(Tasks.IRON_DRAGONS,5, new Integer[]{40, 80}), new Task(Tasks.KALPHITES,9), - new Task(Tasks.KURASKS,4), - new Task(Tasks.MITHRIL_DRAGONS,9), + new Task(Tasks.MITHRIL_DRAGONS,9, new Integer[]{4, 8}), new Task(Tasks.NECHRYAELS,9), - //new Task(Tasks.RED_DRAGONS,8), - new Task(Tasks.SKELETAL_WYVERN,7), + // new Task(Tasks.SCABARITES, 9, new Integer[]{40, 80}), + new Task(Tasks.SKELETAL_WYVERN,7, new Integer[]{40, 80}), new Task(Tasks.SPIRTUAL_MAGES,2), - new Task(Tasks.SPIRTUAL_RANGERS,2), - new Task(Tasks.SPIRTUAL_WARRIORS,2), - new Task(Tasks.STEEL_DRAGONS,7), - new Task(Tasks.SUQAHS,8), - new Task(Tasks.TROLLS,6), - new Task(Tasks.TZHAAR, 10), - new Task(Tasks.VAMPIRES,8), - // new Task(Tasks.WARPED_TERRORBIRD,8), + new Task(Tasks.STEEL_DRAGONS,7, new Integer[]{40, 80}), + new Task(Tasks.SUQAHS,8, new Integer[]{40, 80}), + // new Task(Tasks.WARPED_TERROR_BIRD,8), new Task(Tasks.WATERFIENDS,2)); - //new Task(Tasks.MUTATED_ZYGOMITES,2), - //Boss Tasks below this point - Crash - //new Task(Tasks.JAD, 1), - //new Task(Tasks.COMMANDER_ZILYANA,1), - //new Task(Tasks.CHAOS_ELEMENTAL, 1), - //new Task(Tasks.GENERAL_GRARDOOR,1), - //new Task(Tasks.GIANT_MOLE,1), - //new Task(Tasks.KING_BLACK_DRAGON,1), - //new Task(Tasks.KRIL_TSUTSAROTH,1), - //new Task(Tasks.KREE_ARRA,1)); - private static HashMap idMap = new HashMap<>(); + private static final HashMap idMap = new HashMap<>(); static{ Arrays.stream(Master.values()).forEach(m -> idMap.putIfAbsent(m.npc_id, m)); } - int npc_id,required_combat,required_slayer; - public int[] assignment_range; - int[] streakPoints; - public List tasks; - Master(int npc_id, int required_combat, int required_slayer, int[] assignment_range, int[] streakPoints, Task... tasks) { + final int npc_id; + final int required_combat; + final int required_slayer; + public final int[] default_assignment_range; + final int[] streakPoints; + public final List tasks; + Master(int npc_id, int required_combat, int required_slayer, int[] default_assignment_range, int[] streakPoints, Task... tasks) { this.npc_id = npc_id; this.required_combat = required_combat; this.required_slayer = required_slayer; - this.assignment_range = assignment_range; + this.default_assignment_range = default_assignment_range; this.streakPoints = streakPoints; this.tasks = new ArrayList<>(Arrays.asList(tasks)); } @@ -301,9 +273,17 @@ public enum Master { public static class Task{ public Tasks task; public Integer weight; - Task(Tasks task, Integer weight){ + public Integer[] task_range; + public Task(Tasks task, Integer weight){ this.task = task; this.weight = weight; + this.task_range = new Integer[]{null, null}; + } + + Task(Tasks task, Integer weight, Integer[] task_range){ + this.task = task; + this.weight = weight; + this.task_range = task_range; } } } diff --git a/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java b/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java index 25f059d22..128d6cc00 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java +++ b/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java @@ -15,6 +15,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; + import static core.tools.DialogueConstKt.END_DIALOGUE; /** @@ -349,7 +350,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin { if (player.getInventory().freeSlots() != 0) { player.getInventory().add(GEM); SlayerManager.getInstance(player).generate(master); - interpreter.sendDialogues(master.getNpc(), getExpression(master), "We'll start you off hunting " + SlayerManager.getInstance(player).getTaskName() + "'s, you'll need to", "kill " + SlayerManager.getInstance(player).getAmount() + " of them."); + interpreter.sendDialogues(master.getNpc(), getExpression(master), "We'll start you off hunting " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + ", you'll need to", "kill " + SlayerManager.getInstance(player).getAmount() + " of them."); stage = 510; } else if (player.getInventory().freeSlots() == 0) { player("Sorry, I don't have enough inventory space."); @@ -485,7 +486,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin { if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) { interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad."); } else { - interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerManager.getInstance(player).getTaskName() + "s."); + interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + "."); } stage = 844; break; @@ -499,7 +500,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin { if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) { interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad."); } else { - interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerManager.getInstance(player).getTaskName() + "'s."); + interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + "."); } stage = 844; } diff --git a/Server/src/main/content/global/skill/slayer/SlayerUtils.kt b/Server/src/main/content/global/skill/slayer/SlayerUtils.kt index 34fc944c1..c034fc557 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerUtils.kt +++ b/Server/src/main/content/global/skill/slayer/SlayerUtils.kt @@ -1,19 +1,16 @@ package content.global.skill.slayer +import core.api.setVarp import core.game.node.entity.combat.BattleState import core.game.node.entity.player.Player import core.game.node.entity.player.link.SpellBookManager.SpellBook import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills -import content.global.skill.slayer.Master -import content.global.skill.slayer.Tasks import core.tools.RandomFunction import org.rs09.consts.Items -import java.util.ArrayList -import core.api.* object SlayerUtils { - fun generate(player: Player, master: Master): Tasks? + fun generate(player: Player, master: Master): Master.Task? { val tasks: MutableList = ArrayList(10) val taskWeightSum = intArrayOf(0) @@ -24,7 +21,7 @@ object SlayerUtils { tasks.shuffle(RandomFunction.RANDOM) var rnd = RandomFunction.random(taskWeightSum[0]) for (task in tasks) { - if (rnd < task!!.weight) return task.task + if (rnd < task!!.weight) return task rnd -= task.weight } return null @@ -35,11 +32,14 @@ object SlayerUtils { 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: Master.Task, master: Master) { SlayerManager.getInstance(player).master = master - SlayerManager.getInstance(player).task = task - SlayerManager.getInstance(player).amount = RandomFunction.random(master.assignment_range[0], master.assignment_range[1]) + SlayerManager.getInstance(player).task = task.task + if (task.task_range[0] == null) + SlayerManager.getInstance(player).amount = RandomFunction.random(master.default_assignment_range[0], master.default_assignment_range[1]) + else + SlayerManager.getInstance(player).amount = RandomFunction.random(task.task_range[0], task.task_range[1]) if (master == Master.DURADEL) { player.achievementDiaryManager.finishTask(player, DiaryType.KARAMJA, 2, 8) } else if (master == Master.VANNAKA) { @@ -57,4 +57,24 @@ object SlayerUtils { .spellBook == SpellBook.MODERN.interfaceId ) } + + @JvmStatic + fun pluralise(str: String): String { + return when (str) { + "black bear" -> "bears" + "cyclops" -> "cyclopes" + "guard dog" -> "dogs" + "dwarf" -> "dwarves" + "elf warrior" -> "elves" + "jelly" -> "jellies" + "nechryael" -> str // the plural and singular is the same + "turoth" -> str // the plural and singular is the same + "tzhaar-mej" -> "tzHaar" + "werewolf" -> "werewolves" + "wolf" -> "wolves" + "kalphite worker" -> "kalphites" + "scarab swarm" -> "scabarites" + else -> str + "s" + } + } } diff --git a/Server/src/main/content/global/skill/slayer/Tasks.java b/Server/src/main/content/global/skill/slayer/Tasks.java index 76f8c4fce..f2c459776 100644 --- a/Server/src/main/content/global/skill/slayer/Tasks.java +++ b/Server/src/main/content/global/skill/slayer/Tasks.java @@ -11,101 +11,128 @@ import static core.api.ContentAPIKt.hasRequirement; /** * A non-garbage way of representing tasks + * Slayer level source: ... + * Combat level source: None * @author ceik + * @author gregf */ public enum Tasks { - ABERRANT_SPECTRES(65, new int[] { 1604, 1605, 1606, 1607, 7801, 7802, 7803, 7804 }, new String[] { "Aberrant spectres have an extremely potent stench that drains", "stats and life points. A nose peg, protects against the stench." }, 60, true, false), - ABYSSAL_DEMONS(85, new int[] { 1615, 4230 }, new String[] { "Abyssal Demons are nasty creatures to deal with, they aren't really part, ", "of this realm, and are able to move very quickly to trap their prey"}, 85, false, false), - ANKOU(40, new int[] { 4381, 4382, 4383 }, new String[] { "Neither skeleton nor ghost, but a combination of both." }, 1, true, false), - AVIANSIES(60, new int[] { 6245, 6243, 6235, 6232, 6244, 6246, 6233, 6241, 6238, 6237, 6240, 6242, 6239, 6234 }, new String[] { "Graceful, bird-like creature." }, 1, false, false), - BANSHEE(20, new int[] { 1612 }, new String[] { "Banshees use a piercing scream to shock their enemies", "you'll need some Earmuffs to protect yourself from them." }, 15, true, false), - BASILISKS(40, new int[] { 1616, 1617, 4228 }, new String[] { "A mirror shield is much necessary when hunting", "these mad creatures." }, 40, false, false), - BATS(5, new int[] { 412, 78, 1005, 2482, 3711, }, new String[] { "These little creatures are incredibly quick.", "make sure you keep your eye on them at all times." }, 1, false, false), - BEARS(13, new int[] { 106, 105, 1195, 3645, 3664, 1326, 1327 }, new String[] { "A large animal with a crunching punch." }, 1, false, false), - BIRDS(1, new int[] { 1475, 5120, 5121, 5122, 5123, 5133, 1475, 1476, 41, 951, 1017, 1401, 1402, 2313, 2314, 2315, 1016, 1550, 147, 1180, 1754, 1755, 1756, 2252, 4570, 4571, 1911, 6114, 46, 2693, 6113, 6112, 146, 149, 150, 450, 451, 1179, 1322, 1323, 1324, 1325, 1400, 2726, 2727, 3197, 138, 48, 4373, 4374, 4535, 139, 1751, 148, 1181, 6382, 2459, 2460, 2461, 2462, 2707, 2708, 6115, 6116, 3296, 6378, 1996, 3675, 3676, 6792, 6946, 7320, 7322, 7324, 7326, 7328, 1692, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 3476, 1018, 1403, }, new String[] { "Birds aren't the most intelligent of creatures, but watch out for their", "sharp, stabbing beaks." }, 1, false, false), - BLACK_DEMONS(80, new int[] { 84, 677, 4702, 4703, 4704, 4705, 6208, }, new String[] { "Black Demons are magic creatures that are weak to magic attacks.", "They're the strongest demon and very dangerous." }, 1, false, false), - BLACK_DRAGONS(80, new int[] {54, 4673, 4674, 4675, 4676, 3376, 50 }, new String[] { "Black dragons are the strongest dragons", "watch out for their fiery breath" }, 1, false, true, 40 | 80 << 16), - BLOODVELDS(50, new int[] { 1618, 1619, 6215, 7643, 7642 }, new String[] { "Bloodvelds are strange demonic creatures, they use their long rasping tongue", "to feed on just about anything they can find." }, 50, false, false), - BLUE_DRAGONS(65, new int[] { 55, 4681, 4682, 4683, 4684, 5178, 52, 4665, 4666, }, new String[] { "Blue dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their fiery breath." }, 1, false, true), - BRINE_RATS(45, new int[] { 3707 }, new String[] { "Small little creatures they are, yet so very", "powerful." }, 47, false, false), - BRONZE_DRAGONS(75, new int[] { 1590 }, new String[] { "Bronze dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their fiery breath." }, 1, false, true, 30 | 60 << 16), - CATABLEPONS(35, new int[] { 4397, 4398, 4399, }, new String[] { "They use the magic spell Weaken to drain up to 15% of their", "opponent's maximum Strength level." }, 1, false, false), - CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "It regenerates life points quickly and seems to be a good", "herblore monster." }, 7, false, false), - CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "The poisonous parts of them are presumably removed." }, 10, false, false), - CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "preferred to wear a witchwood icon." }, 58, "Cabin Fever"), - CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "These are lesser versions of jellies, watch out they can poison you." }, 17, false, false), - COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "A Mirror shield is necessary when", "fighting these monsters." }, 25, false, false), - COWS(5, new int[] { 1766, 1768, 2310, 81, 397, 955, 1767, 3309 }, new String[] { "Cow's may seem stupid, however they know more then", "you think. Don't under estimate them." }, 1, false, false), + ABERRANT_SPECTRES(65, new int[] { 1604, 1605, 1606, 1607, 7801, 7802, 7803, 7804 }, new String[] { "Aberrant Spectres are fetid, vile ghosts. The very", "smell of them will paralyse and harm you. A nose peg", "will help ignore their stink." }, 60, true, false), + ABYSSAL_DEMONS(85, new int[] { 1615 }, new String[] { "Abyssal Demons are nasty creatures to fight. They", "aren't really part of this realm, and are able to", "move very quickly to trap their prey."}, 85, false, false), + ANKOU(40, new int[] { 4381, 4382, 4383 }, new String[] { "Ankou are undead skeletal ghosts. They'll fight you", "up close but make sure to take advantage out of their", "limited defence." }, 1, true, false), + AVIANSIES(60, new int[] { 6245, 6243, 6235, 6232, 6244, 6246, 6233, 6241, 6238, 6237, 6240, 6242, 6239, 6234 }, new String[] { "Aviansies are bird-like creatures found in the icy", "dungeons of the north. Melee weapons can't reach them,", "so use Magic or Ranged attacks." }, 1, false, false), + BANSHEE(20, new int[] { 1612 }, new String[] { "Banshees use a piercing scream to shock their enemies.", "You'll need some earmuffs to protect yourself from them." }, 15, true, false), + BASILISKS(40, new int[] { 1616, 1617 }, new String[] { "Basilisks, like Cockatrice, have a gaze which will", "paralyse and harm their prey. You'll need a Mirror", "Shield to protect you." }, 40, false, false), + BATS(5, new int[] { 412, 78, 3711 }, new String[] { "Bats are rarely found on the ground, so you'll have", "to fight them while they're airborne, which won't be", "easy for melee." }, 1, false, false), + BEARS(13, new int[] { 106, 105, 1195, 3645, 3664, 1326, 1327 }, new String[] { "Bears are tough creatures and fierce fighters, watch", "out for their powerful claws." }, 1, false, false), + BIRDS(1, new int[] { 1475, 5120, 5121, 5122, 5123, 5133, 1475, 1476, 41, 951, 1017, 1401, 1402, 2313, 2314, 2315, 1016, 1550, 147, 1180, 1754, 1755, 1756, 2252, 4570, 4571, 1911, 6114, 46, 2693, 6113, 6112, 146, 149, 150, 450, 451, 1179, 1322, 1323, 1324, 1325, 1400, 2726, 2727, 3197, 138, 48, 4373, 4374, 4535, 139, 1751, 148, 1181, 6382, 2459, 2460, 2461, 2462, 2707, 2708, 6115, 6116, 3296, 6378, 1996, 3675, 3676, 6792, 6946, 7320, 7322, 7324, 7326, 7328, 1692, 6322, 3476, 1018, 1403, }, new String[] { "Birds aren't the most intelligent of creatures, but", "watch out for their sharp stabbing beaks." }, 1, false, false), + BLACK_DEMONS(80, new int[] { 84, 677, 4702, 4703, 4704, 4705, 6208, }, new String[] { "Black Demons are magic creatures that are weak", "to magic attacks. They're a very strong", "demon and very dangerous." }, 1, false, false), + BLACK_DRAGONS(80, new int[] {54, 4673, 4674, 4675, 4676, 3376, 50 }, new String[] { "Black dragons are the strongest dragons;", "watch out for their fiery breath." }, 1, false, true), + BLOODVELDS(50, new int[] { 1618, 1619, 6215, 7643, 7642 }, new String[] { "Bloodvelds are strange demonic creatures, they use their", "long rasping tongue to feed on just about", "anything they can find." }, 50, false, false), + BLUE_DRAGONS(65, new int[] { 55, 4681, 4682, 4683, 4684, 5178, 52, 4665, 4666, }, new String[] { "Blue dragons aren't as strong as other dragons but they're", "still very powerful, watch out for their fiery breath." }, 1, false, true), + BRINE_RATS(45, new int[] { 3707 }, new String[] { "Brine rats can be found in caves that are near the", "sea. They are hairless, bad-tempered and generally", "unfriendly." }, 47, "Olaf's Quest"), + BRONZE_DRAGONS(75, new int[] { 1590 }, new String[] { "Bronze Dragons are the weakest of the metallic", "dragons, their bronze scales are far thicker than", "normal bronze armour." }, 1, false, true), + CATABLEPONS(35, new int[] { 4397, 4398, 4399, }, new String[] { "Catablepon are mythical, cow like, magical creatures", "Beware their weakening glare." }, 1, false, false), + CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "Cave Bugs are like Cave Crawlers, except smaller and", "easier to squish, though they still have a fondness", "for plants." }, 7, false, false), + CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "Cave Crawlers are small and fast, often hiding in", "ambush. Avoid their barbed tongue or you'll", "get poisoned." }, 10, false, false), + CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "Cave Horrors can be found under Mos Le'Harmless. You", "will need a Witchwood Icon to fight them effectively." }, 58, "Cabin Fever"), + CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "Cave Slimes are the lesser cousins of Jellies, though", "don't be fooled they can still be dangerous as", "they're often poisonous." }, 17, false, false), + COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "Cockatrice, like Basilisks, have a gaze which will", "paralyse and harm their prey. You'll need a Mirror", "Shield to protect you." }, 25, false, false), + COWS(5, new int[] { 81, 1766, 1768, 2310, 397, 955, 1767, 3309 }, new String[] { "Cows are bigger than you, so they'll often hit fairly", "hard but are usually fairly slow to react." }, 1, false, false), CRAWLING_HAND(1,new int[] { 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 4226, 7640, 7641 }, new String[] { "Crawling Hands are undead severed hands, fast and", "dexterous they claw their victims." }, 5, true, false), - CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles can be found near water and marshes in and near the Kharidian Desert." }, 1, false, false), - CYCLOPES(25,new int[] { 116, 4291, 4292, 6078, 6079, 6080, 6081, 6269, 6270 }, new String[] { "Large one eyed creatures who normally wield a", "large mallet." }, 1, false, false), - DAGANNOTHS(75, new int[] { 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 2454, 2455, 2456, 2881, 2882, 2883, 2887, 2888, 3591, }, new String[] { "There are many types of Dagannoth, the most powerful being the three Dagannoth Kings." }, 1, false, false), - DARK_BEASTS(90, new int[] { 2783 }, new String[] { "A dark beast can attack using magic or melee." }, 90, false, false), - DESERT_LIZARDS(15, new int[] { 2803, 2804, 2805, 2806, 2807 }, new String[] { "Desert lizards are big Slayer monsters found in the Kharidian Desert." }, 22, false, false), - DOG(15, new int[] { 99, 3582, 6374, 1994, 1593, 1594, 3582 }, new String[] { "Dogs are much like Wolves, they are", "pack creatures which will hunt in groups." }, 1, false, false), + CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles are large reptiles which live near water.", "You'll want to have a stabbing weapon handy for", "puncturing their thick scaly hides." }, 1, false, false), + DAGANNOTHS(75, new int[] { 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 2454, 2455, 2456, 2881, 2882, 2883, 2887, 2888, 3591, }, new String[] { "Dagannoth are large sea dwelling creatures which are", "very aggressive. You'll often find them in caves", "near sea water." }, 1, "Horror from the Deep"), + DARK_BEASTS(90, new int[] { 2783 }, new String[] { "Dark Beasts are large, dog-like predators.", "Their massively muscled bodies protect", "them from crushing weapons." }, 90, "Mourning's Ends Part II"), + DESERT_LIZARDS(15, new int[] { 2803, 2804, 2805, 2806, 2807, 2808 }, new String[] { "Lizards are large reptiles with tough skin. Those", "found in the desert will need you to douse them with", "freezing water to finish them off after a tough battle." }, 22, false, false), + DOG(15, new int[] { 99, 3582, 1994, 1593, 1594, 3582 }, new String[] { "Dogs are much like Wolves, they are", "pack creatures which will hunt in groups." }, 1, false, false), DUST_DEVILS(70, new int[] { 1624 }, new String[] { "Dust Devils use clouds of dust, sand, ash and whatever", "else they can inhale to blind and disorientate", "their victims." }, 65, false, false), - DWARF(6, new int[] { 118, 120, 121, 382, 3219, 3220, 3221, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3294, 3295, 4316, 5880, 5881, 5882, 5883, 5884, 5885, 2130, 2131, 2132, 2133, 3276, 3277, 3278, 3279, 119, 2423 }, new String[] { "They are slightly resistant to Magic attacks", "and are not recommended for low levels." }, 1, false, false), - EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "An Earth warrior is a monster made of earth"," which fights using melee." }, 1, false, false), - ELVES(70, new int[] { 1183, 1184, 2359, 2360, 2361, 2362, 7438, 7439, 7440, 7441 }, new String[]{"Elves are agile creatures."}, 1, false, false), - FIRE_GIANTS(65, new int[] { 110, 1582, 1583, 1584, 1585, 1586, 7003, 7004 }, new String[] { "Like other giants, Fire Giants often wield large weapons", "learn to recognise what kind of weapon it is, and act accordingly." }, 1, false, false), - FLESH_CRAWLERS(15, new int[] { 4389, 4390, 4391 }, new String[] { "Flesh crawlers are medium level monsters found on", "level 2 of the Stronghold of Security." }, 1, false, false), - GARGOYLES(80, new int[] { 1610, 1611, 6389 }, new String[] { "Gargoyles are winged creatures of stone. You'll need to fight them to", "near death before breaking them apart with a rock hammer." }, 75, false, false), - GHOSTS(13, new int[] { 103, 104, 491, 1541, 1549, 2716, 2931, 4387, 388, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 1698, 5349, 5350, 5351, 5352, 5369, 5370, 5371, 5372, 5373, 5374, 5572, 6094, 6095, 6096, 6097, 6098, 6504, 13645, 13466, 13467, 13468, 13469, 13470, 13471, 13472, 13473, 13474, 13475, 13476, 13477, 13478, 13479, 13480, 13481 }, new String[] { "A Ghost is an undead monster that is found", "in various places and dungeons. " }, 1, false, false), - GHOULS(25, new int[] { 1218, 3059 }, new String[] { "Ghouls are a humanoid race and the descendants of a long-dead society", "that degraded to the point that its people ate their dead." }, 1, false, false), + DWARF(6, new int[] { 118, 120, 121, 382, 3219, 3220, 3221, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3294, 3295, 4316, 5880, 5881, 5882, 5883, 5884, 5885, 2130, 2131, 2132, 2133, 3276, 3277, 3278, 3279, 119, 2423 }, new String[] { "Dwarves are a small but tough race of miners, often", "using pickaxes to pierce their opponents armour." }, 1, false, false), + EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "Earth Warriors are a kind of earth elemental,", "grind them to dust with blunt weapons." }, 1, false, false), + ELVES(70, new int[] { 1183, 1184, 2359, 2360, 2361, 2362, 2373, 7438, 7439, 7440, 7441 }, new String[]{ "Elves are quick, agile, and vicious fighters which", "often favour bows and polearms."}, 1, "Regicide"), + // Waiting for either Rum Deal or Pirate Pete and Fever Spiders before adding this assignment + FEVER_SPIDER(1, new int[] { 2850 }, new String[] { "Fever Spiders are giant spiders that carry the deadly", "Spider Fever. If you don't want to catch it I suggest", "you wear Slayer Gloves to fight them." }, 42, "Rum Deal"), + FIRE_GIANTS(65, new int[] { 110, 1582, 1583, 1584, 1585, 1586, 7003, 7004 }, new String[] { "Like other giants, Fire Giants often wield large weapons", "learn to recognise what kind of weapon it is,", "and act accordingly." }, 1, false, false), + FLESH_CRAWLERS(15, new int[] { 4389, 4390, 4391 }, new String[] { "Flesh Crawlers are scavengers and will eat you - and", "anyone else, given the chance." }, 1, false, false), + GARGOYLES(80, new int[] { 1610, 6389 }, new String[] { "Gargoyles are winged creatures of stone. You'll need", "to fight them to near death before breaking them apart", "with a rock hammer." }, 75, false, false), + GHOSTS(13, new int[] { 103, 104, 491, 1541, 1549, 2716, 2931, 4387, 388, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 1698, 5349, 5350, 5351, 5352, 5369, 5370, 5371, 5372, 5373, 5374, 5572, 6094, 6095, 6096, 6097, 6098, 6504, 13645, 13466, 13467, 13468, 13469, 13470, 13471, 13472, 13473, 13474, 13475, 13476, 13477, 13478, 13479, 13480, 13481 }, new String[] { "Ghosts are undead so magic is your best bet against", "them, there is even a spell specially for fighting", "the undead." }, 1, true, false), + GHOULS(25, new int[] { 1218, 3059 }, new String[] { "Ghouls aren't undead but they are stronger and", "tougher than they look. However they're also very", "cowardly and will run if they're losing a fight." }, 1, false, false), GOBLINS(1, new int[] { 100, 101, 102, 444, 445, 489, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2678, 2679, 2680, 2681, 3060, 3264, 3265, 3266, 3267, 3413, 3414, 3415, 3726, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4407, 4408, 4409, 4410, 4411, 4412, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4499, 4633, 4634, 4635, 4636, 4637, 5786, 5824, 5855, 5856, 6125, 6126, 6132, 6133, 6279, 6280, 6281, 6282, 6283, 6402, 6403, 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497 }, new String[] { "Goblins are mostly just annoying, but they can be vicious.", "Watch out for the spears they sometimes carry." }, 1, false, false), - GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks can be tough monsters to fight. Be prepared." }, 1, false, false), - GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6204 }, new String[] { "Greater Demons are magic creatures so they are weak to magical attacks.", "They're the strongest demon and very dangerous." }, 1, false, false), - GREEN_DRAGONS(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362, 742 }, new String[] { "Green dragons are very powerful, they have fierce", "fiery breath." }, 1, false, true), - HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are insectoid Slayer monsters." }, 33, false, false), - HELLHOUNDS(75, new int[] { 49, 3586, 6210, }, new String[] { "Hellhounds are mid to high level demons." }, 1, false, false), - HILL_GIANTS(25, new int[] { 117, 4689, 4690, 3058, 4691, 4692, 4693 }, new String[] { "Hill giants can hit up to 19 damage, and they only attack with Melee." }, 1, false, false), - HOBGOBLINS(20, new int[] { 122, 123, 2685, 2686, 3061, 6608, 6642, 6661, 6684, 6710, 6722, 6727, 2687, 2688, 3583, 4898, 6275 }, new String[] { "Mysterious goblin like creatures." }, 1, false, false), - ICE_FIENDS(20, new int[] { 3406, 6217, 7714, 7715, 7716 }, new String[] { "An Icefiend is a monster found on top of Ice Mountain." }, 1, false, false), - ICE_GIANTS(50, new int[] { 111, 3072, 4685, 4686, 4687 }, new String[] { "Ice Giants often wield large weapons, learn to recognise", "what kind of weapon it is, and act accordingly" }, 1, false, false), - ICE_WARRIOR(45, new int[] { 125, 145, 3073 }, new String[] { "Ice warriors, are cold majestic creatures." }, 1, false, false), - INFERNAL_MAGES(40, new int[] { 1643, 1644, 1645, 1646, 1647 }, new String[] { "Infernal Mages are dangerous spell users, beware of their magic", "spells an go properly prepared" }, 45, false, false), - IRON_DRAGONS(80, new int[] { 1591 }, new String[] { "Iron dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their fiery breath." }, 1, false, true, 40 | 59 << 16), + GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks are extremely aggressive creatures. They have", "been imprisoned on an alternative plane, which is", "only accessible by using the fairyrings. Be extremely", "careful, their touch drains health as well as skills!" }, 1, "A Fairy Tale I - Growing Pains"), + GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6204 }, new String[] { "Greater Demons are magic creatures so they are weak", "to magical attacks. Though not the strongest demon,", "they are still dangerous." }, 1, false, false), + GREEN_DRAGONS(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362, 742 }, new String[] { "Green Dragons are the weakest dragon but still very", "powerful, watch out for their fiery breath." }, 1, false, true), + HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are pesky critters that are hard to", "hit. You need a lit bug lantern to distract them with", "its hypnotic light." }, 33, false, false), + HELLHOUNDS(75, new int[] { 49, 3586, 6210, }, new String[] { "Hellhounds are a cross between Dogs and Demons, they", "are dangerous with a fierce bite." }, 1, false, false), + HILL_GIANTS(25, new int[] { 117, 4689, 4690, 3058, 4691, 4692, 4693 }, new String[] { "Hill Giants often wield large weapons, learn to", "recognise what kind of weapon it is and", "act accordingly." }, 1, false, false), + HOBGOBLINS(20, new int[] { 122, 123, 2685, 2686, 3061, 6608, 6642, 6661, 6684, 6710, 6722, 6727, 2687, 2688, 3583, 4898, 6275 }, new String[] { "Hobgoblins are sneaky underhanded creatures, they", "often wield spears and some times carry javelins too." }, 1, false, false), + ICE_FIENDS(20, new int[] { 3406, 6217, 7714, 7715, 7716 }, new String[] { "Icefiends are beings of ice and freezing rock, they're", "quick and agile so you'll want to be careful when", "getting close to them." }, 1, false, false), + ICE_GIANTS(50, new int[] { 111, 3072, 4685, 4686, 4687 }, new String[] { "Like other giants, Ice Giants often wield large", "weapons, learn to recognise what kind of weapon it is", "and act accordingly." }, 1, false, false), + ICE_WARRIOR(45, new int[] { 125, 145, 3073 }, new String[] { "Ice Warriors are a kind of ice elemental, shatter them", "with blunt weapons or melt them with fire." }, 1, false, false), + INFERNAL_MAGES(40, new int[] { 1643, 1644, 1645, 1646, 1647 }, new String[] { "Infernal Mages are dangerous spell users, beware of", "their magic spells and go properly prepared" }, 45, false, false), + IRON_DRAGONS(80, new int[] { 1591 }, new String[] { "Iron Dragons are some of the weaker metallic dragons,", "their iron scales are far thicker than normal", "iron armour." }, 1, false, true), JELLIES(57, new int[] { 1637, 1638, 1639, 1640, 1641, 1642 }, new String[] { "Jellies are nasty cube-like gelatinous creatures which", "absorb everything they come across into themselves." }, 52, false, false), - JUNGLE_HORRORS(65, new int[] { 4348, 4349, 4350, 4351, 4352 }, new String[] { "Jungle Horrors can be found all over Mos Le'Harmless.", "They are strong and aggressive, so watch out!" }, 1, false, false), - KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1159, 1160, 1161 }, new String[] { "Kalaphite are large insects which live in great hives under the desert sands." }, 1, false, false), - KURASKS(65, new int[] { 1608, 1609, 4229, 7805, 7797 }, new String[] { "A kurask is a very quick creature." }, 70, false, false), - LESSER_DEMONS(60, new int[] { 82, 6203, 3064, 4694, 4695, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to magical attacks." }, 1, false, false), - MITHRIL_DRAGONS(60, new int[] { 5363 }, new String[] { "Mithril dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their fiery breath." }, 1, false, true, 5 | 9 << 16), + JUNGLE_HORRORS(65, new int[] { 4348, 4349, 4350, 4351, 4352 }, new String[] { "Jungle Horrors can be found all over Mos Le'Harmless.", "They are strong and aggressive, so watch out!" }, 1, "Cabin Fever"), + KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1159, 1160, 1161 }, new String[] { "Kalphites are large insects which live in great hives", "under the desert sands." }, 1, false, false), + // Waiting for the killer watt plane to be implemented before adding to assignments + KILLERWATTS(1, new int[] { 3201 }, new String[] { "Killerwatts store huge amounts of energy in their", "bodies, which is released if they are touched. You'll", "need to wear heavily insulated boots to counter this", "shocking effect." }, 37, "Ernest the Chicken"), + KURASKS(65, new int[] { 1608, 1609, 4229, 7805, 7797 }, new String[] { "Kurasks are large brutal creatures with very thick", "hides. You'll need a Leaf-Tipped Spear Sword or", "Battle-axe, Broad Arrows, or a Magic Dart to harm them." }, 70, false, false), + LESSER_DEMONS(60, new int[] { 82, 6203, 3064, 4694, 4695, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to", "magical attacks. Though they're relatively weak they", "are still dangerous." }, 1, false, false), MINOTAURS(7, new int[] { 4404, 4405, 4406 }, new String[] { "Minotaurs are large manlike creatures but you'll", "want to be careful of their horns." }, 1, false, false), - MONKEYS(1, new int[] { 132, 1463, 1464, 2301, 4344, 4363, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 1455, 1459, 1460, 1456, 1457, 1458 }, new String[] { "Small agile creatures, watch out they pinch!" }, 1, false, false), - MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "They are known to carry large sticks." }, 1, false, false), - NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small winged beings which", "help them fight their victims." }, 80, false, false), - OGRES(40, new int[] { 115, 374, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057,2801, 3419, 7078, 7079, 7080, 7081, 7082 }, new String[] { "Ogres are brutal creatures, favouring large blunt maces and clubs", "they often attack without warning." }, 1, false, false), - OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "A creature filled with everlasting power." }, 1, false, false), - PYREFIENDS(25, new int[] { 1633, 1634, 1635, 1636, 6216, 6631, 6641, 6660, 6668, 6683, 6709, 6721, }, new String[] { "A scorching hot creature, watch out!" }, 30, false, false), - RATS(1, new int[] { 2682, 2980, 2981, 3007, 88, 224, 4928, 4929, 4936, 4937, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 4396, 4415, 7202, 7204, 7417, 7461, 87, 446, 950, 4395, 4922, 4923, 4924, 4925, 4926, 4927, 4942, 4943, 4944, 4945, 86, 87, 446, 950, 4395, 4922, 4923, 4924, 4925, 4926, 4927, 4942, 4943, 4944, 4945 }, new String[] { "Quick little rodents!" }, 1, false, false), - ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "A rock slug can leave behind a trail of his presence.." }, 20, false, false), - SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "A scorpion makes a piercing sound, watch out for", "its long sharp tail." }, 1, false, false), - SHADE(30, new int[] { 3617, 1250, 1241, 1246, 1248, 1250, 428, 1240 }, new String[] { "Shades are dark and mysterious", "they hide in the shadows so be wary of ambushes." }, 1, true, false), - SKELETONS(15, new int[] { 90, 91, 92, 93, 94, 459, 1471, 1575, 1973, 2036, 2037, 2715, 2717, 3065, 3151, 3291, 3581, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3844, 3850, 3851, 4384, 4385, 4386, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5359, 5365, 5366, 5367, 5368, 5381, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5411, 5412, 5422, 6091, 6092, 6093, 6103, 6104, 6105, 6106, 6107, 6764, 6765, 6766, 6767, 6768, 2050, 2056, 2057, 1539, 7640 }, new String[] { "Skeletons are undead monsters found in various locations." }, 1, true, false), - SPIDERS(1, new int[] { 61, 1004, 1221, 1473, 1474, 63, 4401, 2034, 977, 7207, 134, 1009, 59, 60, 4400, 58, 62, 1478, 2491, 2492, 6376, 6377, }, new String[] { "Level 24 spiders are aggressive and can hit up to 60 life points." }, 1, false, false), - SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "They are dangerous, they hit with mage." }, 83, false, false), - SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "They are dangerous, they hit with range." }, 63, false, false), - SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "They are dangerous, they hit with melee." }, 68, false, false), - STEEL_DRAGONS( 85,new int[] { 1592, 3590 }, new String[] { "Steel dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their fiery breath." }, 1, false, true, 10 | 20 << 16), - 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, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 391, 392, 393, 394, 395, 396}, new String[] { "Trolls have a crushing attack, it's bets to wear a high crushing defence." }, 1, false, false), - TUROTHS(60, new int[] { 1611, 1622, 1623, 1626, 1627, 1628, 1629, 1630, 7800}, new String[] { "Turoths are Slayer monsters that require a Slayer level of 55 to kill" }, 55, false, false), - TZHAAR(45, new int[] { 2591, 2592, 2593, 2745, 2594, 2595, 2596, 2597, 2604, 2605, 2606, 2607, 2608, 2609, 7755, 7753, 2598, 2599, 2600, 2601, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2617, 2618, 2625, 2602, 2603, 7754, 7767, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2625, 2627, 2628, 2629, 2630, 2631, 2632, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762, 7763, 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7747, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7757, 7765, 7769, 7768 }, new String[] { "Young Tzhaar's of the century are furious with your kind." }, 1, false, false), - SUQAHS (65, new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] { "Suquah are big, angry folk that inhabit Lunar Isle." }, 1, "Lunar Diplomacy"), - VAMPIRES(35, new int[] { 1023, 1220, 1223, 1225, 6214 }, new String[] { "Vampires are equipped with large fangs,", "they can do serious damage." }, 1, false, false), - WATERFIENDS(75, new int[] { 5361 }, new String[] { "A waterfiend takes no damage from fire!" }, 1, false, false), - WEREWOLFS(60, new int[] { 1665, 6006, 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, 6025, 6212, 6213, 6607, 6609, 6614, 6617, 6625, 6632, 6644, 6663, 6675, 6686, 6701, 6712, 6724, 6728, }, new String[] { "There temper is alot more nasty then a regular wolf!" }, 1, false, false), - WOLVES(20, new int[] { 95, 96, 97, 141, 142, 143, 839, 1198, 1330, 1558, 1559, 1951, 1952, 1953, 1954, 1955, 1956, 4413, 4414, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6829, 6830, 7005 }, new String[] { "Wolves are more agressive then dog's." }, 1, false, false), - ZOMBIES(10, new int[] { 73, 74, 75, 76, 2714, 2863, 2866, 2869, 2878, 3622, 4392, 4393, 4394, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5375, 5376, 5377, 5378, 5379, 5380, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 6099, 6100, 6131, 8149, 8150, 8151, 8152, 8153, 8159, 8160, 8161, 8162, 8163, 8164, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 7641, 1465, 1466, 1467, 2837, 2838, 2839, 2840, 2841, 2842, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, 5641, 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, 2843, 2844, 2845, 2846, 2847, 2848}, new String[] { "Zombies are creatures with no brain, they do hit farley", "high though." }, 1, true, false), - JAD(90, new int[] { }, new String[] { "TzTok-Jad is the king of the Fight Caves." }, 1, false, false, 1 | 1 << 16), - CHAOS_ELEMENTAL(90, new int[] { 3200 }, new String[] { "The Chaos Elemental is located in the deep Wilderness." }, 1, false, false, 5 | 25 << 16), - GIANT_MOLE(75, new int[] { 3340 }, new String[] { "Fighting the Giant Mole will require a light source." }, 1, false, false, 5 | 25 << 16), - KING_BLACK_DRAGON(75, new int[] { 50 }, new String[] { "The King Black Dragon is located in the deep wilderness." }, 1, false, true, 5 | 25 << 16), - COMMANDER_ZILYANA(90, new int[] { 6247 }, new String[] { "Commander Zilyana is one of the four Godwars bosses." }, 1, false, false, 5 | 25 << 16), - GENERAL_GRARDOOR(90, new int[] { 6260 }, new String[] { "General Grardoor is one of the four Godwars bosses." }, 1, false, false, 5 | 25 << 16), - KRIL_TSUTSAROTH(90, new int[] { 6203 }, new String[] { "Kril Tsutsaroth is one of the four Godwars bosses." }, 1, false, false, 5 | 25 << 16), - KREE_ARRA(90, new int[] { 6222 }, new String[] { "Kree'arra is one of the four Godwars bosses." }, 1, false, false, 5 | 25 << 16), - SKELETAL_WYVERN(70, new int[] { 3068, 3069, 3070, 3071 }, new String[] { "A skeletal wyvern requires an elemental, mirror", "or dragonfire shield." }, 72, false, false, 24 | 39 << 16); + MITHRIL_DRAGONS(60, new int[] { 5363 }, new String[] { "Mithril dragons are more vulnerable to magic and to", "stab-based melee attacks than to anything else." }, 1, false, true), + MOGRES(1, new int[] { 114 }, new String[] { "Mogres are a type of aquatic Ogre that is", "often mistaken for a giant mudskipper. You have to force", "them out of the water with a fishing explosive." }, 32, false, false), + // Waiting for molanisks transform to be implemented before adding this to assignments + MOLANISKS(1, new int[] { 5751 }, new String[] { "Molanisks are subterranean creatures. You can find", "them in caves deep below the ground. I heard that the", "goblins have recently had trouble with some, but they", "use a bell of some sort to deal with them."}, 39, "Death to the Dorgeshuun"), + MONKEYS(1, new int[] { 132, 1463, 1464, 2301, 4344, 4363, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 1455, 1459, 1460, 1456, 1457, 1458 }, new String[] { "Monkeys are tricky creatures, they are agile and", "fairly fast. Learn to anticipate their movements." }, 1, false, false), + MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "Like other giants, Moss Giants often wield large", "weapons, learn to recognise what kind of weapon it is", "and act accordingly." }, 1, false, false), + // Waiting for zygomite transform to be implemented before adding this to assignments + MUTATED_ZYGOMITES(1, new int[] { 3346, 3347 }, new String[] { "Mutated Zygomites are hard to destroy. They regenerate", "quickly so you will need to finish them with fungicide." }, 57, "Lost City"), + NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small", "winged beings to help them fight their victims." }, 80, false, false), + OGRES(40, new int[] { 115, 374, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2060, 2801, 3419, 7078, 7079, 7080, 7081, 7082 }, new String[] { "Ogres are brutal creatures, favouring large blunt", "maces and clubs they often attack without warning." }, 1, false, false), + OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "Otherworldly Beings are ethereal beings making them", "weak to magical attack." }, 1, false, false), + PYREFIENDS(25, new int[] { 1633, 1634, 1635, 1636, 6216, 6631, 6641, 6660, 6668, 6683, 6709, 6721, }, new String[] { "Pyrefiends are beings of fire and molten rock,", "they're quick and agile so you'll want to be careful", "when getting close to them." }, 30, false, false), + RED_DRAGONS(1, new int[] { 53, 1589, 3588, 4667, 4668, 4669, 4670, 4671, 4672 }, new String[] { "Red Dragons are very powerful, stronger than most", "dragons, watch out for their fiery breath." }, 1, false, false), + ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "Rockslugs are strange stoney slugs. You'll need to", "fight them to near death before finishing them off", "with Salt." }, 20, false, false), + // Seems to need Contact or the NPCs added to dungeons before adding this assignment as a task + SCABARITES(1, new int[] { 2001, 4500, 5251, 5252, 5255, 5256, 5250, 5254, 6777, 6778, 6774, 6780, 6781, 6773 }, new String[] {"Scabarites are insectoid creatures, found beyond the", "Kharidian deserts. They can be extremely dangerous."}, 1, "Contact!"), + SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "Scorpions are almost always poisonous, their hard", "carapace makes them resistant to crushing and", "stabbing attacks." }, 1, false, false), + SEA_SNAKES(1, new int[] { 3939, 3940 }, new String[] { "Sea Snakes are long and slithery with a venomous bite.", "The larger ones are more poisonous, so keep an eye on", "your health." }, 1, "Royal Trouble"), + SHADE(30, new int[] { 3617, 1250, 1241, 1246, 1248, 1250, 428, 1240 }, new String[] { "Shades are undead so magic is your best best against", "them, you can find Shades at Mort'ton." }, 1, true, false), + // Dungeon needs to be connected to the Legend's Guild before adding this assignment as a task + SHADOW_WARRIORS(1, new int[] { 158 }, new String[] { "Shadow Warriors are dark and mysterious, they hide in", "the shadows so be wary of ambushes." }, 1, "Legends' Quest"), + SKELETAL_WYVERN(70, new int[] { 3068, 3069, 3070, 3071 }, new String[] { "Skeletal Wyverns are extremely dangerous and they are", "hard to hit with arrows as they slip right through.", "To stand a good chance of surviving you'll need some", "elemental shielding from its icy breath." }, 72, false, false), + SKELETONS(15, new int[] { 90, 91, 92, 93, 94, 459, 1471, 1575, 1973, 2036, 2037, 2715, 2717, 3065, 3151, 3291, 3581, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3844, 3850, 3851, 4384, 4385, 4386, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5359, 5365, 5366, 5367, 5368, 5381, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5411, 5412, 5422, 6091, 6092, 6093, 6103, 6104, 6105, 6106, 6107, 6764, 6765, 6766, 6767, 6768, 2050, 2056, 2057, 1539, 7640 }, new String[] { "Skeletons are undead so magic is your best bet against", "them, there is even a spell specially for fighting the undead." }, 1, true, false), + SPIDERS(1, new int[] { 61, 1004, 1221, 1473, 1474, 63, 4401, 2034, 977, 7207, 134, 1009, 59, 60, 4400, 58, 62, 1478, 2491, 2492, 6376, 6377, }, new String[] { "Spiders are often poisonous, and many varieties are", "camouflaged too." }, 1, false, false), + SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "Spiritual mages can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 83, "Death Plateau"), + SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "Spiritual rangers can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 63, "Death Plateau"), + SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "Spiritual warriors can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 68, "Death Plateau"), + STEEL_DRAGONS( 85,new int[] { 1592, 3590 }, new String[] { "Steel dragons are dangerous and metallic, with steel", "scales that are far thicker than normal steel armour. As", "you are an accomplished slayer, I am sure you'll be", "able to deal with them easily."}, 1, false, true), + SUQAHS (65, new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] { "Suqahs can only be found on the mystical Lunar Isle.", "They are capable of melee and magic attacks and often", "drop hide, teeth and herbs!" }, 1, "Lunar Diplomacy"), + // No access to Lair of Tarn Razorlor but this should be added as a task when there is access + TERROR_DOGS(1, new int[] { 5417, 5418 }, new String[] { "Terror dogs are the personal pets of Tarn Razorlor.", "Wherever you find him, you will find them. They are", "bad-tempered and generally unfriendly." }, 40, "Haunted Mine"), + 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, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 391, 392, 393, 394, 395, 396}, new String[] { "Trolls regenerate damage quickly but are still", "vulnerable to poisons, they usually use crushing", "weapons." }, 1, false, false), + TUROTHS(60, new int[] { 1622, 1611, 1623, 1626, 1627, 1628, 1629, 1630, 7800}, new String[] { "Turoth are large vicious creatures with thick hides.", "You'll need a Leaf-Tipped Spear Sword or Battle-axe,", "Broad Arrows, or a Magic Dart to harm them." }, 55, false, false), + VAMPIRES(35, new int[] { 1220, 1223, 1225, 6214 }, new String[] { "Vampires are extremely powerful beings. They feed on", "the blood of the living so watch out you don't", "get bitten." }, 1, false, false), + // Waiting for the wall beast movement bug to be fixed before adding this as a task + WALL_BEASTS(1, new int[] { 7823 }, new String[] { "Wall Beasts are really much larger creatures but", "you'll only see their arms. You'll want something", "sharp on your head to stop them grabbing you." }, 35, false, false ), + // No way to get to Poison Swamp Cave + // If a grapple is implemented from W Castle Wars to E Posion Swamps + // The dungeon connected and populated + // then these could be added as a task + WARPED_TERROR_BIRD(1, new int[] { 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6608 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, "The Path of Glouphrie"), + WARPED_TORTOISE(1, new int[] { 6296, 6297 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, "The Path of Glouphrie"), + WATERFIENDS(75, new int[] { 5361 }, new String[] { "Waterfiends are creatures of water, which live under", "the Baxtorian Lake. Their watery form is well defended", "against slashing and piercing weapons, so use", "something blunt." }, 1, false, false), + WEREWOLVES(60, new int[] { 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[] { "Werewolves are feral creatures, they are strong and", "tough with sharp claws and teeth." }, 1, false, false), + WOLVES(20, new int[] { 95, 96, 97, 141, 142, 143, 839, 1198, 1330, 1558, 1559, 1951, 1952, 1953, 1954, 1955, 1956, 4413, 4414, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6829, 6830, 7005 }, new String[] { "Wolves are pack animals, so you'll always find them", "in groups. Watch out for their bite, it can be nasty." }, 1, false, false), + ZOMBIES(10, new int[] { 73, 74, 75, 76, 2060, 2714, 2863, 2866, 2869, 2878, 3622, 4392, 4393, 4394, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5375, 5376, 5377, 5378, 5379, 5380, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 6099, 6100, 6131, 8149, 8150, 8151, 8152, 8153, 8159, 8160, 8161, 8162, 8163, 8164, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 7641, 1465, 1466, 1467, 2837, 2838, 2839, 2840, 2841, 2842, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, 5641, 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, 2843, 2844, 2845, 2846, 2847, 2848}, new String[] { "Zombies are undead so magic is your best bet against", "them, there is even a spell specially for", "fighting the undead." }, 1, true, false), + // Bosses need to be handled differently/have a source. They should probably be removed from here + JAD(90, new int[] { }, new String[] { "You must complete the entire fight cave, including", "TzTok-Jad. Beware, only those skilled in combat should", "attempt this and death will reset your task." }, 1, false, false), + CHAOS_ELEMENTAL(90, new int[] { 3200 }, new String[] { "The Chaos Elemental roams the deepest Wilderness. It", "can teleport you and make you unequip items randomly." }, 1, false, false), + GIANT_MOLE(75, new int[] { 3340 }, new String[] { "Dig on the mole-hills in Falador Park to enter the", "mole cave, and bring a lantern he can't extinguish." }, 1, false, false), + KING_BLACK_DRAGON(75, new int[] { 50 }, new String[] { "The King Black Dragon's cave is reached by pulling a", "lever in the Wilderness. An anti-fire shield is", "strongly recommended." }, 1, false, true), + COMMANDER_ZILYANA(90, new int[] { 6247 }, new String[] { "Commander Zilyana is in the God Wars Dungeon.", "She frequently uses magic attacks." }, 1, false, false), + GENERAL_GRARDOOR(90, new int[] { 6260 }, new String[] { "General Graardor is in the God Wars Dungeon.", "He uses melee and ranged attacks." }, 1, false, false), + KRIL_TSUTSAROTH(90, new int[] { 6203 }, new String[] { "K'ril Tsutsaroth is in the God Wars Dungeon.", "He's poisonous and he can hit through prayers." }, 1, false, false), + KREE_ARRA(90, new int[] { 6222 }, new String[] { "Kree'arra roosts in the God Wars Dungeon.", "Melee attacks don't work on flying creatures,", "and you'll need a grappling hook to get in." }, 1, false, false), + ; static final HashMap taskMap = new HashMap<>(); static{ @@ -117,7 +144,6 @@ public enum Tasks { public final int[] ids; public boolean undead = false; public boolean dragon = false; - public int amtHash; public String questReq = ""; Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon){ this.levelReq = levelReq; @@ -128,16 +154,6 @@ public enum Tasks { this.combatCheck = combatCheck; } - Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon, int amtHash){ - this.levelReq = levelReq; - this.ids = ids; - this.info = info; - this.undead = undead; - this.dragon = dragon; - this.amtHash = amtHash; - this.combatCheck = combatCheck; - } - Tasks (int combatCheck, int[] ids, String[] info, int levelReq, String questReq) { this.combatCheck = combatCheck; this.ids = ids; @@ -155,7 +171,7 @@ public enum Tasks { } public boolean hasQuestRequirements (Player player) { - return questReq.equals("") || hasRequirement(player, questReq, false); + return questReq.isEmpty() || hasRequirement(player, questReq, false); } public static Tasks forId(int id){ diff --git a/Server/src/main/content/global/skill/slayer/unused-tasks b/Server/src/main/content/global/skill/slayer/unused-tasks deleted file mode 100644 index 03501f20e..000000000 --- a/Server/src/main/content/global/skill/slayer/unused-tasks +++ /dev/null @@ -1,92 +0,0 @@ - /*WALL_BEASTS(new Task(new int[] { 7823 }, new String[] { "A spiny helmet or equivalent is required to start fighting one " }, 35, new Master[] { Master.MAZCHNA }, false, Equipment.SPINY_HELMET) { - @Override - public boolean isDisabled() { - return true; - } - }), - WARPED_TERRORBIRDS(new Task(new int[] { 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, }, new String[] { "They require 56 Slayer and a Crystal chime to be killed. " }, 56, new Master[] { Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }), - WARPED_TORTOISES(new Task(new int[] { 6296, 6297 }, new String[] { "A warped tortoise is not as slow as they look." }, 56, new Master[] { Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ -/*CERBERUS(new Task(new int[] {8632, 8634}, new String[] {"Cerberus is about the best guard dog there is!"}, 91, new Master[] {Master.VANNAKA, Master.CHAELDAR, Master.NIEVE, Master.DURADEL}, false, 20 | 25 << 16) { - @Override - public boolean isDisabled() { - return true; - } - })*/ -/*ZYGOMITES(new Task(new int[] { 3346, 3347 }, new String[] { "Mutated zygomites are monsters that appear as Fungi until provoked." }, 57, new Master[] { Master.CHAELDAR }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ -/*SUQAHS(new Task(new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] {}, 1, new Master[] { Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }), - TERROR_DOG(new Task(new int[] { 5417, 5418 }, new String[] { "Terror Dogs are much like Wolves, they are pack creatures which will hunt in groups." }, 1, new Master[] { Master.VANNAKA, Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ -/*SHADOW_WARRIORS(new Task(new int[] { 158 }, new String[] { "Shadow warriors are dark and mysterious, they hide in the shadows so be wary of ambushes." }, 1, new Master[] { Master.VANNAKA, Master.CHAELDAR }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ -//MOGRES(new Task(new int[] { 114 }, new String[] { "Mogres are Slayer monsters and require level 32 Slayer to kill. " }, 32, new Master[] { Master.MAZCHNA, Master.VANNAKA }, false)), - /*MOLANISKS(new Task(new int[] { 5751 }, new String[] { "Molanisks are found attached to cave walls and must be lured", "off with a Slayer bell" }, 39, new Master[] { Master.VANNAKA }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ - - /*RED_DRAGONS(new Task(new int[] { 53, 4669, 4670, 4671, 4672, 1589, 3588, 4667, 4668, }, new String[] { "Red dragons aren't as strong as other dragons but they're still", "very powerful, watch out for their firey breath." }, 1, new Master[] { Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ - /*SCABARITES(new Task(new int[] { 2009 }, new String[] { "The Scabarites are fairly strong monsters, and can hit pretty hard." }, 1, new Master[] { Master.CHAELDAR }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ - /*SEA_SNAKES(new Task(new int[] { 3943, 3939, }, new String[] { "They are quick, make sure you don't let your", "eye off of them for 1 second." }, 1, new Master[] { Master.VANNAKA }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ -/*ELVES(new Task(new int[] { 1184, 1183, 1185 }, new String[] { "Elves are quick, agile and vicious fighters which", "often favour bows and polearms." }, 1, new Master[] { Master.VANNAKA, Master.CHAELDAR, Master.NIEVE }, false) { - @Override - public boolean isDisabled() { - return true; - } - }), - FEVER_SPIDERS(new Task(new int[] { 2850 }, new String[] { "Fever Spiders are giant spiders that carry the deadly Spider Fever.", "If you don't want to catch it I suggest you wear Slayer Gloves to fight them." }, 1, new Master[] { Master.CHAELDAR, Master.DURADEL }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ - /*KILLERWATTS(new Task(new int[] { 3201, 3202 }, new String[] { "Vexia halfassed this... (this was shadow knight text)" }, 37, new Master[] { Master.VANNAKA }, false) { - @Override - public boolean isDisabled() { - return true; - } - }),*/ \ No newline at end of file diff --git a/Server/src/main/core/game/system/command/sets/SlayerCommandSet.kt b/Server/src/main/core/game/system/command/sets/SlayerCommandSet.kt index 62e952d5b..9be1e0626 100644 --- a/Server/src/main/core/game/system/command/sets/SlayerCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/SlayerCommandSet.kt @@ -45,11 +45,12 @@ class SlayerCommandSet : CommandSet(Privilege.ADMIN){ val npc = (args[1].toIntOrNull() ?: reject(player, "Must enter valid npc id")) as Int val task = (Tasks.forId(npc) ?: reject(player, "Must enter valid npc id")) as Tasks + val masterTask = Master.Task(task, 1) val amount = args.getOrNull(2)?.toIntOrNull() ?.let { if (it !in 1..255) reject(player, "Amount must be an integer: 1-255.") else it } as Int? val slayer = SlayerManager.getInstance(player) - if (slayer.hasTask()) slayer.task = task else SlayerUtils.assign(player, task, Master.values().random()) + if (slayer.hasTask()) slayer.task = task else SlayerUtils.assign(player, masterTask, Master.values().random()) if (amount != null) slayer.amount = amount setVarp(player, 2502, slayer.flags.taskFlags shr 4) } From 6c386e6ed2fb30f44b9a5c3b74def33cb149c83d Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:15:07 +0000 Subject: [PATCH 176/306] Implemented Hunters' Crossbow --- Server/data/configs/npc_configs.json | 5 + Server/data/configs/shops.json | 9 ++ .../skill/fletching/BoltCreatePlugin.java | 51 ------- .../global/skill/fletching/BoltGemPlugin.java | 45 ------ .../skill/fletching/DartCreatePlugin.java | 49 ------- .../global/skill/fletching/FletchItem.java | 137 ------------------ .../global/skill/fletching/FletchType.java | 88 ----------- .../skill/fletching/FletchingListeners.kt | 32 ++++ .../yanille/dialogue/LeonDialogue.java | 96 ------------ .../kandarin/yanille/dialogue/LeonDialogue.kt | 134 +++++++++++++++++ 10 files changed, 180 insertions(+), 466 deletions(-) delete mode 100644 Server/src/main/content/global/skill/fletching/BoltCreatePlugin.java delete mode 100644 Server/src/main/content/global/skill/fletching/BoltGemPlugin.java delete mode 100644 Server/src/main/content/global/skill/fletching/DartCreatePlugin.java delete mode 100644 Server/src/main/content/global/skill/fletching/FletchItem.java delete mode 100644 Server/src/main/content/global/skill/fletching/FletchType.java delete mode 100644 Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.java create mode 100644 Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.kt diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 52829dd81..b453b65a6 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -72370,6 +72370,11 @@ "name": "Eclectic Impling", "id": "1033" }, + { + "examine": "He seems to be making odd sucking noises with his teeth.", + "name": "Leon", + "id": "5111" + }, { "examine": "A very stealthy impling.", "name": "Ninja Impling", diff --git a/Server/data/configs/shops.json b/Server/data/configs/shops.json index 7863aae6e..0b7745e45 100644 --- a/Server/data/configs/shops.json +++ b/Server/data/configs/shops.json @@ -2177,5 +2177,14 @@ "id": "255", "title": "Castle Wars Ticket Exchange", "stock": "{4068,1,100}-{4069,1,100}-{4070,1,100}-{4071,1,100}-{4072,1,100}-{4503,1,100}-{4504,1,100}-{4505,1,100}-{4506,1,100}-{4507,1,100}-{4508,1,100}-{4509,1,100}-{4510,1,100}-{4511,1,100}-{4512,1,100}-{4513,1,100}-{4514,1,100}-{4515,1,100}-{4516,1,100}" + }, + { + "npcs": "5111", + "high_alch": "0", + "currency": "995", + "general_store": "false", + "id": "256", + "title": "Leon's Prototype Crossbow", + "stock": "{10156,2,100}" } ] \ No newline at end of file diff --git a/Server/src/main/content/global/skill/fletching/BoltCreatePlugin.java b/Server/src/main/content/global/skill/fletching/BoltCreatePlugin.java deleted file mode 100644 index 711e9b626..000000000 --- a/Server/src/main/content/global/skill/fletching/BoltCreatePlugin.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -package core.game.node.entity.skill.fletching; - -import core.game.dialogue.SkillDialogueHandler; -import core.game.dialogue.SkillDialogueHandler.SkillDialogue; -import core.game.node.entity.skill.fletching.items.bolts.Bolt; -import core.game.node.entity.skill.fletching.items.bolts.BoltPulse; -import org.crandor.game.interaction.NodeUsageEvent; -import org.crandor.game.interaction.UseWithHandler; -import org.crandor.game.node.entity.player.Player; -import org.crandor.net.packet.PacketRepository; -import org.crandor.net.packet.context.ChildPositionContext; -import org.crandor.net.packet.out.RepositionChild; -import org.crandor.plugin.InitializablePlugin; -import org.crandor.plugin.Plugin; - -*/ -/** - * Represents the bolt creating plugin. - * @author 'Vexia - * @version 1.0 - *//* - -@InitializablePlugin -public final class BoltCreatePlugin extends UseWithHandler { - - */ -/** - * Constructs a new {@code BoltCreatePlugin} {@code Object}. - *//* - - public BoltCreatePlugin() { - super(314); - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (Bolt bolt : Bolt.values()) { - addHandler(bolt.getItem().getId(), ITEM_TYPE, this); - } - return this; - } - - @Override - public boolean handle(final NodeUsageEvent event) { - final Player player = event.getPlayer(); - - } - -} -*/ diff --git a/Server/src/main/content/global/skill/fletching/BoltGemPlugin.java b/Server/src/main/content/global/skill/fletching/BoltGemPlugin.java deleted file mode 100644 index 70c38b30a..000000000 --- a/Server/src/main/content/global/skill/fletching/BoltGemPlugin.java +++ /dev/null @@ -1,45 +0,0 @@ -//package core.game.node.entity.skill.fletching; -// -//import core.game.dialogue.SkillDialogueHandler; -//import core.game.dialogue.SkillDialogueHandler.SkillDialogue; -//import core.game.node.entity.skill.fletching.items.gem.GemBolt; -//import core.game.node.entity.skill.fletching.items.gem.GemBoltPulse; -//import org.crandor.game.interaction.NodeUsageEvent; -//import org.crandor.game.interaction.UseWithHandler; -//import org.crandor.game.node.entity.player.Player; -//import org.crandor.net.packet.PacketRepository; -//import org.crandor.net.packet.context.ChildPositionContext; -//import org.crandor.net.packet.out.RepositionChild; -//import org.crandor.plugin.InitializablePlugin; -//import org.crandor.plugin.Plugin; -// -///** -// * Represents the plugin used to handle gem bolt making. -// * @author 'Vexia -// * @version 1.0 -// */ -//@InitializablePlugin -//public class BoltGemPlugin extends UseWithHandler { -// -// /** -// * Constructs a new {@code BoltGemPlugin} {@code Object}. -// */ -// public BoltGemPlugin() { -// super(45, 46, 9187, 9188, 9189, 9190, 9191, 9192, 9193, 9194); -// } -// -// @Override -// public Plugin newInstance(Object arg) throws Throwable { -// for (GemBolt bolt : GemBolt.values()) { -// addHandler(bolt.getBase().getId(), ITEM_TYPE, this); -// } -// return this; -// } -// -// @Override -// public boolean handle(final NodeUsageEvent event) { -// final Player player = event.getPlayer(); -// -// } -// -//} diff --git a/Server/src/main/content/global/skill/fletching/DartCreatePlugin.java b/Server/src/main/content/global/skill/fletching/DartCreatePlugin.java deleted file mode 100644 index c43104095..000000000 --- a/Server/src/main/content/global/skill/fletching/DartCreatePlugin.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -package core.game.node.entity.skill.fletching; - -import core.game.node.entity.skill.fletching.items.darts.Dart; -import org.crandor.game.interaction.NodeUsageEvent; -import org.crandor.game.interaction.UseWithHandler; -import org.crandor.plugin.InitializablePlugin; -import org.crandor.plugin.Plugin; -import core.game.content.quest.touristrap.TouristTrap; - -*/ -/** - * Represents the plugin used to create a dart. - * @author 'Vexia - * @version 1.0 - *//* - -@InitializablePlugin -public final class DartCreatePlugin extends UseWithHandler { - - */ -/** - * Constructs a new {@code DartCreatePlugin} {@code Object}. - *//* - - public DartCreatePlugin() { - super(314); - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (Dart dart : Dart.values()) { - addHandler(dart.getItem().getId(), ITEM_TYPE, this); - } - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - if (event.getPlayer().getQuestRepository().getQuest(TouristTrap.NAME).getStage(event.getPlayer()) < 60) { - event.getPlayer().getPacketDispatch().sendMessage("You need to start Tourist Trap in order to do this."); - return true; - } - event.getPlayer().getDialogueInterpreter().open(328933, event.getUsedItem(), event.getBaseItem()); - return true; - } - -} -*/ diff --git a/Server/src/main/content/global/skill/fletching/FletchItem.java b/Server/src/main/content/global/skill/fletching/FletchItem.java deleted file mode 100644 index fee42d6c1..000000000 --- a/Server/src/main/content/global/skill/fletching/FletchItem.java +++ /dev/null @@ -1,137 +0,0 @@ -/* -package core.game.node.entity.skill.fletching; - -import org.crandor.game.node.item.Item; - -*/ -/** - * Represents a fletching item to make. - * @author 'Vexia - *//* - -public enum FletchItem { - ARROW_SHAFT(FletchType.LOG, new Item(52, 15), 1, 5), SHORTBOW(FletchType.LOG, new Item(50), 5, 5), - LONGBOW(FletchType.LOG, new Item(48), 10, 10), - OAK_SHORTBOW(FletchType.OAK, new Item(54), 20, 16.5), - OAK_LONGBOW(FletchType.OAK, new Item(56), 25, 25), - WILLOW_SHORTBOW(FletchType.WILLOW, new Item(60), 35, 33.3), - WILLOW_LONGBOW(FletchType.WILLOW, new Item(58), 40, 41.5), - MAPLE_SHORTBOW(FletchType.MAPLE, new Item(64), 50, 50), - MAPLE_LONGBOW(FletchType.MAPLE, new Item(62), 55, 58.3), - YEW_SHORTBOW(FletchType.YEW, new Item(68), 65, 55), - YEW_LONGBOW(FletchType.YEW, new Item(66), 70, 75), - MAGIC_SHORTBOW(FletchType.MAGIC, new Item(72), 80, 83.3), - MAGIC_LONGBOW(FletchType.MAGIC, new Item(70), 85, 91.5), - WOODEN_STOCK(FletchType.LOG, new Item(9440), 9, 6), - OAK_STOCK(FletchType.OAK, new Item(9442), 24, 16), - WILLOW_STOCK(FletchType.WILLOW, new Item(9444), 39, 22), - TEAK_STOCK(FletchType.TEAK, new Item(9446), 46, 27), - MAPLE_STOCK(FletchType.MAPLE, new Item(9448), 54, 32), - MAHOGANY_STOCK(FletchType.MAHOGANY, new Item(9450), 61, 41), - YEW_STOCK(FletchType.YEW, new Item(9452), 69, 50); - - */ -/** - * Constructs a new {@code FletchItem.java} {@code Object}. - * @param type the type. - * @param product the product. - * @param level the level. - * @param experience the experience. - *//* - - FletchItem(final FletchType type, final Item product, final int level, final double experience) { - this.type = type; - this.product = product; - this.level = level; - this.experience = experience; - } - - */ -/** - * Represents the type this item pertaint o. - *//* - - private FletchType type; - - */ -/** - * Represents the product of this item. - *//* - - private Item product; - - */ -/** - * Represents the level. - *//* - - private final int level; - - */ -/** - * Represents the experience. - *//* - - private final double experience; - - */ -/** - * Gets the type. - * @return The type. - *//* - - public FletchType getType() { - return type; - } - - */ -/** - * Sets the type. - * @param type The type to set. - *//* - - public void setType(FletchType type) { - this.type = type; - } - - */ -/** - * Gets the product. - * @return The product. - *//* - - public Item getProduct() { - return product; - } - - */ -/** - * Sets the product. - * @param product The product to set. - *//* - - public void setProduct(Item product) { - this.product = product; - } - - */ -/** - * Gets the level. - * @return The level. - *//* - - public int getLevel() { - return level; - } - - */ -/** - * Gets the experience. - * @return The experience. - *//* - - public double getExperience() { - return experience; - } -} -*/ diff --git a/Server/src/main/content/global/skill/fletching/FletchType.java b/Server/src/main/content/global/skill/fletching/FletchType.java deleted file mode 100644 index 33509c1ab..000000000 --- a/Server/src/main/content/global/skill/fletching/FletchType.java +++ /dev/null @@ -1,88 +0,0 @@ -/* -package core.game.node.entity.skill.fletching; - -import org.crandor.game.component.Component; -import org.crandor.game.node.item.Item; - -*/ -/** - * Represents the multiple fletching types(log types) - * @author 'Vexia - *//* - -public enum FletchType { - LOG(new Item(1511), FletchItem.ARROW_SHAFT, FletchItem.SHORTBOW, FletchItem.LONGBOW, FletchItem.WOODEN_STOCK), OAK(new Item(1521), FletchItem.OAK_SHORTBOW, FletchItem.OAK_LONGBOW, FletchItem.OAK_STOCK), WILLOW(new Item(1519), FletchItem.WILLOW_SHORTBOW, FletchItem.WILLOW_LONGBOW, FletchItem.WILLOW_STOCK), MAPLE(new Item(1517), FletchItem.MAPLE_SHORTBOW, FletchItem.MAPLE_LONGBOW, FletchItem.MAPLE_STOCK), TEAK(new Item(6333), FletchItem.TEAK_STOCK), MAHOGANY(new Item(6332), FletchItem.MAHOGANY_STOCK), YEW(new Item(1515), FletchItem.YEW_SHORTBOW, FletchItem.YEW_LONGBOW, FletchItem.YEW_STOCK), MAGIC(new Item(1513), FletchItem.MAGIC_SHORTBOW, FletchItem.MAGIC_LONGBOW); - - */ -/** - * Constructs a new {@code FletchType} {@code Object}. - * @param log the log. - * @param items the item.s - *//* - - FletchType(final Item log, final FletchItem... items) { - this.log = log; - this.items = items; - } - - */ -/** - * Represents the log of this type. - *//* - - private final Item log; - - */ -/** - * Represents the fletching items of this type. - *//* - - private FletchItem[] items; - - */ -/** - * Gets the items. - * @return The items. - *//* - - public FletchItem[] getItems() { - return items; - } - - */ -/** - * Gets the log. - * @return The log. - *//* - - public Item getLog() { - return log; - } - - */ -/** - * Method used to get the component based on type. - * @return the component. - *//* - - public Component getComponent() { - return items.length > 1 ? new Component(301 + items.length) : new Component(309); - } - - */ -/** - * Method used to get the FletchType based on the log item. - * @param item the item. - * @return the fletch type. - *//* - - public static FletchType forItem(final Item item) { - for (FletchType type : FletchType.values()) { - if (type.getLog().getId() == item.getId()) { - return type; - } - } - return null; - } -} -*/ diff --git a/Server/src/main/content/global/skill/fletching/FletchingListeners.kt b/Server/src/main/content/global/skill/fletching/FletchingListeners.kt index 54ac72b5d..52ae6f94b 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingListeners.kt +++ b/Server/src/main/content/global/skill/fletching/FletchingListeners.kt @@ -6,6 +6,7 @@ import content.global.skill.fletching.items.arrow.ArrowHeadPulse import content.global.skill.fletching.items.arrow.HeadlessArrowPulse import content.global.skill.fletching.items.bow.StringPulse import content.global.skill.fletching.items.crossbow.LimbPulse +import core.api.* import core.game.node.item.Item import core.net.packet.PacketRepository import core.net.packet.context.ChildPositionContext @@ -21,6 +22,7 @@ import org.rs09.consts.Items.YELLOW_FEATHER_10090 import core.game.dialogue.SkillDialogueHandler import core.game.interaction.InteractionListener import core.game.interaction.IntType +import core.game.node.entity.player.Player class FletchingListeners : InteractionListener { @@ -134,6 +136,36 @@ class FletchingListeners : InteractionListener { return@onUseWith true } + /** + * (Long) Kebbit bolts don't need feathers and go 6 at a time so use their own interaction + */ + fun makeKebbitBolt(player : Player, ingredient : Item) : Boolean{ + val longBolts = when(ingredient.id){ + Items.KEBBIT_SPIKE_10105 -> false + Items.LONG_KEBBIT_SPIKE_10107 -> true + else -> return false + } + val level = if(longBolts) 42 else 26 + if (getDynLevel(player, Skills.FLETCHING) < level){ + sendMessage(player, "You need a fletching level of $level to create ${if (longBolts) "long " else ""}kebbit bolts.") + return true + } + val finalProduct = if(longBolts) Items.LONG_KEBBIT_BOLTS_10159 else Items.KEBBIT_BOLTS_10158 + val xp = if(longBolts) 47.7 else 28.6 // source https://runescape.wiki/w/Fletching?oldid=1069981#Bolts_2 + if(removeItem(player, ingredient.id)){ + addItem(player, finalProduct, 6) + player.skills.addExperience(Skills.FLETCHING, xp) + animate(player, 885) + } + return true + } + onUseWith(IntType.ITEM, Items.CHISEL_1755, Items.KEBBIT_SPIKE_10105) { player, used, with -> + return@onUseWith makeKebbitBolt(player, with as Item) + } + + onUseWith(IntType.ITEM, Items.CHISEL_1755, Items.LONG_KEBBIT_SPIKE_10107) { player, used, with -> + return@onUseWith makeKebbitBolt(player, with as Item) + } } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.java b/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.java deleted file mode 100644 index 08f548ac6..000000000 --- a/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.java +++ /dev/null @@ -1,96 +0,0 @@ -package content.region.kandarin.yanille.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the dialogue plugin used for the leon npc. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class LeonDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code LeonDialogue} {@code Object}. - */ - public LeonDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code LeonDialogue} {@code Object}. - * @param player the player. - */ - public LeonDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new LeonDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendOptions("Select an Option", "What is this place?", "Can I have a go with your crossbow?", "What are you holding there?"); - stage = 1; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogues(player, FacialExpression.ASKING, "What is this place?"); - stage = 10; - break; - case 2: - interpreter.sendDialogues(player, FacialExpression.FRIENDLY, "Can I have a go with your crossbow?"); - stage = 20; - break; - case 3: - interpreter.sendDialogues(player, FacialExpression.ASKING, "What are you holding there?"); - stage = 30; - break; - - } - break; - case 10: - interpreter.sendDialogues(npc, FacialExpression.HAPPY, "This is Aleck's Hunter Emporium. Basically, it's just a", "shop with fancy name; you can buy various weapons", "and traps here."); - stage = 11; - break; - case 11: - end(); - break; - case 20: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I'm afraid with it being a prototype, I've only got a few", "for my own testing purposes."); - stage = 21; - break; - case 21: - end(); - break; - case 30: - interpreter.sendDialogues(npc, FacialExpression.HAPPY, "This? This is a prototype for a new type of crossbow", "I've been designing."); - stage = 31; - break; - case 31: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 5111 }; - } -} diff --git a/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.kt b/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.kt new file mode 100644 index 000000000..f5e3b2463 --- /dev/null +++ b/Server/src/main/content/region/kandarin/yanille/dialogue/LeonDialogue.kt @@ -0,0 +1,134 @@ +package content.region.kandarin.yanille.dialogue + +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.IfTopic +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class LeonDialogue (player: Player? = null) : DialoguePlugin(player) { + + companion object { + const val WHAT_IS_THIS_PLACE = 10 + const val BUY_GEAR = 20 + const val ABOUT_CBOW = 30 + const val ABOUT_AMMO = 40 + const val BYE = 50 + const val CRAZY = 60 + const val TRADE = 70 + const val MAKE_OWN_AMMO = 80 + const val CRAFT_AMMO = 90 + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + if (hasAnItem(player, Items.HUNTERS_CROSSBOW_10156).exists()) npcl(FacialExpression.HAPPY, "Oh, hey, you have one of my crossbows! How's it working for you?") + else sendItemDialogue(player, Items.HUNTERS_CROSSBOW_10156,"Leon is gazing intently at the crossbow in his hands.") + return true + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(stage){ + 0 -> showTopics( + IfTopic("It's okay, thanks.", 0, hasAnItem(player, Items.HUNTERS_CROSSBOW_10156).exists()), + Topic("What is this place?", WHAT_IS_THIS_PLACE), + Topic("Can you tell me about your crossbow?", ABOUT_CBOW), + Topic("Tell me about the ammo for your crossbow.", ABOUT_AMMO), + Topic("I'll be off now, excuse me.", BYE), + + ) + + WHAT_IS_THIS_PLACE -> npcl(FacialExpression.NEUTRAL, "This is Aleck's Hunter Emporium. Basically, it's just a shop with a fancy name; you can buy various weapons and traps here.").also { stage++ } + WHAT_IS_THIS_PLACE + 1 -> showTopics( + Topic("Can I buy some equipment from the shop then?", BUY_GEAR), + Topic("Can you tell me about your crossbow?", ABOUT_CBOW), + Topic("Tell me about the ammo for your crossbow.", ABOUT_AMMO), + Topic("I'll be off now, excuse me.", BYE) + ) + + BUY_GEAR -> npcl(FacialExpression.NEUTRAL, "Oh, this isn't my shop; the owner is Aleck over there behind the counter.").also { stage++ } + BUY_GEAR + 1 -> npcl(FacialExpression.NEUTRAL, "I experiment with weapon designs. I'm here because I've been trying to convince people to back my research and maybe sell some of my products - like this one I'm holding - in their shops.").also { stage++ } + BUY_GEAR + 2 -> npcl(FacialExpression.SAD, "Aleck doesn't seem to be interested, though.").also { stage++ } + BUY_GEAR + 3 -> showTopics( + Topic("Can you tell me about your crossbow?", ABOUT_CBOW), + Topic("Tell me about the ammo for your crossbow.", ABOUT_AMMO), + Topic("I'll be off now, excuse me.", BYE) + ) + + ABOUT_CBOW -> npcl(FacialExpression.HAPPY, "It's good, isn't it? I designed it to incorporate the bones of various animals in its construction.").also { stage++ } + ABOUT_CBOW + 1 -> npcl(FacialExpression.HAPPY, "It's a fair bit faster than an ordinary crossbow too; it'll take you far less time to reload between shots.").also { stage++ } + ABOUT_CBOW + 2 -> showTopics( + Topic("That's crazy, it'll never work!", CRAZY), + Topic("That sounds good. Let's trade.", TRADE) + ) + + CRAZY -> npcl(FacialExpression.HALF_THINKING, "That's what they said about my wind-powered mouse traps, too.").also { stage++ } + CRAZY + 1 -> playerl(FacialExpression.HALF_WORRIED, "And did they work?").also { stage++ } + CRAZY + 2 -> npcl(FacialExpression.HALF_THINKING, "Well, they only ran into problems because people kept insisting on trying to use them indoors.").also { stage++ } + CRAZY + 3 -> npcl(FacialExpression.HAPPY, "Anyway, I think my crossbow invention is showing a lot more promise.").also { stage = 0 } + + TRADE -> { + end() + openNpcShop(player, npc.id) + } + + ABOUT_AMMO -> npcl(FacialExpression.NEUTRAL, "Ah, I admit as a result of its... er... unique construction, it won't take just any old bolts.").also { stage++ } + ABOUT_AMMO + 1 -> npcl(FacialExpression.NEUTRAL, "If you can supply the materials and a token fee, I'd be happy to make some for you.").also { stage++ } + ABOUT_AMMO + 2 -> npcl(FacialExpression.NEUTRAL, "I need kebbit spikes, lots of 'em. Not all kebbits have spikes, mind you. You'll be wanting prickly kebbits or, even better, razor-backed kebbits to get material hard enough.").also { stage++ } + ABOUT_AMMO + 3 -> showTopics( + Topic("Can't I just make my own?", MAKE_OWN_AMMO), + Topic("Okay, can you make ammo for me?", CRAFT_AMMO) + ) + + MAKE_OWN_AMMO -> npcl(FacialExpression.HALF_THINKING, "Yes, I suppose you could, although you'll need a steady hand with a knife and a chisel.").also { stage++ } + MAKE_OWN_AMMO + 1 -> npcl(FacialExpression.HALF_THINKING, "The bolts have an unusual diameter, but basically you'll just need to be able to carve kebbit spikes into straight shafts.").also { stage++ } + MAKE_OWN_AMMO + 2 -> npcl(FacialExpression.NEUTRAL, "Meanwhile, since you're here, I can make some for you if you have the materials.").also { stage = 0 } + + // OSRS suggests this may be inauthentic and there should be a make x interface. + // No 2009 sources found saying that though + CRAFT_AMMO -> npcl(FacialExpression.NEUTRAL, "Sure what type of bolts do you want?").also { stage++ } + CRAFT_AMMO + 1 -> showTopics( + Topic("Kebbit bolts.", CRAFT_AMMO + 2), + Topic("Long kebbit bolts.", CRAFT_AMMO + 3) + ) + CRAFT_AMMO + 2 -> { + if (hasAnItem(player!!, Items.KEBBIT_SPIKE_10105).exists() && inInventory(player, Items.COINS_995, 20)){ + if(removeItem(player, Items.KEBBIT_SPIKE_10105) && removeItem(player, Item(Items.COINS_995, 20))){ + addItem(player, Items.KEBBIT_BOLTS_10158, 6) + sendItemDialogue(player, Items.KEBBIT_BOLTS_10158, "You hand the weapon designer one spike and 20 coins. In return he presents you with 6 bolts.").also { stage = END_DIALOGUE } + } + } + else{ + sendItemDialogue(player, Items.KEBBIT_SPIKE_10105, "You need 1 kebbit spike and 20 coins to make 6 kebbit bolts.").also { stage = END_DIALOGUE } + } + } + CRAFT_AMMO + 3 -> { + if (hasAnItem(player!!, Items.LONG_KEBBIT_SPIKE_10107).exists() && inInventory(player, Items.COINS_995, 24)){ + if(removeItem(player, Items.LONG_KEBBIT_SPIKE_10107) && removeItem(player, Item(Items.COINS_995, 40))){ + addItem(player, Items.LONG_KEBBIT_BOLTS_10159, 6) + sendItemDialogue(player, Items.LONG_KEBBIT_BOLTS_10159, "You hand the weapon designer one long spike and 40 coins. In return he presents you with 6 long bolts.").also { stage = END_DIALOGUE } + } + } + else{ + sendItemDialogue(player, Items.LONG_KEBBIT_SPIKE_10107, "You need 1 long kebbit spike and 40 coins to make 6 kebbit bolts.").also { stage = END_DIALOGUE } + } + } + + BYE -> npcl(FacialExpression.NEUTRAL, "Well, if you ever find yourself in need of that innovative edge, you can always find me here.").also { stage++ } + BYE + 1 -> playerl(FacialExpression.HALF_ROLLING_EYES, "...thanks").also { stage = END_DIALOGUE } + } + + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.LEON_5111) + } +} \ No newline at end of file From 57f5617fe8cb1de353c8f44c6f6b8a58e17abea2 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:18:19 +0000 Subject: [PATCH 177/306] Fixed loss of draconic visages if used on an anvil without an anti-dragon shield in the player's inventory Fixed dragonfire shield and dragon square shield smithing not checking for a hammer in inventory --- .../skill/smithing/DragonShieldDialogue.java | 89 ++++++++----------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/Server/src/main/content/global/skill/smithing/DragonShieldDialogue.java b/Server/src/main/content/global/skill/smithing/DragonShieldDialogue.java index 84d4e7edf..64833097c 100644 --- a/Server/src/main/content/global/skill/smithing/DragonShieldDialogue.java +++ b/Server/src/main/content/global/skill/smithing/DragonShieldDialogue.java @@ -1,55 +1,23 @@ package content.global.skill.smithing; +import content.global.skill.skillcapeperks.SkillcapePerks; +import core.api.Container; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; -import core.game.node.item.Item; import core.plugin.Initializable; -import core.game.world.update.flag.context.Animation; +import org.rs09.consts.Items; + +import static core.api.ContentAPIKt.*; /** * Represents the dialogue plugin used for making a dragon shield. * @author 'Vexia - * @version 1.0 + * @author Player Name + * @version 1.1 */ @Initializable public final class DragonShieldDialogue extends DialoguePlugin { - - /** - * Represents the item shield parts. - */ - private static final Item[] SHIELD_PARTS = new Item[] { new Item(2366), new Item(2368) }; - - /** - * Represents th edraconic visage item. - */ - private static final Item DRACONIC_VISAGE = new Item(11286); - - /** - * Represents the anti dragon fire shield. - */ - private static final Item ANTI_DRAGONSHIELD = new Item(1540); - - /** - * Represents the dragon fire shield item. - */ - private static final Item DRAGON_FIRESHIELD = new Item(11284); - - /** - * Represents the shield item. - */ - private static final Item SQ_SHIELD = new Item(1187); - - /** - * Represents the hammering animation. - */ - private static Animation ANIMATION = new Animation(898); - - /** - * Represents the shield type. - */ - private int type; - /** * Constructs a new {@code DragonShieldDialogue} {@code Object}. */ @@ -74,11 +42,26 @@ public final class DragonShieldDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - type = (int) args[0]; + if (!inInventory(player, Items.HAMMER_2347, 1) && !SkillcapePerks.isActive(SkillcapePerks.BAREFISTED_SMITHING, player)) { + interpreter.sendDialogue("You need a hammer to work the metal with."); + } + int type = (int) args[0]; if (type == 1) { - interpreter.sendDialogue("You set to work trying to fix the ancient shield. It's seen some", "heavy reward and needs some serious work doing to it."); + if (!(inInventory(player, Items.SHIELD_RIGHT_HALF_2368, 1) && inInventory(player, Items.SHIELD_LEFT_HALF_2366, 1))) { + interpreter.sendDialogue("You need the other half of the shield."); //todo authentic message + return false; + } + interpreter.sendDialogue("You set to work trying to fix the ancient shield. It's seen some", "heavy action and needs some serious work doing to it."); stage = 0; } else { + if (!inInventory(player, Items.ANTI_DRAGON_SHIELD_1540, 1)) { + interpreter.sendDialogue("You need an anti-dragon shield to attach the visage to."); //todo authentic message + return false; + } + if (!inInventory(player, Items.DRACONIC_VISAGE_11286, 1)) { + interpreter.sendDialogue("You don't have anything you could attach to the shield."); //todo authentic message + return false; + } interpreter.sendDialogue("You set to work, trying to attach the ancient draconic", "visage to your anti-dragonbreath shield. It's not easy to", "work with the ancient artifact and it takes all of your", "skills as a master smith."); stage = 10; } @@ -89,26 +72,26 @@ public final class DragonShieldDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - player.lock(5); - player.animate(ANIMATION); - interpreter.sendDialogue("Even for an experienced armourer it is not an easy task, but", "eventually it is ready. You have restored the dragon square shield to", "its former glory."); - if (player.getInventory().remove(SHIELD_PARTS)) { - player.getInventory().add(SQ_SHIELD); + lock(player, 5); + animate(player, 898, false); + if (removeItem(player, Items.SHIELD_RIGHT_HALF_2368, Container.INVENTORY) && removeItem(player, Items.SHIELD_LEFT_HALF_2366, Container.INVENTORY)) { + interpreter.sendDialogue("Even for an experienced armourer it is not an easy task, but", "eventually it is ready. You have restored the dragon square shield to", "its former glory."); + addItem(player, Items.DRAGON_SQ_SHIELD_1187, 1, Container.INVENTORY); + rewardXP(player, Skills.SMITHING, 75); } - player.getSkills().addExperience(Skills.SMITHING, 75, true); stage = 1; break; case 1: end(); break; case 10: - player.lock(5); - player.animate(ANIMATION); - interpreter.sendDialogue("Even for an experienced armourer it is not an easy task, but", "eventually it is ready. You have crafted the", "draconic visage and anti-dragonbreath shield into a", "dragonfire shield."); - if (player.getInventory().remove(DRACONIC_VISAGE, ANTI_DRAGONSHIELD)) { - player.getInventory().add(DRAGON_FIRESHIELD); + lock(player, 5); + animate(player, 898, false); + if (removeItem(player, Items.ANTI_DRAGON_SHIELD_1540, Container.INVENTORY) && removeItem(player, Items.DRACONIC_VISAGE_11286, Container.INVENTORY)) { + interpreter.sendDialogue("Even for an experienced armourer it is not an easy task, but", "eventually it is ready. You have crafted the", "draconic visage and anti-dragonbreath shield into a", "dragonfire shield."); + addItem(player, Items.DRAGONFIRE_SHIELD_11284, 1, Container.INVENTORY); + rewardXP(player, Skills.SMITHING, 2000); } - player.getSkills().addExperience(Skills.SMITHING, 2000); stage = 1; break; } From b62f4e9525cfa5948c7606ed3a32b749273272d8 Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:19:17 +0000 Subject: [PATCH 178/306] Implemented black swan NPC --- Server/data/configs/npc_configs.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index b453b65a6..eba0dde1d 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -72380,6 +72380,12 @@ "name": "Ninja Impling", "id": "6053" }, + { + "examine": "A rare bird.", + "name": "Black Swan", + "water_npc": "true", + "id": "3297" + }, { "examine": "A nature impling. Right on, maaan.", "name": "Nature Impling", From 064edfbbe47cabb0225931f42660dacc126f61c0 Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Sat, 1 Feb 2025 13:20:27 +0000 Subject: [PATCH 179/306] Implemented spirit saratrice --- .../familiar/CockatriceFamiliarNPC.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/CockatriceFamiliarNPC.java b/Server/src/main/content/global/skill/summoning/familiar/CockatriceFamiliarNPC.java index d1716b3d5..02564d7e1 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/CockatriceFamiliarNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/CockatriceFamiliarNPC.java @@ -34,6 +34,7 @@ public final class CockatriceFamiliarNPC implements Plugin { ClassScanner.definePlugin(new SpiritPengatrice()); ClassScanner.definePlugin(new SpiritCoraxatrice()); ClassScanner.definePlugin(new SpiritVulatrice()); + ClassScanner.definePlugin(new SpiritSaratrice()); return this; } @@ -58,7 +59,11 @@ public final class CockatriceFamiliarNPC implements Plugin { GameWorld.getPulser().submit(new Pulse(1, familiar.getOwner(), familiar, target) { @Override public boolean pulse() { - target.getSkills().updateLevel(skill, -3, 0); + if(skill == 5) { + target.skills.decrementPrayerPoints(3); + }else { + target.getSkills().updateLevel(skill, -3, 0); + } Projectile.magic(familiar, target, 1468, 40, 36, 71, 10).send(); familiar.sendFamiliarHit(target, 10, Graphics.create(1469)); return true; @@ -297,4 +302,43 @@ public final class CockatriceFamiliarNPC implements Plugin { } } + + /** + * Represents the Spirit Saratrice familiar. + * @author Aero - DeadlyGenga + */ + public class SpiritSaratrice extends Forager { + + /** + * Constructs a new {@code SpiritSaratriceNPC} {@code Object}. + */ + public SpiritSaratrice() { + this(null, 6879); + } + + /** + * Constructs a new {@code SpiritSaratriceNPC} {@code Object}. + * @param owner The owner. + * @param id The id. + */ + public SpiritSaratrice(Player owner, int id) { + super(owner, id, 3600, 12099, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG); + } + + @Override + public Familiar construct(Player owner, int id) { + return new SpiritSaratrice(owner, id); + } + + @Override + protected boolean specialMove(FamiliarSpecial special) { + return petrifyingGaze(this, special, Skills.PRAYER); + } + + @Override + public int[] getIds() { + return new int[] { 6879, 6880 }; + } + + } } From edc6f9cf07ddb8bc0af40aa5f83ffddf15f5c2fe Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:23:42 +0000 Subject: [PATCH 180/306] Implemented Gaze of Saradomin Fixed respawn bugs --- .../dialogue/SirTiffyCashienDialogue.kt | 52 ++++++++++++------- .../core/game/node/entity/player/Player.java | 4 +- .../entity/player/info/login/LoginParser.kt | 7 +-- .../player/info/login/PlayerSaveParser.kt | 3 -- .../command/sets/DevelopmentCommandSet.kt | 9 ++-- 5 files changed, 41 insertions(+), 34 deletions(-) diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt index 40420b785..25c8bfbf7 100644 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt @@ -52,6 +52,22 @@ class SirTiffyCashienDialogue (player: Player? = null) : DialoguePlugin(player) // Move this to Wanted!! Quest. class SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile : DialogueBuilderFile() { + private fun dialogueChangeSpawnPoint(builder: DialogueBuilder, place: String, location: Location, tiffyLine1: String, tiffyLine2: String): DialogueBuilder { + return builder.npcl("${tiffyLine1} Are you sure?") + .options().let { optionBuilder -> + optionBuilder.option("Yes, I want to respawn in $place.") + .playerl("Yes, I want to respawn in $place.") + .npcl(tiffyLine2) + .endWith { _, player -> + setAttribute(player, "/save:spawnLocation", location) + player.properties.spawnLocation = location + } + optionBuilder.option("Actually, no thanks. I like my respawn point.") + .playerl("Actually, no thanks. I like my respawn point.") + .npcl("As you wish, what? Ta-ta for now.") + } + } + override fun create(b: DialogueBuilder) { b.onPredicate { _ -> true } .npc(FacialExpression.HAPPY, "What ho, @g[sirrah,milady].", "Jolly good show on the old training grounds thingy,", "what?") @@ -79,28 +95,26 @@ class SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile : DialogueBuilderFil .endWith { _, player -> openNpcShop(player, npc!!.id) } - optionBuilder.option_playerl("Can I switch respawns please?") - .npcl("I'm sorry dear @g[boy,gal], I'm afraid I can't switch your respawn point at the moment.") - .end() -// I have no idea how to do this properly. -// optionBuilder.option("Can I switch respawns please?") -// .branch { player -> if(player.properties.spawnLocation == Location(2997, 3375, 0)) { 1 } else { 0 } } -// .let { branch -> -// branch.onValue(1) -// .npcl("Ah, so you'd like to respawn in Falador, the good old homestead! Are you sure?") -// .endWith { _, player -> -// player.properties.spawnLocation = Location(2997, 3375, 0) -// } -// branch.onValue(0) -// .npcl("What? You're saying you want to respawn in Lumbridge? Are you sure?") -// .endWith { _, player -> -// player.properties.spawnLocation = ServerConstants.HOME_LOCATION -// } -// } + optionBuilder.option("Can I switch respawns please?") + .branch { player -> if (player.properties.spawnLocation == ServerConstants.HOME_LOCATION) { 1 } else { 0 } } + .let { branch -> + dialogueChangeSpawnPoint( + branch.onValue(1), + "Falador", Location(2971, 3340, 0), //https://www.youtube.com/watch?v=Mm15dHuIaVg + "Ah, so you'd like to respawn in Falador, the good old homestead!", + "Top-hole, what? Good old Fally is definitely the hot-spot nowadays!" + ) + dialogueChangeSpawnPoint( + branch.onValue(0), + "Lumbridge", ServerConstants.HOME_LOCATION ?: Location(3222, 3218, 0), + "What? You're saying you want to respawn in Lumbridge?", + "Why anyone would want to visit that smelly little swamp village of oiks is quite beyond me, I'm afraid, but the deed is done now." + ) + } optionBuilder.option("Goodbye.") .playerl("Well, see you around Tiffy.") .npcl(FacialExpression.HAPPY,"Ta-ta for now, old bean!") .end() } } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 0fb8f6110..63fd5f611 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -326,10 +326,8 @@ public class Player extends Entity { @Override public void init() { - if(!artificial) - log(this.getClass(), Log.INFO, getUsername() + " initialising..."); if (!artificial) { - getProperties().setSpawnLocation(ServerConstants.HOME_LOCATION); + log(this.getClass(), Log.INFO, getUsername() + " initialising..."); getDetails().getSession().setObject(this); } super.init(); diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginParser.kt b/Server/src/main/core/game/node/entity/player/info/login/LoginParser.kt index 85fdf972a..75eb6e4c6 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginParser.kt @@ -1,11 +1,12 @@ package core.game.node.entity.player.info.login +import core.ServerConstants import core.api.* +import core.auth.AuthResponse import core.game.node.entity.player.Player import core.game.node.entity.player.info.PlayerDetails import core.game.system.SystemManager import core.game.system.task.Pulse -import core.auth.AuthResponse import core.game.world.GameWorld import core.game.world.GameWorld.loginListeners import core.game.world.repository.Repository @@ -27,8 +28,7 @@ class LoginParser(val details: PlayerDetails) { parser = PlayerParser.parse(player) ?: throw IllegalStateException("Failed parsing save for: " + player.username) //Parse core } - catch (e: Exception) - { + catch (e: Exception) { e.printStackTrace() Repository.removePlayer(player) flag(AuthResponse.ErrorLoadingProfile) @@ -37,6 +37,7 @@ class LoginParser(val details: PlayerDetails) { override fun pulse(): Boolean { try { if (details.session.isActive) { + player.properties.spawnLocation = getAttribute(player, "/save:spawnLocation", ServerConstants.HOME_LOCATION) loginListeners.forEach(Consumer { listener: LoginListener -> listener.login(player) }) //Run our login hooks parser.runContentHooks() //Run our saved-content-parsing hooks player.details.session.setObject(player) diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index 64e4a80e6..b48f72e63 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -1,7 +1,5 @@ package core.game.node.entity.player.info.login -import content.global.skill.farming.CompostBins -import content.global.skill.farming.FarmingPatch import core.JSONUtils import core.api.PersistPlayer import core.game.node.entity.combat.spell.CombatSpell @@ -18,7 +16,6 @@ import core.ServerConstants import core.api.log import core.game.node.entity.combat.graves.GraveController import core.game.node.entity.combat.graves.GraveType -import core.tools.SystemLogger import core.game.world.GameWorld import core.tools.Log import java.io.File diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index dbf032a3c..24766719d 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -1,14 +1,12 @@ package core.game.system.command.sets import content.global.activity.jobs.JobManager -import content.global.skill.slayer.Master import core.api.* import core.cache.Cache import core.cache.def.impl.DataMap import core.cache.def.impl.NPCDefinition import core.cache.def.impl.VarbitDefinition import core.cache.def.impl.Struct -import core.game.dialogue.DialogueFile import core.game.node.entity.combat.ImpactHandler.HitsplatType import core.game.node.entity.player.Player import core.game.node.entity.player.link.SpellBookManager @@ -20,7 +18,6 @@ import core.plugin.Initializable import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.rs09.consts.Items -import core.tools.SystemLogger import core.game.system.command.Privilege import java.io.BufferedWriter import java.io.File @@ -28,10 +25,10 @@ import java.io.FileWriter import java.util.Arrays import core.net.packet.PacketWriteQueue import core.tools.Log -import core.game.world.update.flag.* -import core.game.world.update.flag.context.* -import core.game.node.entity.impl.* +import core.game.node.entity.player.info.Rights +import core.game.node.entity.skill.Skills import core.game.world.map.Location +import core.game.world.repository.Repository @Initializable class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { From f37b30749ee2430e7808bf134f7e7c39d49f9115 Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:25:23 +0000 Subject: [PATCH 181/306] Iron men can no longer participate in lootshare --- .../handlers/iface/ClanInterfacePlugin.java | 22 +++++++++++-------- .../node/entity/npc/drop/NPCDropTables.java | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/ClanInterfacePlugin.java b/Server/src/main/content/global/handlers/iface/ClanInterfacePlugin.java index 1ad3857e8..5003507c2 100644 --- a/Server/src/main/content/global/handlers/iface/ClanInterfacePlugin.java +++ b/Server/src/main/content/global/handlers/iface/ClanInterfacePlugin.java @@ -36,17 +36,21 @@ public final class ClanInterfacePlugin extends ComponentPlugin { switch (component.getId()) { case 589: switch (button) { - case 9: - if (player.getInterfaceManager().getComponent(590) != null) { - player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'"); + case 9: + if (player.getInterfaceManager().getComponent(590) != null) { + player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'"); + return true; + } + ClanRepository.openSettings(player); return true; - } - ClanRepository.openSettings(player); - return true; - case 14: - player.getDetails().getCommunication().toggleLootshare(player); - return true; + case 14: + if (player.getIronmanManager().checkRestriction()) { + return false; + } + player.getDetails().getCommunication().toggleLootshare(player); + return true; } + break; case 590: final ClanRepository clan = ClanRepository.get(player.getName(), true); diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index e4e1cd3b6..baacc117b 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -147,7 +147,7 @@ public final class NPCDropTables { List players = RegionManager.getLocalPlayers(npc, 16); List looters = new ArrayList<>(20); for (Player p : players) { - if (p != null && p.getCommunication().getClan() != null && p.getCommunication().getClan() == player.getCommunication().getClan() && p.getCommunication().isLootShare() && p.getCommunication().getLootRequirement().ordinal() >= p.getCommunication().getClan().getLootRequirement().ordinal() && !p.getIronmanManager().isIronman()) { + if (p != null && p.getCommunication().getClan() != null && p.getCommunication().getClan() == player.getCommunication().getClan() && p.getCommunication().isLootShare() && p.getCommunication().getLootRequirement().ordinal() >= p.getCommunication().getClan().getLootRequirement().ordinal()) { looters.add(p); } } From 818ffc01e7902a99ed1abf2c838eb82197130f2d Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:27:03 +0000 Subject: [PATCH 182/306] Removed random events from Tutorial Island --- .../region/misc/tutisland/handlers/TutorialArea.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Server/src/main/content/region/misc/tutisland/handlers/TutorialArea.kt diff --git a/Server/src/main/content/region/misc/tutisland/handlers/TutorialArea.kt b/Server/src/main/content/region/misc/tutisland/handlers/TutorialArea.kt new file mode 100644 index 000000000..082da760b --- /dev/null +++ b/Server/src/main/content/region/misc/tutisland/handlers/TutorialArea.kt @@ -0,0 +1,10 @@ +package content.region.misc.tutisland.handlers + +import core.api.* +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction + +class TutorialArea : MapArea { + override fun defineAreaBorders() : Array { return arrayOf(12079, 12080, 12335, 12336, 12436, 12592).map { ZoneBorders.forRegion(it) }.toTypedArray() } + override fun getRestrictions() : Array { return arrayOf(ZoneRestriction.RANDOM_EVENTS) } +} From ccc60b12403e604546ce67167a4b6235eb5078c3 Mon Sep 17 00:00:00 2001 From: Tooze Date: Sat, 1 Feb 2025 13:38:50 +0000 Subject: [PATCH 183/306] Implemented knife spawn in Sorcerer's Tower --- Server/data/configs/ground_spawns.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json index 49a0f8786..9b44b4f65 100644 --- a/Server/data/configs/ground_spawns.json +++ b/Server/data/configs/ground_spawns.json @@ -233,7 +233,7 @@ }, { "item_id": "946", - "loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-" + "loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-{1,2700,3407,0,100}-" }, { "item_id": "952", From 0c8efbac7af9f3fbfe6c1f1f0b0f9761a4a9df0d Mon Sep 17 00:00:00 2001 From: GregF Date: Sat, 1 Feb 2025 13:42:53 +0000 Subject: [PATCH 184/306] Added all missing NPCs to config file for future use --- Server/data/configs/npc_configs.json | 14632 +++++++++++++++++++++++++ 1 file changed, 14632 insertions(+) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index eba0dde1d..c8ee4ef73 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -72330,6 +72330,14638 @@ "name": "Balnea", "id": "7047" }, + { + "id": "17", + "name": "Schoolgirl" + }, + { + "id": "70", + "name": "Orc" + }, + { + "id": "94", + "name": "Skeleton Mage" + }, + { + "id": "129", + "name": "Skavid" + }, + { + "id": "135", + "name": "Mammoth" + }, + { + "id": "136", + "name": "Mounted terrorchick gnome" + }, + { + "id": "149", + "name": "Gull" + }, + { + "id": "150", + "name": "Gull" + }, + { + "id": "151", + "name": "Fly trap" + }, + { + "id": "152", + "name": "Butterfly" + }, + { + "id": "155", + "name": "Butterfly" + }, + { + "id": "156", + "name": "Butterfly" + }, + { + "id": "157", + "name": "Butterfly" + }, + { + "id": "165", + "name": "Gnome shop keeper" + }, + { + "id": "167", + "name": "Gnome baller" + }, + { + "id": "171", + "name": "Brimstail" + }, + { + "id": "177", + "name": "Witch" + }, + { + "id": "195", + "name": "Bandit" + }, + { + "id": "197", + "name": "Barbarian guard" + }, + { + "id": "200", + "name": "Lord Daquarius" + }, + { + "id": "207", + "name": "Lollk" + }, + { + "id": "209", + "name": "Nulodion" + }, + { + "id": "211", + "name": "Sir Percival" + }, + { + "id": "213", + "name": "Merlin" + }, + { + "id": "215", + "name": "Peasant" + }, + { + "id": "217", + "name": "Crone" + }, + { + "id": "218", + "name": "Galahad" + }, + { + "id": "225", + "name": "Bonzo" + }, + { + "id": "226", + "name": "Morris" + }, + { + "id": "228", + "name": "Big Dave" + }, + { + "id": "229", + "name": "Joshua" + }, + { + "id": "232", + "name": "Austri" + }, + { + "id": "234", + "name": "Fishing spot" + }, + { + "id": "235", + "name": "Fishing spot" + }, + { + "id": "236", + "name": "Fishing spot" + }, + { + "id": "239", + "name": "Sir Lancelot" + }, + { + "id": "240", + "name": "Sir Gawain" + }, + { + "id": "241", + "name": "Sir Kay" + }, + { + "id": "242", + "name": "Sir Bedivere" + }, + { + "id": "243", + "name": "Sir Tristram" + }, + { + "id": "244", + "name": "Sir Pelleas" + }, + { + "id": "245", + "name": "Sir Lucan" + }, + { + "id": "248", + "name": "Morgan Le Faye" + }, + { + "id": "249", + "name": "Merlin" + }, + { + "id": "250", + "name": "The Lady of the Lake" + }, + { + "id": "252", + "name": "Beggar" + }, + { + "id": "260", + "name": "Kelvin" + }, + { + "id": "261", + "name": "Joe" + }, + { + "id": "263", + "name": "Hengrad" + }, + { + "id": "276", + "name": "Winelda" + }, + { + "id": "287", + "name": "Ernest" + }, + { + "id": "292", + "name": "Guard" + }, + { + "id": "301", + "name": "Twig" + }, + { + "id": "302", + "name": "Hadley" + }, + { + "id": "303", + "name": "Gerald" + }, + { + "id": "304", + "name": "Almera" + }, + { + "id": "305", + "name": "Hudon" + }, + { + "id": "306", + "name": "Golrie" + }, + { + "id": "309", + "name": "Fishing spot" + }, + { + "id": "310", + "name": "Fishing spot" + }, + { + "id": "311", + "name": "Fishing spot" + }, + { + "id": "312", + "name": "Fishing spot" + }, + { + "id": "313", + "name": "Fishing spot" + }, + { + "id": "314", + "name": "Fishing spot" + }, + { + "id": "315", + "name": "Fishing spot" + }, + { + "id": "316", + "name": "Fishing spot" + }, + { + "id": "317", + "name": "Fishing spot" + }, + { + "id": "318", + "name": "Fishing spot" + }, + { + "id": "319", + "name": "Fishing spot" + }, + { + "id": "320", + "name": "Fishing spot" + }, + { + "id": "321", + "name": "Fishing spot" + }, + { + "id": "322", + "name": "Fishing spot" + }, + { + "id": "324", + "name": "Fishing spot" + }, + { + "id": "325", + "name": "Fishing spot" + }, + { + "id": "326", + "name": "Fishing spot" + }, + { + "id": "327", + "name": "Fishing spot" + }, + { + "id": "328", + "name": "Fishing spot" + }, + { + "id": "329", + "name": "Fishing spot" + }, + { + "id": "330", + "name": "Fishing spot" + }, + { + "id": "331", + "name": "Fishing spot" + }, + { + "id": "332", + "name": "Fishing spot" + }, + { + "id": "333", + "name": "Fishing spot" + }, + { + "id": "334", + "name": "Fishing spot" + }, + { + "id": "337", + "name": "Da Vinci" + }, + { + "id": "343", + "name": "Guidor" + }, + { + "id": "349", + "name": "Kilron" + }, + { + "id": "350", + "name": "Omart" + }, + { + "id": "366", + "name": "Jerico" + }, + { + "id": "379", + "name": "Luthas" + }, + { + "id": "381", + "name": "Dwarf" + }, + { + "id": "383", + "name": "Stankers" + }, + { + "id": "399", + "name": "Legends guard" + }, + { + "id": "400", + "name": "Radimus Erkle" + }, + { + "id": "403", + "name": "Fishing spot" + }, + { + "id": "404", + "name": "Fishing spot" + }, + { + "id": "405", + "name": "Fishing spot" + }, + { + "id": "406", + "name": "Fishing spot" + }, + { + "id": "409", + "name": "Genie" + }, + { + "id": "410", + "name": "Mysterious Old Man" + }, + { + "id": "431", + "name": "Cyrisus" + }, + { + "id": "433", + "name": "Cyrisus" + }, + { + "id": "434", + "name": "Cyrisus" + }, + { + "id": "436", + "name": "Fallen Man" + }, + { + "id": "463", + "name": "Murphy" + }, + { + "id": "464", + "name": "Murphy" + }, + { + "id": "465", + "name": "Murphy" + }, + { + "id": "466", + "name": "Murphy" + }, + { + "id": "467", + "name": "Shark" + }, + { + "id": "468", + "name": "Shark" + }, + { + "id": "471", + "name": "Bolkoy" + }, + { + "id": "472", + "name": "Remsai" + }, + { + "id": "473", + "name": "Khazard trooper" + }, + { + "id": "480", + "name": "Gnome troop" + }, + { + "id": "484", + "name": "Local Gnome" + }, + { + "id": "486", + "name": "Kalron" + }, + { + "id": "488", + "name": "Observatory professor" + }, + { + "id": "510", + "name": "Hajedy" + }, + { + "id": "511", + "name": "Vigroy" + }, + { + "id": "513", + "name": "Yohnus" + }, + { + "id": "514", + "name": "Seravel" + }, + { + "id": "536", + "name": "Valaine" + }, + { + "id": "537", + "name": "Scavvo" + }, + { + "id": "553", + "name": "Aubury" + }, + { + "id": "560", + "name": "Jiminua" + }, + { + "id": "563", + "name": "Arhein" + }, + { + "id": "565", + "name": "Lunderwin" + }, + { + "id": "568", + "name": "Zambo" + }, + { + "id": "575", + "name": "Hickton" + }, + { + "id": "576", + "name": "Harry" + }, + { + "id": "578", + "name": "Frincos" + }, + { + "id": "584", + "name": "Herquin" + }, + { + "id": "585", + "name": "Rommik" + }, + { + "id": "588", + "name": "Davon" + }, + { + "id": "589", + "name": "Zenesha" + }, + { + "id": "590", + "name": "Aemad" + }, + { + "id": "591", + "name": "Kortan" + }, + { + "id": "592", + "name": "Roachey" + }, + { + "id": "593", + "name": "Frenita" + }, + { + "id": "594", + "name": "Nurmof" + }, + { + "id": "597", + "name": "Noterazzo" + }, + { + "id": "600", + "name": "Hudo" + }, + { + "id": "601", + "name": "Rometti" + }, + { + "id": "602", + "name": "Gulluck" + }, + { + "id": "603", + "name": "Heckel Funch" + }, + { + "id": "607", + "name": "Gunnjorn" + }, + { + "id": "608", + "name": "Sir Amik Varze" + }, + { + "id": "612", + "name": "Greldo" + }, + { + "id": "622", + "name": "Gnome baller" + }, + { + "id": "623", + "name": "Gnome baller" + }, + { + "id": "624", + "name": "Gnome baller" + }, + { + "id": "625", + "name": "Gnome baller" + }, + { + "id": "626", + "name": "Gnome baller" + }, + { + "id": "627", + "name": "Gnome baller" + }, + { + "id": "628", + "name": "Gnome baller" + }, + { + "id": "629", + "name": "Gnome baller" + }, + { + "id": "630", + "name": "Gnome baller" + }, + { + "id": "631", + "name": "Gnome baller" + }, + { + "id": "632", + "name": "Gnome baller" + }, + { + "id": "634", + "name": "Gnome winger" + }, + { + "id": "636", + "name": "Cheerleader" + }, + { + "id": "642", + "name": "Katrine" + }, + { + "id": "644", + "name": "Straven" + }, + { + "id": "647", + "name": "King Roald" + }, + { + "id": "653", + "name": "Fairy Queen" + }, + { + "id": "654", + "name": "Shamus" + }, + { + "id": "661", + "name": "Megan" + }, + { + "id": "662", + "name": "Lucy" + }, + { + "id": "664", + "name": "Boot" + }, + { + "id": "666", + "name": "Caleb" + }, + { + "id": "668", + "name": "Johnathon" + }, + { + "id": "669", + "name": "Hazelmere" + }, + { + "id": "671", + "name": "Glough" + }, + { + "id": "672", + "name": "Anita" + }, + { + "id": "673", + "name": "Charlie" + }, + { + "id": "675", + "name": "Shipyard worker" + }, + { + "id": "676", + "name": "Femi" + }, + { + "id": "685", + "name": "Tower Advisor" + }, + { + "id": "686", + "name": "Tower Advisor" + }, + { + "id": "687", + "name": "Tower Advisor" + }, + { + "id": "693", + "name": "Competition Judge" + }, + { + "id": "695", + "name": "Bailey" + }, + { + "id": "697", + "name": "Holgart" + }, + { + "id": "699", + "name": "Holgart" + }, + { + "id": "700", + "name": "Holgart" + }, + { + "id": "701", + "name": "Kent" + }, + { + "id": "702", + "name": "Fisherman" + }, + { + "id": "703", + "name": "Fisherman" + }, + { + "id": "704", + "name": "Fisherman" + }, + { + "id": "710", + "name": "Alrena" + }, + { + "id": "711", + "name": "Bravek" + }, + { + "id": "712", + "name": "Carla" + }, + { + "id": "721", + "name": "Ted Rehnison" + }, + { + "id": "722", + "name": "Martha Rehnison" + }, + { + "id": "723", + "name": "Billy Rehnison" + }, + { + "id": "724", + "name": "Milli Rehnison" + }, + { + "id": "725", + "name": "Jethick" + }, + { + "id": "740", + "name": "Trufitus" + }, + { + "id": "746", + "name": "Oracle" + }, + { + "id": "748", + "name": "Angry barbarian spirit" + }, + { + "id": "754", + "name": "Peaceful barbarian spirit" + }, + { + "id": "759", + "name": "Kittens" + }, + { + "id": "761", + "name": "Kitten" + }, + { + "id": "762", + "name": "Kitten" + }, + { + "id": "763", + "name": "Kitten" + }, + { + "id": "764", + "name": "Kitten" + }, + { + "id": "765", + "name": "Kitten" + }, + { + "id": "766", + "name": "Kitten" + }, + { + "id": "768", + "name": "Cat" + }, + { + "id": "769", + "name": "Cat" + }, + { + "id": "770", + "name": "Cat" + }, + { + "id": "771", + "name": "Cat" + }, + { + "id": "772", + "name": "Cat" + }, + { + "id": "773", + "name": "Cat" + }, + { + "id": "774", + "name": "Overgrown cat" + }, + { + "id": "775", + "name": "Overgrown cat" + }, + { + "id": "776", + "name": "Overgrown cat" + }, + { + "id": "777", + "name": "Overgrown cat" + }, + { + "id": "779", + "name": "Overgrown cat" + }, + { + "id": "780", + "name": "Gertrude" + }, + { + "id": "782", + "name": "Philop" + }, + { + "id": "784", + "name": "Kanel" + }, + { + "id": "788", + "name": "Garv" + }, + { + "id": "789", + "name": "Grubor" + }, + { + "id": "791", + "name": "Seth" + }, + { + "id": "792", + "name": "Grip" + }, + { + "id": "797", + "name": "Helemos" + }, + { + "id": "807", + "name": "Pierre" + }, + { + "id": "808", + "name": "Hobbes" + }, + { + "id": "809", + "name": "Louisa" + }, + { + "id": "810", + "name": "Mary" + }, + { + "id": "811", + "name": "Stanford" + }, + { + "id": "814", + "name": "Anna" + }, + { + "id": "815", + "name": "Bob" + }, + { + "id": "816", + "name": "Carol" + }, + { + "id": "817", + "name": "David" + }, + { + "id": "818", + "name": "Elizabeth" + }, + { + "id": "819", + "name": "Frank" + }, + { + "id": "822", + "name": "Ana" + }, + { + "id": "823", + "name": "Ana" + }, + { + "id": "824", + "name": "Female slave" + }, + { + "id": "826", + "name": "Escaping slave" + }, + { + "id": "828", + "name": "Shanty Claws" + }, + { + "id": "829", + "name": "Mercenary Captain" + }, + { + "id": "832", + "name": "Al Shabim" + }, + { + "id": "844", + "name": "Horacio" + }, + { + "id": "846", + "name": "Kangai Mau" + }, + { + "id": "848", + "name": "Blurberry" + }, + { + "id": "849", + "name": "Barman" + }, + { + "id": "853", + "name": "Og" + }, + { + "id": "854", + "name": "Grew" + }, + { + "id": "855", + "name": "Toban" + }, + { + "id": "857", + "name": "Ogre guard" + }, + { + "id": "860", + "name": "Ogre guard" + }, + { + "id": "861", + "name": "Ogre guard" + }, + { + "id": "865", + "name": "Skavid" + }, + { + "id": "866", + "name": "Skavid" + }, + { + "id": "867", + "name": "Skavid" + }, + { + "id": "868", + "name": "Skavid" + }, + { + "id": "869", + "name": "Skavid" + }, + { + "id": "871", + "name": "Watchtower Wizard" + }, + { + "id": "876", + "name": "Ogre trader" + }, + { + "id": "880", + "name": "Weakened Delrith" + }, + { + "id": "886", + "name": "Claus the chef" + }, + { + "id": "888", + "name": "Philipe Carnillean" + }, + { + "id": "889", + "name": "Henryeta Carnillean" + }, + { + "id": "890", + "name": "Butler Jones" + }, + { + "id": "891", + "name": "Alomone" + }, + { + "id": "892", + "name": "Hazeel" + }, + { + "id": "896", + "name": "Nora T. Hagg" + }, + { + "id": "901", + "name": "Mouse" + }, + { + "id": "902", + "name": "Gundai" + }, + { + "id": "903", + "name": "Lundail" + }, + { + "id": "906", + "name": "Kolodion" + }, + { + "id": "918", + "name": "Ned" + }, + { + "id": "921", + "name": "Prince Ali" + }, + { + "id": "926", + "name": "Border Guard" + }, + { + "id": "927", + "name": "Fishing spot" + }, + { + "id": "928", + "name": "Gujuo" + }, + { + "id": "929", + "name": "Ungadulu" + }, + { + "id": "930", + "name": "Ungadulu" + }, + { + "id": "933", + "name": "Siegfried Erkle" + }, + { + "id": "935", + "name": "Viyeldi" + }, + { + "id": "936", + "name": "San Tojalon" + }, + { + "id": "937", + "name": "Irvig Senay" + }, + { + "id": "940", + "name": "Echned Zekin" + }, + { + "id": "952", + "name": "Fishing spot" + }, + { + "id": "953", + "name": "Banker" + }, + { + "id": "992", + "name": "Kardia" + }, + { + "id": "994", + "name": "Niloof" + }, + { + "id": "1003", + "name": "Lord Iban" + }, + { + "id": "1008", + "name": "Hamid" + }, + { + "id": "1011", + "name": "Fycie" + }, + { + "id": "1012", + "name": "Bugs" + }, + { + "id": "1014", + "name": "Bloated Toad" + }, + { + "id": "1016", + "name": "Chompy bird" + }, + { + "id": "1024", + "name": "Baby impling" + }, + { + "id": "1036", + "name": "Banker" + }, + { + "id": "1038", + "name": "Rufus" + }, + { + "id": "1039", + "name": "Barker" + }, + { + "id": "1040", + "name": "Fidelio" + }, + { + "id": "1041", + "name": "Sbott" + }, + { + "id": "1042", + "name": "Roavar" + }, + { + "id": "1043", + "name": "Will o' the wisp" + }, + { + "id": "1047", + "name": "Drezel" + }, + { + "id": "1056", + "name": "Mime" + }, + { + "id": "1070", + "name": "Saba" + }, + { + "id": "1071", + "name": "Tenzing" + }, + { + "id": "1075", + "name": "Archer" + }, + { + "id": "1091", + "name": "Bob" + }, + { + "id": "1093", + "name": "Billy" + }, + { + "id": "1094", + "name": "Mountain goat" + }, + { + "id": "1113", + "name": "Eadgar" + }, + { + "id": "1114", + "name": "Godric" + }, + { + "id": "1159", + "name": "Kalphite Queen" + }, + { + "id": "1162", + "name": "Timfraku" + }, + { + "id": "1163", + "name": "Tiadeche" + }, + { + "id": "1164", + "name": "Tiadeche" + }, + { + "id": "1165", + "name": "Tinsay" + }, + { + "id": "1166", + "name": "Tinsay" + }, + { + "id": "1167", + "name": "Tamayu" + }, + { + "id": "1168", + "name": "Tamayu" + }, + { + "id": "1169", + "name": "Tamayu" + }, + { + "id": "1170", + "name": "Tamayu" + }, + { + "id": "1171", + "name": "Lubufu" + }, + { + "id": "1173", + "name": "The Shaikahan" + }, + { + "id": "1174", + "name": "Fishing spot" + }, + { + "id": "1175", + "name": "Fishing spot" + }, + { + "id": "1177", + "name": "Fishing spot" + }, + { + "id": "1178", + "name": "Fishing spot" + }, + { + "id": "1180", + "name": "Cormorant" + }, + { + "id": "1181", + "name": "Pelican" + }, + { + "id": "1182", + "name": "Lord Iorwerth" + }, + { + "id": "1186", + "name": "Idris" + }, + { + "id": "1187", + "name": "Essyllt" + }, + { + "id": "1188", + "name": "Morvran" + }, + { + "id": "1189", + "name": "Fishing spot" + }, + { + "id": "1190", + "name": "Fishing spot" + }, + { + "id": "1191", + "name": "Fishing spot" + }, + { + "id": "1202", + "name": "Arianwyn" + }, + { + "id": "1205", + "name": "Tyras guard" + }, + { + "id": "1207", + "name": "Quartermaster" + }, + { + "id": "1221", + "name": "Spider" + }, + { + "id": "1222", + "name": "Mist" + }, + { + "id": "1224", + "name": "Vampyric hound" + }, + { + "id": "1226", + "name": "Tree" + }, + { + "id": "1236", + "name": "Fishing spot" + }, + { + "id": "1237", + "name": "Fishing spot" + }, + { + "id": "1238", + "name": "Fishing spot" + }, + { + "id": "1242", + "name": "Shade Spirit" + }, + { + "id": "1251", + "name": "Afflicted(Ulsquire)" + }, + { + "id": "1252", + "name": "Ulsquire Shauncy" + }, + { + "id": "1253", + "name": "Afflicted(Razmire)" + }, + { + "id": "1254", + "name": "Razmire Keelgan" + }, + { + "id": "1255", + "name": "Mort'ton Local" + }, + { + "id": "1256", + "name": "Mort'ton Local" + }, + { + "id": "1259", + "name": "Mort'ton local" + }, + { + "id": "1260", + "name": "Mort'ton local" + }, + { + "id": "1280", + "name": "Butterfly" + }, + { + "id": "1284", + "name": "Bjorn" + }, + { + "id": "1285", + "name": "Eldgrim" + }, + { + "id": "1295", + "name": "Askeladden" + }, + { + "id": "1299", + "name": "Town Guard" + }, + { + "id": "1310", + "name": "Freygerd" + }, + { + "id": "1311", + "name": "Lensa" + }, + { + "id": "1312", + "name": "Jennella" + }, + { + "id": "1322", + "name": "Gull" + }, + { + "id": "1323", + "name": "Gull" + }, + { + "id": "1324", + "name": "Gull" + }, + { + "id": "1325", + "name": "Gull" + }, + { + "id": "1331", + "name": "Fishing spot" + }, + { + "id": "1332", + "name": "Fishing spot" + }, + { + "id": "1333", + "name": "Fishing spot" + }, + { + "id": "1334", + "name": "Jossik" + }, + { + "id": "1335", + "name": "Jossik" + }, + { + "id": "1336", + "name": "Larrissa" + }, + { + "id": "1337", + "name": "Larrissa" + }, + { + "id": "1348", + "name": "Dagannoth mother" + }, + { + "id": "1349", + "name": "Dagannoth mother" + }, + { + "id": "1350", + "name": "Dagannoth mother" + }, + { + "id": "1359", + "name": "Queen Sigrid" + }, + { + "id": "1361", + "name": "Arnor" + }, + { + "id": "1362", + "name": "Haming" + }, + { + "id": "1363", + "name": "Moldof" + }, + { + "id": "1364", + "name": "Helga" + }, + { + "id": "1365", + "name": "Matilda" + }, + { + "id": "1366", + "name": "Ashild" + }, + { + "id": "1371", + "name": "Prince Brand" + }, + { + "id": "1372", + "name": "Princess Astrid" + }, + { + "id": "1373", + "name": "King Vargas" + }, + { + "id": "1375", + "name": "Advisor Ghrim" + }, + { + "id": "1383", + "name": "Halla" + }, + { + "id": "1384", + "name": "Yrsa" + }, + { + "id": "1387", + "name": "Thora" + }, + { + "id": "1399", + "name": "Fishing spot" + }, + { + "id": "1400", + "name": "Gull" + }, + { + "id": "1405", + "name": "Fishing spot" + }, + { + "id": "1406", + "name": "Fishing spot" + }, + { + "id": "1407", + "name": "Daero" + }, + { + "id": "1408", + "name": "Waydar" + }, + { + "id": "1409", + "name": "Waydar" + }, + { + "id": "1410", + "name": "Waydar" + }, + { + "id": "1411", + "name": "Garkor" + }, + { + "id": "1412", + "name": "Garkor" + }, + { + "id": "1413", + "name": "Lumo" + }, + { + "id": "1414", + "name": "Lumo" + }, + { + "id": "1415", + "name": "Bunkdo" + }, + { + "id": "1416", + "name": "Bunkdo" + }, + { + "id": "1417", + "name": "Carado" + }, + { + "id": "1418", + "name": "Carado" + }, + { + "id": "1420", + "name": "Karam" + }, + { + "id": "1421", + "name": "Karam" + }, + { + "id": "1422", + "name": "Karam" + }, + { + "id": "1423", + "name": "Bunkwicket" + }, + { + "id": "1424", + "name": "Waymottin" + }, + { + "id": "1425", + "name": "Zooknock" + }, + { + "id": "1426", + "name": "Zooknock" + }, + { + "id": "1428", + "name": "G.L.O. Caranock" + }, + { + "id": "1429", + "name": "Dugopul" + }, + { + "id": "1430", + "name": "Salenab" + }, + { + "id": "1431", + "name": "Trefaji" + }, + { + "id": "1432", + "name": "Aberab" + }, + { + "id": "1433", + "name": "Solihib" + }, + { + "id": "1434", + "name": "Daga" + }, + { + "id": "1435", + "name": "Tutab" + }, + { + "id": "1436", + "name": "Ifaba" + }, + { + "id": "1437", + "name": "Hamab" + }, + { + "id": "1438", + "name": "Hafuba" + }, + { + "id": "1439", + "name": "Denadu" + }, + { + "id": "1440", + "name": "Lofu" + }, + { + "id": "1441", + "name": "Kruk" + }, + { + "id": "1448", + "name": "Awowogei" + }, + { + "id": "1449", + "name": "Uwogo" + }, + { + "id": "1450", + "name": "Muruwoi" + }, + { + "id": "1462", + "name": "Elder Guard" + }, + { + "id": "1468", + "name": "Bonzara" + }, + { + "id": "1470", + "name": "Foreman" + }, + { + "id": "1474", + "name": "Spider" + }, + { + "id": "1482", + "name": "Gorilla" + }, + { + "id": "1488", + "name": "Dummy" + }, + { + "id": "1489", + "name": "Dummy" + }, + { + "id": "1490", + "name": "Dummy" + }, + { + "id": "1491", + "name": "Dummy" + }, + { + "id": "1492", + "name": "Dummy" + }, + { + "id": "1493", + "name": "Dummy" + }, + { + "id": "1494", + "name": "Dummy" + }, + { + "id": "1495", + "name": "Dummy" + }, + { + "id": "1496", + "name": "Dummy" + }, + { + "id": "1497", + "name": "Dummy" + }, + { + "id": "1498", + "name": "Dummy" + }, + { + "id": "1499", + "name": "Dummy" + }, + { + "id": "1500", + "name": "Dummy" + }, + { + "id": "1501", + "name": "Dummy" + }, + { + "id": "1502", + "name": "Dummy" + }, + { + "id": "1503", + "name": "Dummy" + }, + { + "id": "1504", + "name": "Dummy" + }, + { + "id": "1505", + "name": "Dummy" + }, + { + "id": "1506", + "name": "Dummy" + }, + { + "id": "1507", + "name": "Dummy" + }, + { + "id": "1508", + "name": "Forester" + }, + { + "id": "1509", + "name": "Woman-at-arms" + }, + { + "id": "1510", + "name": "Apprentice" + }, + { + "id": "1511", + "name": "Ranger" + }, + { + "id": "1512", + "name": "Adventurer" + }, + { + "id": "1513", + "name": "Mage" + }, + { + "id": "1515", + "name": "Nail beast" + }, + { + "id": "1522", + "name": "Nail beast" + }, + { + "id": "1523", + "name": "Nail beast" + }, + { + "id": "1525", + "name": "Undead Lumberjack" + }, + { + "id": "1526", + "name": "Lanthus" + }, + { + "id": "1527", + "name": "Mine cart" + }, + { + "id": "1529", + "name": "Sheep" + }, + { + "id": "1530", + "name": "Rabbit" + }, + { + "id": "1542", + "name": "Loading crane" + }, + { + "id": "1543", + "name": "Innocent-looking key" + }, + { + "id": "1544", + "name": "Mine cart" + }, + { + "id": "1545", + "name": "Mine cart" + }, + { + "id": "1546", + "name": "Mine cart" + }, + { + "id": "1547", + "name": "Mine cart" + }, + { + "id": "1548", + "name": "Mine cart" + }, + { + "id": "1552", + "name": "Santa" + }, + { + "id": "1554", + "name": "Aga" + }, + { + "id": "1555", + "name": "Arrg" + }, + { + "id": "1559", + "name": "Ice wolf" + }, + { + "id": "1568", + "name": "Curpile Fyod" + }, + { + "id": "1569", + "name": "Veliaf Hurtz" + }, + { + "id": "1570", + "name": "Sani Piliu" + }, + { + "id": "1571", + "name": "Harold Evans" + }, + { + "id": "1572", + "name": "Radigad Ponfit" + }, + { + "id": "1573", + "name": "Polmafi Ferdygris" + }, + { + "id": "1574", + "name": "Ivan Strom" + }, + { + "id": "1575", + "name": "Skeleton Hellhound" + }, + { + "id": "1576", + "name": "Stranger" + }, + { + "id": "1577", + "name": "Vanstrom Klause" + }, + { + "id": "1578", + "name": "Mist" + }, + { + "id": "1579", + "name": "Vanstrom Klause" + }, + { + "id": "1580", + "name": "Vanstrom Klause" + }, + { + "id": "1581", + "name": "Vanstrom Klause" + }, + { + "id": "1595", + "name": "Saniboch" + }, + { + "id": "1596", + "name": "Vannaka" + }, + { + "id": "1599", + "name": "Cave crawler" + }, + { + "id": "1659", + "name": "Skullball" + }, + { + "id": "1664", + "name": "Agility Trainer" + }, + { + "id": "1666", + "name": "Dr Fenkenstrain" + }, + { + "id": "1671", + "name": "Fenkenstrain's Monster" + }, + { + "id": "1674", + "name": "Lord Rologarth" + }, + { + "id": "1679", + "name": "Eluned" + }, + { + "id": "1680", + "name": "Islwyn" + }, + { + "id": "1682", + "name": "Golrie" + }, + { + "id": "1683", + "name": "Velorina" + }, + { + "id": "1685", + "name": "Gravingas" + }, + { + "id": "1687", + "name": "Ak-Haranu" + }, + { + "id": "1689", + "name": "Undead cow" + }, + { + "id": "1694", + "name": "Robin" + }, + { + "id": "1709", + "name": "Johanhus Ulsbrecht" + }, + { + "id": "1719", + "name": "Tree" + }, + { + "id": "1720", + "name": "Tree" + }, + { + "id": "1721", + "name": "Tree" + }, + { + "id": "1722", + "name": "Dead tree" + }, + { + "id": "1723", + "name": "Dead tree" + }, + { + "id": "1724", + "name": "Dead tree" + }, + { + "id": "1725", + "name": "Dead tree" + }, + { + "id": "1726", + "name": "Dead tree" + }, + { + "id": "1727", + "name": "Dead tree" + }, + { + "id": "1728", + "name": "Dead tree" + }, + { + "id": "1729", + "name": "Dead tree" + }, + { + "id": "1730", + "name": "Dead tree" + }, + { + "id": "1731", + "name": "Dead tree" + }, + { + "id": "1732", + "name": "Dramen tree" + }, + { + "id": "1734", + "name": "Magic tree" + }, + { + "id": "1735", + "name": "Maple tree" + }, + { + "id": "1736", + "name": "Willow" + }, + { + "id": "1737", + "name": "Willow" + }, + { + "id": "1738", + "name": "Willow" + }, + { + "id": "1749", + "name": "Hollow tree" + }, + { + "id": "1750", + "name": "Hollow tree" + }, + { + "id": "1753", + "name": "Mounted terrorbird gnome" + }, + { + "id": "1756", + "name": "Crow" + }, + { + "id": "1762", + "name": "Sheep" + }, + { + "id": "1764", + "name": "Sheep" + }, + { + "id": "1765", + "name": "Sheep" + }, + { + "id": "1777", + "name": "Ilfeen" + }, + { + "id": "1778", + "name": "William" + }, + { + "id": "1779", + "name": "Ian" + }, + { + "id": "1780", + "name": "Larry" + }, + { + "id": "1781", + "name": "Darren" + }, + { + "id": "1782", + "name": "Edward" + }, + { + "id": "1784", + "name": "Neil" + }, + { + "id": "1786", + "name": "Simon" + }, + { + "id": "1787", + "name": "Sam" + }, + { + "id": "1788", + "name": "Lumdo" + }, + { + "id": "1789", + "name": "Bunkwicket" + }, + { + "id": "1790", + "name": "Waymottin" + }, + { + "id": "1791", + "name": "Jungle Tree" + }, + { + "id": "1792", + "name": "Jungle Tree" + }, + { + "id": "1793", + "name": "Tassie Slipcast" + }, + { + "id": "1798", + "name": "Phantuwti Fanstuwi Farsight" + }, + { + "id": "1799", + "name": "Tindel Marchant" + }, + { + "id": "1800", + "name": "Gnormadium Avlafrim" + }, + { + "id": "1801", + "name": "Petra Fiyed" + }, + { + "id": "1804", + "name": "Slagilith" + }, + { + "id": "1808", + "name": "Ragnar" + }, + { + "id": "1809", + "name": "Svidi" + }, + { + "id": "1810", + "name": "Jokul" + }, + { + "id": "1811", + "name": "The Kendal" + }, + { + "id": "1821", + "name": "Bald Headed Eagle" + }, + { + "id": "1826", + "name": "Zombie" + }, + { + "id": "1830", + "name": "Frog" + }, + { + "id": "1835", + "name": "Easter Bunny" + }, + { + "id": "1836", + "name": "Dondakan the Dwarf" + }, + { + "id": "1838", + "name": "Dondakan the Dwarf" + }, + { + "id": "1839", + "name": "Dondakan the Dwarf" + }, + { + "id": "1841", + "name": "Rolad" + }, + { + "id": "1845", + "name": "Dwarven Boatman" + }, + { + "id": "1847", + "name": "Miodvetnir" + }, + { + "id": "1848", + "name": "Dernu" + }, + { + "id": "1849", + "name": "Derni" + }, + { + "id": "1860", + "name": "Brian" + }, + { + "id": "1862", + "name": "Ali Morrisane" + }, + { + "id": "1869", + "name": "Ali the Mayor" + }, + { + "id": "1876", + "name": "Bandit Leader" + }, + { + "id": "1879", + "name": "Bandit" + }, + { + "id": "1881", + "name": "Bandit" + }, + { + "id": "1882", + "name": "Sir Palomedes" + }, + { + "id": "1883", + "name": "Sir Palomedes" + }, + { + "id": "1884", + "name": "Trobert" + }, + { + "id": "1887", + "name": "Villager" + }, + { + "id": "1889", + "name": "Villager" + }, + { + "id": "1890", + "name": "Villager" + }, + { + "id": "1891", + "name": "Villager" + }, + { + "id": "1893", + "name": "Villager" + }, + { + "id": "1894", + "name": "Villager" + }, + { + "id": "1895", + "name": "Villager" + }, + { + "id": "1897", + "name": "Villager" + }, + { + "id": "1898", + "name": "Villager" + }, + { + "id": "1899", + "name": "Menaphite Leader" + }, + { + "id": "1903", + "name": "Menaphite Thug" + }, + { + "id": "1907", + "name": "Broken clay golem" + }, + { + "id": "1909", + "name": "Damaged clay golem" + }, + { + "id": "1910", + "name": "Clay golem" + }, + { + "id": "1912", + "name": "Elissa" + }, + { + "id": "1922", + "name": "Eblis" + }, + { + "id": "1924", + "name": "Eblis" + }, + { + "id": "1927", + "name": "Bandit" + }, + { + "id": "1928", + "name": "Bandit" + }, + { + "id": "1929", + "name": "Bandit" + }, + { + "id": "1930", + "name": "Bandit" + }, + { + "id": "1932", + "name": "Troll child" + }, + { + "id": "1934", + "name": "Troll child" + }, + { + "id": "1943", + "name": "Ice block" + }, + { + "id": "1945", + "name": "Ice block" + }, + { + "id": "1957", + "name": "Mummy" + }, + { + "id": "1959", + "name": "Mummy" + }, + { + "id": "1960", + "name": "Mummy ashes" + }, + { + "id": "1966", + "name": "Mummy" + }, + { + "id": "1968", + "name": "Mummy" + }, + { + "id": "1970", + "name": "Azzanadra" + }, + { + "id": "1982", + "name": "Raetul" + }, + { + "id": "1983", + "name": "Siamun" + }, + { + "id": "1984", + "name": "High Priest" + }, + { + "id": "1987", + "name": "Priest" + }, + { + "id": "1989", + "name": "Priest" + }, + { + "id": "1990", + "name": "Sphinx" + }, + { + "id": "1992", + "name": "Neite" + }, + { + "id": "1996", + "name": "Vulture" + }, + { + "id": "2000", + "name": "Plague cow" + }, + { + "id": "2002", + "name": "Wanderer" + }, + { + "id": "2006", + "name": "Wanderer" + }, + { + "id": "2007", + "name": "Het" + }, + { + "id": "2008", + "name": "Apmeken" + }, + { + "id": "2009", + "name": "Scabaras" + }, + { + "id": "2010", + "name": "Crondis" + }, + { + "id": "2011", + "name": "Icthlarin" + }, + { + "id": "2013", + "name": "Klenter" + }, + { + "id": "2020", + "name": "Light creature" + }, + { + "id": "2022", + "name": "Light creature" + }, + { + "id": "2023", + "name": "Juna" + }, + { + "id": "2038", + "name": "Grish" + }, + { + "id": "2039", + "name": "Uglug Nar" + }, + { + "id": "2040", + "name": "Pilg" + }, + { + "id": "2041", + "name": "Grug" + }, + { + "id": "2042", + "name": "Ogre guard" + }, + { + "id": "2043", + "name": "Ogre guard" + }, + { + "id": "2059", + "name": "Zavistic Rarve" + }, + { + "id": "2061", + "name": "Sithik Ints" + }, + { + "id": "2062", + "name": "Sithik Ints" + }, + { + "id": "2063", + "name": "Gargh" + }, + { + "id": "2064", + "name": "Scarg" + }, + { + "id": "2065", + "name": "Gruh" + }, + { + "id": "2066", + "name": "Irwin Feaselbaum" + }, + { + "id": "2068", + "name": "Fishing spot" + }, + { + "id": "2079", + "name": "Sigmund" + }, + { + "id": "2083", + "name": "Sigmund" + }, + { + "id": "2084", + "name": "Mistag" + }, + { + "id": "2085", + "name": "Kazgar" + }, + { + "id": "2087", + "name": "Ur-tag" + }, + { + "id": "2088", + "name": "Duke Horacio" + }, + { + "id": "2089", + "name": "Mistag" + }, + { + "id": "2090", + "name": "Sigmund" + }, + { + "id": "2099", + "name": "Red Axe Secretary" + }, + { + "id": "2107", + "name": "Red Axe Director" + }, + { + "id": "2108", + "name": "Red Axe Cat" + }, + { + "id": "2123", + "name": "Trader" + }, + { + "id": "2125", + "name": "Trader" + }, + { + "id": "2128", + "name": "Supreme Commander" + }, + { + "id": "2129", + "name": "Commander Veldaban" + }, + { + "id": "2137", + "name": "Gnome emissary" + }, + { + "id": "2142", + "name": "Riki the sculptor's model" + }, + { + "id": "2144", + "name": "Riki the sculptor's model" + }, + { + "id": "2145", + "name": "Riki the sculptor's model" + }, + { + "id": "2146", + "name": "Riki the sculptor's model" + }, + { + "id": "2147", + "name": "Riki the sculptor's model" + }, + { + "id": "2148", + "name": "Riki the sculptor's model" + }, + { + "id": "2149", + "name": "Riki the sculptor's model" + }, + { + "id": "2150", + "name": "Riki the sculptor's model" + }, + { + "id": "2151", + "name": "Vigr" + }, + { + "id": "2152", + "name": "Santiri" + }, + { + "id": "2153", + "name": "Saro" + }, + { + "id": "2155", + "name": "Wemund" + }, + { + "id": "2156", + "name": "Randivor" + }, + { + "id": "2157", + "name": "Hervi" + }, + { + "id": "2159", + "name": "Gulldamar" + }, + { + "id": "2161", + "name": "Agmundi" + }, + { + "id": "2162", + "name": "Vermundi" + }, + { + "id": "2166", + "name": "Assistant" + }, + { + "id": "2169", + "name": "Dromund" + }, + { + "id": "2176", + "name": "Inn Keeper" + }, + { + "id": "2179", + "name": "Barman" + }, + { + "id": "2188", + "name": "Hegir" + }, + { + "id": "2189", + "name": "Haera" + }, + { + "id": "2194", + "name": "Reinald" + }, + { + "id": "2196", + "name": "Gauss" + }, + { + "id": "2197", + "name": "Myndill" + }, + { + "id": "2199", + "name": "Tombar" + }, + { + "id": "2200", + "name": "Odmar" + }, + { + "id": "2204", + "name": "Drunken Dwarf" + }, + { + "id": "2208", + "name": "Dwarven Miner" + }, + { + "id": "2209", + "name": "Dwarven Miner" + }, + { + "id": "2210", + "name": "Dwarven Miner" + }, + { + "id": "2211", + "name": "Dwarven Miner" + }, + { + "id": "2212", + "name": "Dwarven Miner" + }, + { + "id": "2213", + "name": "Dwarven Miner" + }, + { + "id": "2214", + "name": "Dwarven Miner" + }, + { + "id": "2215", + "name": "Dwarven Miner" + }, + { + "id": "2216", + "name": "Dwarven Miner" + }, + { + "id": "2217", + "name": "Dwarven Miner" + }, + { + "id": "2218", + "name": "Dwarven Miner" + }, + { + "id": "2219", + "name": "Purple Pewter Director" + }, + { + "id": "2220", + "name": "Purple Pewter Director" + }, + { + "id": "2221", + "name": "Blue Opal Director" + }, + { + "id": "2222", + "name": "Yellow Fortune Director" + }, + { + "id": "2223", + "name": "Green Gemstone Director" + }, + { + "id": "2224", + "name": "White Chisel Director" + }, + { + "id": "2225", + "name": "Silver Cog Director" + }, + { + "id": "2226", + "name": "Brown Engine Director" + }, + { + "id": "2227", + "name": "Red Axe Director" + }, + { + "id": "2228", + "name": "Commander Veldaban" + }, + { + "id": "2229", + "name": "Red Axe Cat" + }, + { + "id": "2230", + "name": "Red Axe Cat" + }, + { + "id": "2231", + "name": "Black Guard Berserker" + }, + { + "id": "2233", + "name": "Olivia" + }, + { + "id": "2238", + "name": "Donie" + }, + { + "id": "2239", + "name": "Pig" + }, + { + "id": "2251", + "name": "Gnome" + }, + { + "id": "2252", + "name": "Crow" + }, + { + "id": "2254", + "name": "Bed" + }, + { + "id": "2255", + "name": "Thing under the bed" + }, + { + "id": "2257", + "name": "Mage of Zamorak" + }, + { + "id": "2259", + "name": "Mage of Zamorak" + }, + { + "id": "2260", + "name": "Mage of Zamorak" + }, + { + "id": "2266", + "name": "Brian O'Richard" + }, + { + "id": "2268", + "name": "Rogue Guard" + }, + { + "id": "2270", + "name": "Martin Thwait" + }, + { + "id": "2273", + "name": "Spin Blades" + }, + { + "id": "2295", + "name": "Rug Merchant" + }, + { + "id": "2297", + "name": "Rug Merchant" + }, + { + "id": "2299", + "name": "Rug Station Attendant" + }, + { + "id": "2302", + "name": "Sarah" + }, + { + "id": "2305", + "name": "Vanessa" + }, + { + "id": "2306", + "name": "Richard" + }, + { + "id": "2307", + "name": "Alice" + }, + { + "id": "2308", + "name": "Capt' Arnav" + }, + { + "id": "2322", + "name": "Metarialus" + }, + { + "id": "2345", + "name": "Sick-looking sheep (1)" + }, + { + "id": "2346", + "name": "Sick-looking sheep (2)" + }, + { + "id": "2347", + "name": "Sick-looking sheep (3)" + }, + { + "id": "2348", + "name": "Sick-looking sheep (4)" + }, + { + "id": "2349", + "name": "Mourner" + }, + { + "id": "2350", + "name": "Mourner" + }, + { + "id": "2351", + "name": "Mourner" + }, + { + "id": "2352", + "name": "Eudav" + }, + { + "id": "2353", + "name": "Oronwen" + }, + { + "id": "2356", + "name": "Dalldav" + }, + { + "id": "2357", + "name": "Gethin" + }, + { + "id": "2358", + "name": "Arianwyn" + }, + { + "id": "2363", + "name": "Goreu" + }, + { + "id": "2364", + "name": "Ysgawyn" + }, + { + "id": "2365", + "name": "Arvel" + }, + { + "id": "2366", + "name": "Mawrth" + }, + { + "id": "2367", + "name": "Kelyn" + }, + { + "id": "2368", + "name": "Eoin" + }, + { + "id": "2369", + "name": "Iona" + }, + { + "id": "2370", + "name": "Gnome" + }, + { + "id": "2375", + "name": "Eluned" + }, + { + "id": "2377", + "name": "Sick-looking sheep (1)" + }, + { + "id": "2378", + "name": "Sick-looking sheep (2)" + }, + { + "id": "2379", + "name": "Sick-looking sheep (3)" + }, + { + "id": "2380", + "name": "Sick-looking sheep (4)" + }, + { + "id": "2381", + "name": "Mysterious ghost" + }, + { + "id": "2403", + "name": "Cart conductor" + }, + { + "id": "2410", + "name": "Red Axe Director" + }, + { + "id": "2411", + "name": "Red Axe Director" + }, + { + "id": "2412", + "name": "Red Axe Henchman" + }, + { + "id": "2413", + "name": "Red Axe Henchman" + }, + { + "id": "2414", + "name": "Red Axe Henchman" + }, + { + "id": "2415", + "name": "Colonel Grimsson" + }, + { + "id": "2416", + "name": "Colonel Grimsson" + }, + { + "id": "2417", + "name": "Ogre shaman" + }, + { + "id": "2418", + "name": "Ogre shaman" + }, + { + "id": "2419", + "name": "Grunsh" + }, + { + "id": "2420", + "name": "Gnome emissary" + }, + { + "id": "2421", + "name": "Gnome companion" + }, + { + "id": "2422", + "name": "Gnome companion" + }, + { + "id": "2424", + "name": "Gunslik" + }, + { + "id": "2425", + "name": "Nolar" + }, + { + "id": "2426", + "name": "Factory Worker" + }, + { + "id": "2427", + "name": "Cart conductor" + }, + { + "id": "2428", + "name": "Gauss" + }, + { + "id": "2429", + "name": "Drunken Dwarf" + }, + { + "id": "2430", + "name": "Rowdy dwarf" + }, + { + "id": "2431", + "name": "Ulifed" + }, + { + "id": "2432", + "name": "Red Axe Henchman" + }, + { + "id": "2433", + "name": "Red Axe Henchman" + }, + { + "id": "2434", + "name": "Ogre shaman" + }, + { + "id": "2435", + "name": "Jarvald" + }, + { + "id": "2437", + "name": "Jarvald" + }, + { + "id": "2438", + "name": "Jarvald" + }, + { + "id": "2440", + "name": "Door-support" + }, + { + "id": "2441", + "name": "Door" + }, + { + "id": "2442", + "name": "Door" + }, + { + "id": "2444", + "name": "Door" + }, + { + "id": "2445", + "name": "Door" + }, + { + "id": "2446", + "name": "Door-support" + }, + { + "id": "2447", + "name": "Door" + }, + { + "id": "2448", + "name": "Door" + }, + { + "id": "2449", + "name": "Egg" + }, + { + "id": "2450", + "name": "Egg" + }, + { + "id": "2451", + "name": "Egg" + }, + { + "id": "2458", + "name": "Freaky Forester" + }, + { + "id": "2469", + "name": "Frog" + }, + { + "id": "2470", + "name": "Frog" + }, + { + "id": "2471", + "name": "Frog" + }, + { + "id": "2472", + "name": "Frog" + }, + { + "id": "2473", + "name": "Frog" + }, + { + "id": "2474", + "name": "Frog prince" + }, + { + "id": "2475", + "name": "Frog princess" + }, + { + "id": "2478", + "name": "Evil Bob" + }, + { + "id": "2480", + "name": "Servant" + }, + { + "id": "2483", + "name": "Bush snake" + }, + { + "id": "2498", + "name": "Broodoo victim" + }, + { + "id": "2500", + "name": "Broodoo victim" + }, + { + "id": "2502", + "name": "Broodoo victim" + }, + { + "id": "2504", + "name": "Sharimika" + }, + { + "id": "2507", + "name": "Mamma Bufetta" + }, + { + "id": "2510", + "name": "Layleen" + }, + { + "id": "2513", + "name": "Karaday" + }, + { + "id": "2516", + "name": "Safta Doc" + }, + { + "id": "2519", + "name": "Gabooty" + }, + { + "id": "2522", + "name": "Fanellaman" + }, + { + "id": "2525", + "name": "Jagbakoba" + }, + { + "id": "2528", + "name": "Murcaily" + }, + { + "id": "2531", + "name": "Rionasta" + }, + { + "id": "2534", + "name": "Mahogany" + }, + { + "id": "2535", + "name": "Teak" + }, + { + "id": "2536", + "name": "Niles" + }, + { + "id": "2537", + "name": "Miles" + }, + { + "id": "2538", + "name": "Giles" + }, + { + "id": "2540", + "name": "Dr Jekyll" + }, + { + "id": "2541", + "name": "Mr Hyde" + }, + { + "id": "2542", + "name": "Mr Hyde" + }, + { + "id": "2543", + "name": "Mr Hyde" + }, + { + "id": "2544", + "name": "Mr Hyde" + }, + { + "id": "2545", + "name": "Mr Hyde" + }, + { + "id": "2546", + "name": "Mr Hyde" + }, + { + "id": "2548", + "name": "Blackjack seller" + }, + { + "id": "2550", + "name": "Dwarven Miner" + }, + { + "id": "2551", + "name": "Dwarven Miner" + }, + { + "id": "2552", + "name": "Dwarven Miner" + }, + { + "id": "2554", + "name": "Tin ore" + }, + { + "id": "2555", + "name": "Copper ore" + }, + { + "id": "2556", + "name": "Iron ore" + }, + { + "id": "2557", + "name": "Mithril ore" + }, + { + "id": "2558", + "name": "Adamantite ore" + }, + { + "id": "2559", + "name": "Runite ore" + }, + { + "id": "2560", + "name": "Silver ore" + }, + { + "id": "2561", + "name": "Gold ore" + }, + { + "id": "2562", + "name": "Coal" + }, + { + "id": "2563", + "name": "Perfect gold ore" + }, + { + "id": "2566", + "name": "Wise Old Man" + }, + { + "id": "2567", + "name": "Wise Old Man" + }, + { + "id": "2568", + "name": "Banker" + }, + { + "id": "2569", + "name": "Banker" + }, + { + "id": "2570", + "name": "Banker" + }, + { + "id": "2573", + "name": "Pillory Guard" + }, + { + "id": "2575", + "name": "Purepker895" + }, + { + "id": "2576", + "name": "Qutiedoll" + }, + { + "id": "2577", + "name": "1337sp34kr" + }, + { + "id": "2578", + "name": "Elfinlocks" + }, + { + "id": "2579", + "name": "Cool Mom227" + }, + { + "id": "2581", + "name": "Ellamaria" + }, + { + "id": "2582", + "name": "Trolley" + }, + { + "id": "2583", + "name": "Trolley" + }, + { + "id": "2584", + "name": "Trolley" + }, + { + "id": "2585", + "name": "Billy, a guard of Falador" + }, + { + "id": "2587", + "name": "Bob, another guard of Falador" + }, + { + "id": "2589", + "name": "PKMaster0036" + }, + { + "id": "2590", + "name": "King Roald" + }, + { + "id": "2617", + "name": "TzHaar-Mej-Jal" + }, + { + "id": "2618", + "name": "TzHaar-Mej-Kah" + }, + { + "id": "2619", + "name": "TzHaar-Ket-Zuh" + }, + { + "id": "2620", + "name": "TzHaar-Hur-Tel" + }, + { + "id": "2622", + "name": "TzHaar-Hur-Lek" + }, + { + "id": "2623", + "name": "TzHaar-Mej-Roh" + }, + { + "id": "2624", + "name": "TzHaar-Ket" + }, + { + "id": "2625", + "name": "TzHaar-Ket" + }, + { + "id": "2626", + "name": "Rocks" + }, + { + "id": "2632", + "name": "Tok-Xil" + }, + { + "id": "2633", + "name": "Wise Old Man" + }, + { + "id": "2635", + "name": "Bob" + }, + { + "id": "2636", + "name": "Bob" + }, + { + "id": "2637", + "name": "Sphinx" + }, + { + "id": "2638", + "name": "Neite" + }, + { + "id": "2639", + "name": "Robert the Strong" + }, + { + "id": "2640", + "name": "Odysseus" + }, + { + "id": "2642", + "name": "King Black Dragon" + }, + { + "id": "2643", + "name": "R4ng3rNo0b889" + }, + { + "id": "2644", + "name": "Love Cats" + }, + { + "id": "2645", + "name": "Love Cats" + }, + { + "id": "2646", + "name": "Neite" + }, + { + "id": "2647", + "name": "Bob" + }, + { + "id": "2648", + "name": "Beite" + }, + { + "id": "2649", + "name": "Gnome" + }, + { + "id": "2650", + "name": "Gnome" + }, + { + "id": "2651", + "name": "Odysseus" + }, + { + "id": "2652", + "name": "Neite" + }, + { + "id": "2654", + "name": "Unferth" + }, + { + "id": "2656", + "name": "Unferth" + }, + { + "id": "2657", + "name": "Unferth" + }, + { + "id": "2658", + "name": "Unferth" + }, + { + "id": "2659", + "name": "Unferth" + }, + { + "id": "2661", + "name": "Reldo" + }, + { + "id": "2662", + "name": "Lazy cat" + }, + { + "id": "2663", + "name": "Lazy cat" + }, + { + "id": "2664", + "name": "Lazy cat" + }, + { + "id": "2665", + "name": "Lazy cat" + }, + { + "id": "2666", + "name": "Lazy cat" + }, + { + "id": "2667", + "name": "Lazy cat" + }, + { + "id": "2668", + "name": "Wily cat" + }, + { + "id": "2669", + "name": "Wily cat" + }, + { + "id": "2670", + "name": "Wily cat" + }, + { + "id": "2671", + "name": "Wily cat" + }, + { + "id": "2672", + "name": "Wily cat" + }, + { + "id": "2673", + "name": "Wily cat" + }, + { + "id": "2676", + "name": "Make-over Mage" + }, + { + "id": "2692", + "name": "Ahab" + }, + { + "id": "2708", + "name": "Seagull" + }, + { + "id": "2719", + "name": "Grum" + }, + { + "id": "2720", + "name": "Gerrant" + }, + { + "id": "2721", + "name": "Wydin" + }, + { + "id": "2722", + "name": "Fishing spot" + }, + { + "id": "2723", + "name": "Fishing spot" + }, + { + "id": "2724", + "name": "Fishing spot" + }, + { + "id": "2727", + "name": "Gull" + }, + { + "id": "2730", + "name": "Monk of Entrana" + }, + { + "id": "2747", + "name": "Solus Dellagar" + }, + { + "id": "2748", + "name": "Savant" + }, + { + "id": "2749", + "name": "Lord Daquarius" + }, + { + "id": "2750", + "name": "Solus Dellagar" + }, + { + "id": "2751", + "name": "Black Knight" + }, + { + "id": "2752", + "name": "Lord Daquarius" + }, + { + "id": "2753", + "name": "Mage of Zamorak" + }, + { + "id": "2754", + "name": "Mage of Zamorak" + }, + { + "id": "2755", + "name": "Mage of Zamorak" + }, + { + "id": "2756", + "name": "Woman" + }, + { + "id": "2777", + "name": "Black Knight" + }, + { + "id": "2778", + "name": "Black Knight" + }, + { + "id": "2780", + "name": "Solus Dellagar" + }, + { + "id": "2781", + "name": "Gnome guard" + }, + { + "id": "2788", + "name": "Thorgel" + }, + { + "id": "2791", + "name": "Pillory Guard" + }, + { + "id": "2793", + "name": "Tramp" + }, + { + "id": "2794", + "name": "Tramp" + }, + { + "id": "2795", + "name": "Skippy" + }, + { + "id": "2797", + "name": "Skippy" + }, + { + "id": "2798", + "name": "Skippy" + }, + { + "id": "2799", + "name": "Skippy" + }, + { + "id": "2800", + "name": "A pile of broken glass" + }, + { + "id": "2813", + "name": "Alice the Camel" + }, + { + "id": "2816", + "name": "Ali the Smith" + }, + { + "id": "2821", + "name": "Ali the Farmer" + }, + { + "id": "2822", + "name": "Ali the Tailor" + }, + { + "id": "2823", + "name": "Ali the Guard" + }, + { + "id": "2829", + "name": "Davey" + }, + { + "id": "2859", + "name": "Fishing spot" + }, + { + "id": "2862", + "name": "Death" + }, + { + "id": "2864", + "name": "Most of a Zombie" + }, + { + "id": "2865", + "name": "Most of a Zombie" + }, + { + "id": "2867", + "name": "Most of a Zombie" + }, + { + "id": "2868", + "name": "Zombie Head" + }, + { + "id": "2870", + "name": "Half-Zombie" + }, + { + "id": "2871", + "name": "Other Half-Zombie" + }, + { + "id": "2872", + "name": "Child" + }, + { + "id": "2873", + "name": "Child" + }, + { + "id": "2874", + "name": "Child" + }, + { + "id": "2875", + "name": "Child" + }, + { + "id": "2876", + "name": "Child" + }, + { + "id": "2877", + "name": "Child" + }, + { + "id": "2879", + "name": "Bardur" + }, + { + "id": "2884", + "name": "Wallasalki" + }, + { + "id": "2891", + "name": "Suspicious water" + }, + { + "id": "2893", + "name": "Suspicious water" + }, + { + "id": "2895", + "name": "Suspicious water" + }, + { + "id": "2897", + "name": "Father Reen" + }, + { + "id": "2900", + "name": "Father Reen" + }, + { + "id": "2901", + "name": "Father Badden" + }, + { + "id": "2903", + "name": "Father Badden" + }, + { + "id": "2904", + "name": "Denath" + }, + { + "id": "2905", + "name": "Denath" + }, + { + "id": "2906", + "name": "Eric" + }, + { + "id": "2907", + "name": "Eric" + }, + { + "id": "2908", + "name": "Evil Dave" + }, + { + "id": "2910", + "name": "Evil Dave" + }, + { + "id": "2911", + "name": "Matthew" + }, + { + "id": "2912", + "name": "Matthew" + }, + { + "id": "2913", + "name": "Jennifer" + }, + { + "id": "2914", + "name": "Jennifer" + }, + { + "id": "2915", + "name": "Tanya" + }, + { + "id": "2916", + "name": "Tanya" + }, + { + "id": "2917", + "name": "Patrick" + }, + { + "id": "2918", + "name": "Patrick" + }, + { + "id": "2920", + "name": "Sand storm" + }, + { + "id": "2922", + "name": "Clay golem" + }, + { + "id": "2928", + "name": "Clay golem" + }, + { + "id": "2929", + "name": "Ghost" + }, + { + "id": "2932", + "name": "Jorral" + }, + { + "id": "2933", + "name": "Melina" + }, + { + "id": "2935", + "name": "Melina" + }, + { + "id": "2936", + "name": "Droalak" + }, + { + "id": "2938", + "name": "Droalak" + }, + { + "id": "2939", + "name": "Dron" + }, + { + "id": "2940", + "name": "Blanin" + }, + { + "id": "2943", + "name": "Pox" + }, + { + "id": "2944", + "name": "Pox" + }, + { + "id": "2946", + "name": "Grimesquit" + }, + { + "id": "2947", + "name": "Phingspet" + }, + { + "id": "2951", + "name": "Felkrash" + }, + { + "id": "2953", + "name": "Ceril Carnillean" + }, + { + "id": "2954", + "name": "Councillor Halgrive" + }, + { + "id": "2955", + "name": "Spice seller" + }, + { + "id": "2956", + "name": "Fur trader" + }, + { + "id": "2957", + "name": "Gem merchant" + }, + { + "id": "2959", + "name": "Silk merchant" + }, + { + "id": "2960", + "name": "Zenesha" + }, + { + "id": "2961", + "name": "Ali Morrisane" + }, + { + "id": "2974", + "name": "Rat" + }, + { + "id": "2983", + "name": "Turbogroomer" + }, + { + "id": "2985", + "name": "Loki" + }, + { + "id": "2987", + "name": "Treacle" + }, + { + "id": "2989", + "name": "Claude" + }, + { + "id": "2991", + "name": "Rauborn" + }, + { + "id": "2992", + "name": "Vaeringk" + }, + { + "id": "2993", + "name": "Oxi" + }, + { + "id": "2994", + "name": "Fior" + }, + { + "id": "2995", + "name": "Sagira" + }, + { + "id": "2996", + "name": "Anleif" + }, + { + "id": "2999", + "name": "Gambler" + }, + { + "id": "3000", + "name": "Barman" + }, + { + "id": "3019", + "name": "Fishing spot" + }, + { + "id": "3020", + "name": "Rug Merchant" + }, + { + "id": "3023", + "name": "Nirrie" + }, + { + "id": "3024", + "name": "Tirrie" + }, + { + "id": "3025", + "name": "Hallak" + }, + { + "id": "3031", + "name": "Usi" + }, + { + "id": "3032", + "name": "Nkuku" + }, + { + "id": "3033", + "name": "Garai" + }, + { + "id": "3034", + "name": "Habibah" + }, + { + "id": "3035", + "name": "Meskhenet" + }, + { + "id": "3036", + "name": "Zahra" + }, + { + "id": "3037", + "name": "Zahur" + }, + { + "id": "3038", + "name": "Seddu" + }, + { + "id": "3039", + "name": "Kazemde" + }, + { + "id": "3041", + "name": "Tarik" + }, + { + "id": "3045", + "name": "Rokuh" + }, + { + "id": "3047", + "name": "Target" + }, + { + "id": "3048", + "name": "Target" + }, + { + "id": "3049", + "name": "Larxus" + }, + { + "id": "3076", + "name": "Dead Monk" + }, + { + "id": "3078", + "name": "High Priest" + }, + { + "id": "3081", + "name": "Assassin" + }, + { + "id": "3082", + "name": "Rosie" + }, + { + "id": "3083", + "name": "Sorcha" + }, + { + "id": "3084", + "name": "Cait" + }, + { + "id": "3085", + "name": "Cormac" + }, + { + "id": "3086", + "name": "Fionn" + }, + { + "id": "3087", + "name": "Donnacha" + }, + { + "id": "3088", + "name": "Ronan" + }, + { + "id": "3093", + "name": "Flying Book" + }, + { + "id": "3095", + "name": "Flying Book" + }, + { + "id": "3096", + "name": "Pizzaz Hat" + }, + { + "id": "3107", + "name": "Charmed Warrior" + }, + { + "id": "3108", + "name": "Bert" + }, + { + "id": "3110", + "name": "Sandy" + }, + { + "id": "3113", + "name": "Sandy" + }, + { + "id": "3114", + "name": "Mazion" + }, + { + "id": "3116", + "name": "Reeso" + }, + { + "id": "3118", + "name": "Prison Pete" + }, + { + "id": "3119", + "name": "Balloon Animal" + }, + { + "id": "3120", + "name": "Balloon Animal" + }, + { + "id": "3124", + "name": "Pyramid block" + }, + { + "id": "3125", + "name": "Pyramid block" + }, + { + "id": "3126", + "name": "Pentyn" + }, + { + "id": "3127", + "name": "Aristarchus" + }, + { + "id": "3128", + "name": "Boneguard" + }, + { + "id": "3130", + "name": "Pile of bones" + }, + { + "id": "3131", + "name": "Desert Spirit" + }, + { + "id": "3132", + "name": "Crust of ice" + }, + { + "id": "3134", + "name": "Furnace grate" + }, + { + "id": "3136", + "name": "Enakhra" + }, + { + "id": "3138", + "name": "Enakhra" + }, + { + "id": "3139", + "name": "Boneguard" + }, + { + "id": "3141", + "name": "Akthanakos" + }, + { + "id": "3142", + "name": "Akthanakos" + }, + { + "id": "3143", + "name": "Lazim" + }, + { + "id": "3148", + "name": "Enakhra" + }, + { + "id": "3149", + "name": "Akthanakos" + }, + { + "id": "3152", + "name": "Harpie Bug Swarm" + }, + { + "id": "3154", + "name": "Count Draynor" + }, + { + "id": "3156", + "name": "Bill Teach" + }, + { + "id": "3157", + "name": "Bill Teach" + }, + { + "id": "3158", + "name": "Bill Teach" + }, + { + "id": "3159", + "name": "Bill Teach" + }, + { + "id": "3160", + "name": "Bill Teach" + }, + { + "id": "3161", + "name": "Charley" + }, + { + "id": "3162", + "name": "Smith" + }, + { + "id": "3163", + "name": "Joe" + }, + { + "id": "3164", + "name": "Mama" + }, + { + "id": "3165", + "name": "Mama" + }, + { + "id": "3197", + "name": "Gull" + }, + { + "id": "3205", + "name": "Romily Weaklax" + }, + { + "id": "3206", + "name": "Priest" + }, + { + "id": "3207", + "name": "Pious Pete" + }, + { + "id": "3208", + "name": "Taper" + }, + { + "id": "3210", + "name": "Alrena" + }, + { + "id": "3211", + "name": "Alrena" + }, + { + "id": "3212", + "name": "Bravek" + }, + { + "id": "3218", + "name": "Tina" + }, + { + "id": "3254", + "name": "Hunding" + }, + { + "id": "3281", + "name": "Engineering assistant" + }, + { + "id": "3284", + "name": "Squirrel" + }, + { + "id": "3285", + "name": "Squirrel" + }, + { + "id": "3287", + "name": "Raccoon" + }, + { + "id": "3289", + "name": "Skeleton" + }, + { + "id": "3292", + "name": "Witch" + }, + { + "id": "3300", + "name": "Frog" + }, + { + "id": "3301", + "name": "Storm cloud" + }, + { + "id": "3303", + "name": "Fairy Nuff" + }, + { + "id": "3305", + "name": "Slim Louie" + }, + { + "id": "3306", + "name": "Fat Rocco" + }, + { + "id": "3308", + "name": "Zandar Horfyre" + }, + { + "id": "3311", + "name": "Sheep" + }, + { + "id": "3312", + "name": "Zanaris choir" + }, + { + "id": "3314", + "name": "Baby tanglefoot" + }, + { + "id": "3321", + "name": "Gatekeeper" + }, + { + "id": "3323", + "name": "Draul Leptoc" + }, + { + "id": "3326", + "name": "Martina Scorsby" + }, + { + "id": "3328", + "name": "Tarquin" + }, + { + "id": "3329", + "name": "Sigurd" + }, + { + "id": "3330", + "name": "Hari" + }, + { + "id": "3332", + "name": "Trees" + }, + { + "id": "3333", + "name": "Trees" + }, + { + "id": "3335", + "name": "Bullrush" + }, + { + "id": "3336", + "name": "Bullrush" + }, + { + "id": "3337", + "name": "Cave scenery" + }, + { + "id": "3338", + "name": "Cave scenery" + }, + { + "id": "3339", + "name": "Cave scenery" + }, + { + "id": "3351", + "name": "Genie" + }, + { + "id": "3352", + "name": "Mysterious Old Man" + }, + { + "id": "3353", + "name": "Swarm" + }, + { + "id": "3354", + "name": "Cap'n Hand" + }, + { + "id": "3355", + "name": "Rick Turpentine" + }, + { + "id": "3356", + "name": "Niles" + }, + { + "id": "3357", + "name": "Miles" + }, + { + "id": "3358", + "name": "Giles" + }, + { + "id": "3359", + "name": "Dr Jekyll" + }, + { + "id": "3360", + "name": "Mr Hyde" + }, + { + "id": "3361", + "name": "Mr Hyde" + }, + { + "id": "3362", + "name": "Mr Hyde" + }, + { + "id": "3363", + "name": "Mr Hyde" + }, + { + "id": "3364", + "name": "Mr Hyde" + }, + { + "id": "3365", + "name": "Mr Hyde" + }, + { + "id": "3372", + "name": "Sir Amik Varze" + }, + { + "id": "3373", + "name": "Sir Amik Varze" + }, + { + "id": "3377", + "name": "K'klik" + }, + { + "id": "3379", + "name": "Evil Dave" + }, + { + "id": "3381", + "name": "Doris" + }, + { + "id": "3383", + "name": "Gypsy" + }, + { + "id": "3386", + "name": "Gypsy" + }, + { + "id": "3387", + "name": "Culinaromancer" + }, + { + "id": "3388", + "name": "Osman" + }, + { + "id": "3395", + "name": "Sir Amik Varze" + }, + { + "id": "3396", + "name": "Awowogei" + }, + { + "id": "3397", + "name": "Awowogei" + }, + { + "id": "3398", + "name": "Skrach Uglogwee" + }, + { + "id": "3399", + "name": "Culinaromancer" + }, + { + "id": "3401", + "name": "An old Dwarf" + }, + { + "id": "3403", + "name": "Rohak" + }, + { + "id": "3417", + "name": "Pirate Pete" + }, + { + "id": "3428", + "name": "Fish" + }, + { + "id": "3429", + "name": "Fish" + }, + { + "id": "3430", + "name": "Fish" + }, + { + "id": "3440", + "name": "Fish" + }, + { + "id": "3441", + "name": "Fish" + }, + { + "id": "3442", + "name": "Fish" + }, + { + "id": "3446", + "name": "Fish" + }, + { + "id": "3447", + "name": "Fish" + }, + { + "id": "3448", + "name": "Fish" + }, + { + "id": "3452", + "name": "? ? ? ?" + }, + { + "id": "3453", + "name": "? ? ? ?" + }, + { + "id": "3454", + "name": "? ? ? ?" + }, + { + "id": "3455", + "name": "? ? ? ?" + }, + { + "id": "3456", + "name": "? ? ? ?" + }, + { + "id": "3457", + "name": "? ? ? ?" + }, + { + "id": "3458", + "name": "? ? ? ?" + }, + { + "id": "3459", + "name": "? ? ? ?" + }, + { + "id": "3460", + "name": "? ? ? ?" + }, + { + "id": "3461", + "name": "? ? ? ?" + }, + { + "id": "3462", + "name": "Skrach Uglogwee" + }, + { + "id": "3464", + "name": "Skrach Uglogwee" + }, + { + "id": "3465", + "name": "Nung" + }, + { + "id": "3466", + "name": "Ogre" + }, + { + "id": "3467", + "name": "Rantz" + }, + { + "id": "3468", + "name": "Rantz" + }, + { + "id": "3469", + "name": "Ogre boat" + }, + { + "id": "3472", + "name": "Ogre boat" + }, + { + "id": "3473", + "name": "Balloon Toad" + }, + { + "id": "3474", + "name": "Balloon Toad" + }, + { + "id": "3475", + "name": "Balloon Toad" + }, + { + "id": "3477", + "name": "Jubbly bird" + }, + { + "id": "3479", + "name": "King Awowogei" + }, + { + "id": "3481", + "name": "Mizaru" + }, + { + "id": "3482", + "name": "Kikazaru" + }, + { + "id": "3483", + "name": "Iwazaru" + }, + { + "id": "3485", + "name": "Culinaromancer" + }, + { + "id": "3486", + "name": "Culinaromancer" + }, + { + "id": "3487", + "name": "Culinaromancer" + }, + { + "id": "3488", + "name": "Culinaromancer" + }, + { + "id": "3489", + "name": "Culinaromancer" + }, + { + "id": "3490", + "name": "Culinaromancer" + }, + { + "id": "3492", + "name": "Culinaromancer" + }, + { + "id": "3503", + "name": "Overgrown hellcat" + }, + { + "id": "3504", + "name": "Hellcat" + }, + { + "id": "3505", + "name": "Hell-kitten" + }, + { + "id": "3506", + "name": "Lazy hellcat" + }, + { + "id": "3507", + "name": "Wily hellcat" + }, + { + "id": "3508", + "name": "Leo" + }, + { + "id": "3510", + "name": "Wiskit" + }, + { + "id": "3512", + "name": "Vampyre Juvinate" + }, + { + "id": "3515", + "name": "Vampyre Juvinate" + }, + { + "id": "3516", + "name": "Gadderanks" + }, + { + "id": "3518", + "name": "Gadderanks" + }, + { + "id": "3519", + "name": "Gadderanks" + }, + { + "id": "3520", + "name": "Vampyre Juvinate" + }, + { + "id": "3528", + "name": "Vampyre Juvinate" + }, + { + "id": "3529", + "name": "Vampyre Juvinate" + }, + { + "id": "3530", + "name": "Mist" + }, + { + "id": "3535", + "name": "Ivan Strom" + }, + { + "id": "3536", + "name": "Ivan Strom" + }, + { + "id": "3537", + "name": "Vampyre Juvinate" + }, + { + "id": "3538", + "name": "Vampyre Juvinate" + }, + { + "id": "3539", + "name": "Veliaf Hurtz" + }, + { + "id": "3540", + "name": "Elisabeta" + }, + { + "id": "3541", + "name": "Aurel" + }, + { + "id": "3542", + "name": "Sorin" + }, + { + "id": "3543", + "name": "Luscion" + }, + { + "id": "3544", + "name": "Sergiu" + }, + { + "id": "3545", + "name": "Radu" + }, + { + "id": "3546", + "name": "Grigore" + }, + { + "id": "3547", + "name": "Ileana" + }, + { + "id": "3548", + "name": "Valeria" + }, + { + "id": "3549", + "name": "Emilia" + }, + { + "id": "3550", + "name": "Florin" + }, + { + "id": "3551", + "name": "Catalina" + }, + { + "id": "3552", + "name": "Ivan" + }, + { + "id": "3553", + "name": "Victor" + }, + { + "id": "3554", + "name": "Helena" + }, + { + "id": "3555", + "name": "Teodor" + }, + { + "id": "3556", + "name": "Marius" + }, + { + "id": "3557", + "name": "Gabriela" + }, + { + "id": "3558", + "name": "Vladimir" + }, + { + "id": "3559", + "name": "Calin" + }, + { + "id": "3560", + "name": "Mihail" + }, + { + "id": "3561", + "name": "Nicoleta" + }, + { + "id": "3562", + "name": "Simona" + }, + { + "id": "3563", + "name": "Vasile" + }, + { + "id": "3564", + "name": "Razvan" + }, + { + "id": "3565", + "name": "Luminata" + }, + { + "id": "3566", + "name": "Cornelius" + }, + { + "id": "3569", + "name": "Cornelius" + }, + { + "id": "3570", + "name": "Benjamin" + }, + { + "id": "3571", + "name": "Liam" + }, + { + "id": "3572", + "name": "Miala" + }, + { + "id": "3573", + "name": "Verak" + }, + { + "id": "3574", + "name": "Fishing spot" + }, + { + "id": "3575", + "name": "Fishing spot" + }, + { + "id": "3576", + "name": "Juvinate" + }, + { + "id": "3578", + "name": "Juvinate" + }, + { + "id": "3580", + "name": "Tentacle" + }, + { + "id": "3584", + "name": "Troll" + }, + { + "id": "3592", + "name": "Tok-Xil" + }, + { + "id": "3594", + "name": "Rocnar" + }, + { + "id": "3595", + "name": "Toy Soldier" + }, + { + "id": "3596", + "name": "Toy Doll" + }, + { + "id": "3597", + "name": "Toy Mouse" + }, + { + "id": "3598", + "name": "Clockwork cat" + }, + { + "id": "3606", + "name": "Ghast" + }, + { + "id": "3607", + "name": "Ghast" + }, + { + "id": "3608", + "name": "Ghast" + }, + { + "id": "3609", + "name": "Ghast" + }, + { + "id": "3610", + "name": "Ghast" + }, + { + "id": "3611", + "name": "Ghast" + }, + { + "id": "3612", + "name": "Giant snail" + }, + { + "id": "3613", + "name": "Giant snail" + }, + { + "id": "3614", + "name": "Giant snail" + }, + { + "id": "3615", + "name": "Riyl shadow" + }, + { + "id": "3616", + "name": "Asyn shadow" + }, + { + "id": "3617", + "name": "Shade" + }, + { + "id": "3621", + "name": "Tentacle" + }, + { + "id": "3623", + "name": "Smiddi Ryak" + }, + { + "id": "3625", + "name": "Rolayne Twickit" + }, + { + "id": "3627", + "name": "Jayene Kliyn" + }, + { + "id": "3629", + "name": "Valantay Eppel" + }, + { + "id": "3631", + "name": "Dalcian Fang" + }, + { + "id": "3633", + "name": "Fyiona Fray" + }, + { + "id": "3635", + "name": "Abidor Crank" + }, + { + "id": "3636", + "name": "Spirit tree" + }, + { + "id": "3637", + "name": "Spirit tree" + }, + { + "id": "3638", + "name": "Launa" + }, + { + "id": "3640", + "name": "Launa" + }, + { + "id": "3641", + "name": "Brana" + }, + { + "id": "3642", + "name": "Mawnis Burowgar" + }, + { + "id": "3643", + "name": "Tolna" + }, + { + "id": "3644", + "name": "Tolna" + }, + { + "id": "3651", + "name": "Confusion beast" + }, + { + "id": "3652", + "name": "Confusion beast" + }, + { + "id": "3653", + "name": "Confusion beast" + }, + { + "id": "3654", + "name": "Confusion beast" + }, + { + "id": "3656", + "name": "Hopeless creature" + }, + { + "id": "3657", + "name": "Hopeless creature" + }, + { + "id": "3658", + "name": "Tolna" + }, + { + "id": "3659", + "name": "Tolna" + }, + { + "id": "3660", + "name": "Tolna" + }, + { + "id": "3668", + "name": "Hopeless beast" + }, + { + "id": "3669", + "name": "Hopeless beast" + }, + { + "id": "3677", + "name": "Sinister Stranger" + }, + { + "id": "3678", + "name": "Sinister Stranger" + }, + { + "id": "3679", + "name": "Vestri" + }, + { + "id": "3681", + "name": "Nigel" + }, + { + "id": "3682", + "name": "Egg" + }, + { + "id": "3683", + "name": "Egg" + }, + { + "id": "3684", + "name": "Egg" + }, + { + "id": "3685", + "name": "Egg" + }, + { + "id": "3686", + "name": "Chocolate kebbit" + }, + { + "id": "3687", + "name": "Chocolate kebbit" + }, + { + "id": "3688", + "name": "Easter Bunny" + }, + { + "id": "3689", + "name": "Egg" + }, + { + "id": "3690", + "name": "Egg" + }, + { + "id": "3691", + "name": "Egg" + }, + { + "id": "3692", + "name": "Egg" + }, + { + "id": "3693", + "name": "Egg" + }, + { + "id": "3694", + "name": "Egg" + }, + { + "id": "3695", + "name": "Volf Olafson" + }, + { + "id": "3696", + "name": "Ingrid Hradson" + }, + { + "id": "3708", + "name": "Boulder" + }, + { + "id": "3710", + "name": "Ulfric" + }, + { + "id": "3712", + "name": "Zanik" + }, + { + "id": "3713", + "name": "Sigmund" + }, + { + "id": "3714", + "name": "Zanik" + }, + { + "id": "3716", + "name": "Sigmund" + }, + { + "id": "3717", + "name": "Sigmund" + }, + { + "id": "3718", + "name": "Sigmund" + }, + { + "id": "3719", + "name": "Sigmund" + }, + { + "id": "3720", + "name": "Sigmund" + }, + { + "id": "3721", + "name": "Zanik" + }, + { + "id": "3722", + "name": "Zanik" + }, + { + "id": "3723", + "name": "General Bentnoze" + }, + { + "id": "3724", + "name": "General Wartface" + }, + { + "id": "3725", + "name": "Grubfoot" + }, + { + "id": "3778", + "name": "Arthur" + }, + { + "id": "3780", + "name": "Squire" + }, + { + "id": "3787", + "name": "Sir Palomedes" + }, + { + "id": "3789", + "name": "Void Knight" + }, + { + "id": "3803", + "name": "Fishing spot" + }, + { + "id": "3817", + "name": "Lieutenant Schepbur" + }, + { + "id": "3820", + "name": "Wise Old Man" + }, + { + "id": "3825", + "name": "Devin Mendelberg" + }, + { + "id": "3826", + "name": "George Laxmeister" + }, + { + "id": "3827", + "name": "Ramara du Croissant" + }, + { + "id": "3828", + "name": "Kathy Corkat" + }, + { + "id": "3831", + "name": "Kathy Corkat" + }, + { + "id": "3832", + "name": "Kalphite Queen" + }, + { + "id": "3837", + "name": "Drunken Dwarf" + }, + { + "id": "3838", + "name": "Wise Old Man" + }, + { + "id": "3839", + "name": "Wise Old Man" + }, + { + "id": "3841", + "name": "Sea troll" + }, + { + "id": "3842", + "name": "Sea troll" + }, + { + "id": "3844", + "name": "Skeleton Mage" + }, + { + "id": "3845", + "name": "Sea troll" + }, + { + "id": "3846", + "name": "Sea Troll General" + }, + { + "id": "3848", + "name": "Fishing spot" + }, + { + "id": "3850", + "name": "Skeleton Mage" + }, + { + "id": "3852", + "name": "Suspect" + }, + { + "id": "3853", + "name": "Suspect" + }, + { + "id": "3854", + "name": "Suspect" + }, + { + "id": "3855", + "name": "Suspect" + }, + { + "id": "3856", + "name": "Suspect" + }, + { + "id": "3857", + "name": "Suspect" + }, + { + "id": "3858", + "name": "Suspect" + }, + { + "id": "3859", + "name": "Suspect" + }, + { + "id": "3860", + "name": "Suspect" + }, + { + "id": "3861", + "name": "Suspect" + }, + { + "id": "3862", + "name": "Suspect" + }, + { + "id": "3863", + "name": "Suspect" + }, + { + "id": "3864", + "name": "Suspect" + }, + { + "id": "3865", + "name": "Suspect" + }, + { + "id": "3866", + "name": "Suspect" + }, + { + "id": "3867", + "name": "Suspect" + }, + { + "id": "3868", + "name": "Suspect" + }, + { + "id": "3869", + "name": "Suspect" + }, + { + "id": "3870", + "name": "Suspect" + }, + { + "id": "3871", + "name": "Suspect" + }, + { + "id": "3872", + "name": "Suspect" + }, + { + "id": "3873", + "name": "Suspect" + }, + { + "id": "3874", + "name": "Suspect" + }, + { + "id": "3875", + "name": "Suspect" + }, + { + "id": "3876", + "name": "Suspect" + }, + { + "id": "3877", + "name": "Suspect" + }, + { + "id": "3878", + "name": "Suspect" + }, + { + "id": "3879", + "name": "Suspect" + }, + { + "id": "3880", + "name": "Suspect" + }, + { + "id": "3881", + "name": "Suspect" + }, + { + "id": "3882", + "name": "Suspect" + }, + { + "id": "3883", + "name": "Suspect" + }, + { + "id": "3884", + "name": "Suspect" + }, + { + "id": "3885", + "name": "Suspect" + }, + { + "id": "3886", + "name": "Suspect" + }, + { + "id": "3887", + "name": "Suspect" + }, + { + "id": "3888", + "name": "Suspect" + }, + { + "id": "3889", + "name": "Suspect" + }, + { + "id": "3890", + "name": "Suspect" + }, + { + "id": "3891", + "name": "Suspect" + }, + { + "id": "3892", + "name": "Molly" + }, + { + "id": "3893", + "name": "Molly" + }, + { + "id": "3894", + "name": "Molly" + }, + { + "id": "3895", + "name": "Molly" + }, + { + "id": "3896", + "name": "Molly" + }, + { + "id": "3897", + "name": "Molly" + }, + { + "id": "3898", + "name": "Molly" + }, + { + "id": "3899", + "name": "Molly" + }, + { + "id": "3900", + "name": "Molly" + }, + { + "id": "3901", + "name": "Molly" + }, + { + "id": "3902", + "name": "Molly" + }, + { + "id": "3903", + "name": "Molly" + }, + { + "id": "3904", + "name": "Molly" + }, + { + "id": "3905", + "name": "Molly" + }, + { + "id": "3906", + "name": "Molly" + }, + { + "id": "3907", + "name": "Molly" + }, + { + "id": "3908", + "name": "Molly" + }, + { + "id": "3909", + "name": "Molly" + }, + { + "id": "3910", + "name": "Molly" + }, + { + "id": "3911", + "name": "Molly" + }, + { + "id": "3912", + "name": "Flippa" + }, + { + "id": "3913", + "name": "Tilt" + }, + { + "id": "3914", + "name": "Gardener" + }, + { + "id": "3918", + "name": "Prince Brand" + }, + { + "id": "3919", + "name": "Princess Astrid" + }, + { + "id": "3920", + "name": "Runa" + }, + { + "id": "3923", + "name": "Osvald" + }, + { + "id": "3924", + "name": "Runolf" + }, + { + "id": "3926", + "name": "Ingrid" + }, + { + "id": "3928", + "name": "Signy" + }, + { + "id": "3929", + "name": "Hild" + }, + { + "id": "3930", + "name": "Armod" + }, + { + "id": "3931", + "name": "Beigarth" + }, + { + "id": "3932", + "name": "Reinn" + }, + { + "id": "3936", + "name": "Thorodin" + }, + { + "id": "3944", + "name": "Hangman game" + }, + { + "id": "3945", + "name": "Hangman game" + }, + { + "id": "3946", + "name": "Hangman game" + }, + { + "id": "3947", + "name": "Hangman game" + }, + { + "id": "3948", + "name": "Hangman game" + }, + { + "id": "3949", + "name": "Hangman game" + }, + { + "id": "3950", + "name": "Hangman game" + }, + { + "id": "3951", + "name": "Hangman game" + }, + { + "id": "3952", + "name": "Hangman game" + }, + { + "id": "3953", + "name": "Hangman game" + }, + { + "id": "3954", + "name": "Treasure fairy" + }, + { + "id": "3955", + "name": "Jacky Jester" + }, + { + "id": "3956", + "name": "Combat stone" + }, + { + "id": "3957", + "name": "Combat stone" + }, + { + "id": "3958", + "name": "Combat stone" + }, + { + "id": "3959", + "name": "Combat stone" + }, + { + "id": "3960", + "name": "Combat stone" + }, + { + "id": "3961", + "name": "Combat stone" + }, + { + "id": "3962", + "name": "Combat stone" + }, + { + "id": "3963", + "name": "Combat stone" + }, + { + "id": "3964", + "name": "Combat stone" + }, + { + "id": "3965", + "name": "Combat stone" + }, + { + "id": "3966", + "name": "Combat stone" + }, + { + "id": "3967", + "name": "Combat stone" + }, + { + "id": "3968", + "name": "Combat stone" + }, + { + "id": "3969", + "name": "Combat stone" + }, + { + "id": "3970", + "name": "Combat stone" + }, + { + "id": "3971", + "name": "Combat stone" + }, + { + "id": "3972", + "name": "Combat stone" + }, + { + "id": "3973", + "name": "Combat stone" + }, + { + "id": "3974", + "name": "Combat stone" + }, + { + "id": "3975", + "name": "Combat stone" + }, + { + "id": "3976", + "name": "Combat stone" + }, + { + "id": "3977", + "name": "Combat stone" + }, + { + "id": "3978", + "name": "Combat stone" + }, + { + "id": "3979", + "name": "Combat stone" + }, + { + "id": "3980", + "name": "Combat stone" + }, + { + "id": "3981", + "name": "Combat stone" + }, + { + "id": "3982", + "name": "Combat stone" + }, + { + "id": "3983", + "name": "Combat stone" + }, + { + "id": "3984", + "name": "Combat stone" + }, + { + "id": "3985", + "name": "Combat stone" + }, + { + "id": "3986", + "name": "Combat stone" + }, + { + "id": "3987", + "name": "Combat stone" + }, + { + "id": "3988", + "name": "Combat stone" + }, + { + "id": "3989", + "name": "Combat stone" + }, + { + "id": "3990", + "name": "Combat stone" + }, + { + "id": "3991", + "name": "Combat stone" + }, + { + "id": "3992", + "name": "Combat stone" + }, + { + "id": "3993", + "name": "Combat stone" + }, + { + "id": "3994", + "name": "Combat stone" + }, + { + "id": "3995", + "name": "Combat stone" + }, + { + "id": "3996", + "name": "Combat stone" + }, + { + "id": "3997", + "name": "Combat stone" + }, + { + "id": "3998", + "name": "Combat stone" + }, + { + "id": "3999", + "name": "Combat stone" + }, + { + "id": "4000", + "name": "Combat stone" + }, + { + "id": "4001", + "name": "Combat stone" + }, + { + "id": "4002", + "name": "Combat stone" + }, + { + "id": "4003", + "name": "Combat stone" + }, + { + "id": "4004", + "name": "Combat stone" + }, + { + "id": "4005", + "name": "Combat stone" + }, + { + "id": "4006", + "name": "Combat stone" + }, + { + "id": "4007", + "name": "Combat stone" + }, + { + "id": "4008", + "name": "Combat stone" + }, + { + "id": "4009", + "name": "Combat stone" + }, + { + "id": "4010", + "name": "Combat stone" + }, + { + "id": "4011", + "name": "Combat stone" + }, + { + "id": "4012", + "name": "Combat stone" + }, + { + "id": "4013", + "name": "Combat stone" + }, + { + "id": "4014", + "name": "Combat stone" + }, + { + "id": "4015", + "name": "Combat stone" + }, + { + "id": "4016", + "name": "Combat stone" + }, + { + "id": "4017", + "name": "Combat stone" + }, + { + "id": "4018", + "name": "Combat stone" + }, + { + "id": "4019", + "name": "Combat stone" + }, + { + "id": "4020", + "name": "Combat stone" + }, + { + "id": "4021", + "name": "Elemental balance" + }, + { + "id": "4022", + "name": "Elemental balance" + }, + { + "id": "4023", + "name": "Elemental balance" + }, + { + "id": "4024", + "name": "Elemental balance" + }, + { + "id": "4025", + "name": "Elemental balance" + }, + { + "id": "4026", + "name": "Elemental balance" + }, + { + "id": "4027", + "name": "Elemental balance" + }, + { + "id": "4028", + "name": "Elemental balance" + }, + { + "id": "4029", + "name": "Elemental balance" + }, + { + "id": "4030", + "name": "Elemental balance" + }, + { + "id": "4031", + "name": "Elemental balance" + }, + { + "id": "4032", + "name": "Elemental balance" + }, + { + "id": "4033", + "name": "Elemental balance" + }, + { + "id": "4034", + "name": "Elemental balance" + }, + { + "id": "4035", + "name": "Elemental balance" + }, + { + "id": "4036", + "name": "Elemental balance" + }, + { + "id": "4037", + "name": "Elemental balance" + }, + { + "id": "4038", + "name": "Elemental balance" + }, + { + "id": "4039", + "name": "Elemental balance" + }, + { + "id": "4040", + "name": "Elemental balance" + }, + { + "id": "4041", + "name": "Elemental balance" + }, + { + "id": "4042", + "name": "Elemental balance" + }, + { + "id": "4043", + "name": "Elemental balance" + }, + { + "id": "4044", + "name": "Elemental balance" + }, + { + "id": "4045", + "name": "Elemental balance" + }, + { + "id": "4046", + "name": "Elemental balance" + }, + { + "id": "4047", + "name": "Elemental balance" + }, + { + "id": "4048", + "name": "Elemental balance" + }, + { + "id": "4049", + "name": "Elemental balance" + }, + { + "id": "4050", + "name": "Elemental balance" + }, + { + "id": "4051", + "name": "Elemental balance" + }, + { + "id": "4052", + "name": "Elemental balance" + }, + { + "id": "4053", + "name": "Elemental balance" + }, + { + "id": "4054", + "name": "Elemental balance" + }, + { + "id": "4055", + "name": "Elemental balance" + }, + { + "id": "4056", + "name": "Elemental balance" + }, + { + "id": "4057", + "name": "Elemental balance" + }, + { + "id": "4058", + "name": "Elemental balance" + }, + { + "id": "4059", + "name": "Elemental balance" + }, + { + "id": "4060", + "name": "Elemental balance" + }, + { + "id": "4061", + "name": "Elemental balance" + }, + { + "id": "4062", + "name": "Elemental balance" + }, + { + "id": "4063", + "name": "Elemental balance" + }, + { + "id": "4064", + "name": "Elemental balance" + }, + { + "id": "4065", + "name": "Elemental balance" + }, + { + "id": "4066", + "name": "Elemental balance" + }, + { + "id": "4067", + "name": "Elemental balance" + }, + { + "id": "4068", + "name": "Elemental balance" + }, + { + "id": "4069", + "name": "Elemental balance" + }, + { + "id": "4070", + "name": "Elemental balance" + }, + { + "id": "4071", + "name": "Elemental balance" + }, + { + "id": "4072", + "name": "Elemental balance" + }, + { + "id": "4073", + "name": "Elemental balance" + }, + { + "id": "4074", + "name": "Elemental balance" + }, + { + "id": "4075", + "name": "Elemental balance" + }, + { + "id": "4076", + "name": "Elemental balance" + }, + { + "id": "4077", + "name": "Elemental balance" + }, + { + "id": "4078", + "name": "Elemental balance" + }, + { + "id": "4079", + "name": "Elemental balance" + }, + { + "id": "4080", + "name": "Elemental balance" + }, + { + "id": "4081", + "name": "Elemental balance" + }, + { + "id": "4082", + "name": "Elemental balance" + }, + { + "id": "4083", + "name": "Elemental balance" + }, + { + "id": "4084", + "name": "Elemental balance" + }, + { + "id": "4085", + "name": "Elemental balance" + }, + { + "id": "4086", + "name": "Elemental balance" + }, + { + "id": "4087", + "name": "Elemental balance" + }, + { + "id": "4088", + "name": "Elemental balance" + }, + { + "id": "4089", + "name": "Elemental balance" + }, + { + "id": "4090", + "name": "Elemental balance" + }, + { + "id": "4091", + "name": "Elemental balance" + }, + { + "id": "4092", + "name": "Elemental balance" + }, + { + "id": "4093", + "name": "Elemental balance" + }, + { + "id": "4094", + "name": "Elemental balance" + }, + { + "id": "4095", + "name": "Elemental balance" + }, + { + "id": "4096", + "name": "Combat stone" + }, + { + "id": "4097", + "name": "Combat stone" + }, + { + "id": "4098", + "name": "Combat stone" + }, + { + "id": "4099", + "name": "Combat stone" + }, + { + "id": "4100", + "name": "Combat stone" + }, + { + "id": "4101", + "name": "Combat stone" + }, + { + "id": "4102", + "name": "Combat stone" + }, + { + "id": "4103", + "name": "Combat stone" + }, + { + "id": "4104", + "name": "Combat stone" + }, + { + "id": "4105", + "name": "Combat stone" + }, + { + "id": "4106", + "name": "Combat stone" + }, + { + "id": "4107", + "name": "Combat stone" + }, + { + "id": "4108", + "name": "Combat stone" + }, + { + "id": "4109", + "name": "Combat stone" + }, + { + "id": "4110", + "name": "Combat stone" + }, + { + "id": "4111", + "name": "Combat stone" + }, + { + "id": "4112", + "name": "Combat stone" + }, + { + "id": "4113", + "name": "Combat stone" + }, + { + "id": "4114", + "name": "Combat stone" + }, + { + "id": "4115", + "name": "Combat stone" + }, + { + "id": "4116", + "name": "Combat stone" + }, + { + "id": "4117", + "name": "Combat stone" + }, + { + "id": "4118", + "name": "Combat stone" + }, + { + "id": "4119", + "name": "Combat stone" + }, + { + "id": "4120", + "name": "Combat stone" + }, + { + "id": "4121", + "name": "Combat stone" + }, + { + "id": "4122", + "name": "Combat stone" + }, + { + "id": "4123", + "name": "Combat stone" + }, + { + "id": "4124", + "name": "Combat stone" + }, + { + "id": "4125", + "name": "Combat stone" + }, + { + "id": "4126", + "name": "Combat stone" + }, + { + "id": "4127", + "name": "Combat stone" + }, + { + "id": "4128", + "name": "Combat stone" + }, + { + "id": "4129", + "name": "Combat stone" + }, + { + "id": "4130", + "name": "Combat stone" + }, + { + "id": "4131", + "name": "Combat stone" + }, + { + "id": "4132", + "name": "Combat stone" + }, + { + "id": "4133", + "name": "Combat stone" + }, + { + "id": "4134", + "name": "Combat stone" + }, + { + "id": "4135", + "name": "Combat stone" + }, + { + "id": "4136", + "name": "Combat stone" + }, + { + "id": "4137", + "name": "Combat stone" + }, + { + "id": "4138", + "name": "Combat stone" + }, + { + "id": "4139", + "name": "Combat stone" + }, + { + "id": "4140", + "name": "Combat stone" + }, + { + "id": "4141", + "name": "Combat stone" + }, + { + "id": "4142", + "name": "Combat stone" + }, + { + "id": "4143", + "name": "Combat stone" + }, + { + "id": "4144", + "name": "Combat stone" + }, + { + "id": "4145", + "name": "Combat stone" + }, + { + "id": "4146", + "name": "Combat stone" + }, + { + "id": "4147", + "name": "Combat stone" + }, + { + "id": "4148", + "name": "Combat stone" + }, + { + "id": "4149", + "name": "Combat stone" + }, + { + "id": "4150", + "name": "Combat stone" + }, + { + "id": "4151", + "name": "Combat stone" + }, + { + "id": "4152", + "name": "Combat stone" + }, + { + "id": "4153", + "name": "Combat stone" + }, + { + "id": "4154", + "name": "Combat stone" + }, + { + "id": "4155", + "name": "Combat stone" + }, + { + "id": "4156", + "name": "Combat stone" + }, + { + "id": "4157", + "name": "Combat stone" + }, + { + "id": "4158", + "name": "Combat stone" + }, + { + "id": "4159", + "name": "Combat stone" + }, + { + "id": "4160", + "name": "Combat stone" + }, + { + "id": "4161", + "name": "Combat stone" + }, + { + "id": "4162", + "name": "Combat stone" + }, + { + "id": "4163", + "name": "Combat stone" + }, + { + "id": "4164", + "name": "Combat stone" + }, + { + "id": "4165", + "name": "Combat stone" + }, + { + "id": "4166", + "name": "Combat stone" + }, + { + "id": "4167", + "name": "Combat stone" + }, + { + "id": "4168", + "name": "Combat stone" + }, + { + "id": "4169", + "name": "Combat stone" + }, + { + "id": "4170", + "name": "Combat stone" + }, + { + "id": "4171", + "name": "Combat stone" + }, + { + "id": "4172", + "name": "Combat stone" + }, + { + "id": "4173", + "name": "Combat stone" + }, + { + "id": "4174", + "name": "Combat stone" + }, + { + "id": "4175", + "name": "Combat stone" + }, + { + "id": "4176", + "name": "Combat stone" + }, + { + "id": "4177", + "name": "Combat stone" + }, + { + "id": "4178", + "name": "Combat stone" + }, + { + "id": "4179", + "name": "Combat stone" + }, + { + "id": "4180", + "name": "Combat stone" + }, + { + "id": "4181", + "name": "Combat stone" + }, + { + "id": "4182", + "name": "Combat stone" + }, + { + "id": "4183", + "name": "Combat stone" + }, + { + "id": "4184", + "name": "Combat stone" + }, + { + "id": "4185", + "name": "Combat stone" + }, + { + "id": "4186", + "name": "Combat stone" + }, + { + "id": "4187", + "name": "Combat stone" + }, + { + "id": "4188", + "name": "Combat stone" + }, + { + "id": "4189", + "name": "Combat stone" + }, + { + "id": "4190", + "name": "Combat stone" + }, + { + "id": "4191", + "name": "Combat stone" + }, + { + "id": "4192", + "name": "Combat stone" + }, + { + "id": "4193", + "name": "Combat stone" + }, + { + "id": "4194", + "name": "Combat stone" + }, + { + "id": "4195", + "name": "Combat stone" + }, + { + "id": "4196", + "name": "Combat stone" + }, + { + "id": "4197", + "name": "Combat stone" + }, + { + "id": "4198", + "name": "Combat stone" + }, + { + "id": "4199", + "name": "Combat stone" + }, + { + "id": "4200", + "name": "Combat stone" + }, + { + "id": "4201", + "name": "Combat stone" + }, + { + "id": "4202", + "name": "Combat stone" + }, + { + "id": "4203", + "name": "Combat stone" + }, + { + "id": "4204", + "name": "Combat stone" + }, + { + "id": "4205", + "name": "Combat stone" + }, + { + "id": "4206", + "name": "Combat stone" + }, + { + "id": "4207", + "name": "Combat stone" + }, + { + "id": "4208", + "name": "Combat stone" + }, + { + "id": "4209", + "name": "Combat stone" + }, + { + "id": "4210", + "name": "Combat stone" + }, + { + "id": "4211", + "name": "Combat stone" + }, + { + "id": "4212", + "name": "Combat stone" + }, + { + "id": "4213", + "name": "Combat stone" + }, + { + "id": "4214", + "name": "Combat stone" + }, + { + "id": "4215", + "name": "Combat stone" + }, + { + "id": "4216", + "name": "Combat stone" + }, + { + "id": "4217", + "name": "Combat stone" + }, + { + "id": "4218", + "name": "Combat stone" + }, + { + "id": "4219", + "name": "Combat stone" + }, + { + "id": "4220", + "name": "Combat stone" + }, + { + "id": "4221", + "name": "Combat stone" + }, + { + "id": "4222", + "name": "Combat stone" + }, + { + "id": "4223", + "name": "Combat stone" + }, + { + "id": "4224", + "name": "Combat stone" + }, + { + "id": "4225", + "name": "Combat stone" + }, + { + "id": "4226", + "name": "Crawling hand" + }, + { + "id": "4231", + "name": "Left head" + }, + { + "id": "4232", + "name": "Middle head" + }, + { + "id": "4233", + "name": "Right head" + }, + { + "id": "4234", + "name": "Kalphite Queen" + }, + { + "id": "4235", + "name": "Rick" + }, + { + "id": "4236", + "name": "Maid" + }, + { + "id": "4238", + "name": "Cook" + }, + { + "id": "4240", + "name": "Butler" + }, + { + "id": "4242", + "name": "Demon butler" + }, + { + "id": "4244", + "name": "Chief servant" + }, + { + "id": "4253", + "name": "Guard" + }, + { + "id": "4277", + "name": "Buinn" + }, + { + "id": "4312", + "name": "Nardok" + }, + { + "id": "4313", + "name": "Dartog" + }, + { + "id": "4315", + "name": "Dwarf" + }, + { + "id": "4317", + "name": "H.A.M. Member" + }, + { + "id": "4319", + "name": "H.A.M. Member" + }, + { + "id": "4321", + "name": "Zanik" + }, + { + "id": "4323", + "name": "Zanik" + }, + { + "id": "4324", + "name": "Zanik" + }, + { + "id": "4325", + "name": "Light creature" + }, + { + "id": "4326", + "name": "Zanik" + }, + { + "id": "4327", + "name": "HAM member" + }, + { + "id": "4328", + "name": "Sigmund" + }, + { + "id": "4330", + "name": "Johanhus Ulsbrecht" + }, + { + "id": "4331", + "name": "Sigmund" + }, + { + "id": "4332", + "name": "Sigmund" + }, + { + "id": "4333", + "name": "Sigmund" + }, + { + "id": "4334", + "name": "Sigmund" + }, + { + "id": "4335", + "name": "Sigmund" + }, + { + "id": "4337", + "name": "Zanik" + }, + { + "id": "4338", + "name": "Zanik" + }, + { + "id": "4340", + "name": "Zanik" + }, + { + "id": "4341", + "name": "Zanik" + }, + { + "id": "4342", + "name": "Zanik" + }, + { + "id": "4346", + "name": "Crab" + }, + { + "id": "4358", + "name": "Cavey Davey" + }, + { + "id": "4360", + "name": "San Fan" + }, + { + "id": "4364", + "name": "Swarm" + }, + { + "id": "4365", + "name": "Blue Monkey" + }, + { + "id": "4374", + "name": "Parrot" + }, + { + "id": "4377", + "name": "Gate of War" + }, + { + "id": "4378", + "name": "Ricketty door" + }, + { + "id": "4379", + "name": "Oozing barrier" + }, + { + "id": "4380", + "name": "Portal of Death" + }, + { + "id": "4416", + "name": "Bee keeper" + }, + { + "id": "4417", + "name": "Bees!" + }, + { + "id": "4420", + "name": "Fairy Godfather" + }, + { + "id": "4435", + "name": "Fairy Queen" + }, + { + "id": "4442", + "name": "Fairy Very Wise" + }, + { + "id": "4444", + "name": "Fairy" + }, + { + "id": "4445", + "name": "Fairy" + }, + { + "id": "4446", + "name": "Fairy" + }, + { + "id": "4447", + "name": "Rabbit" + }, + { + "id": "4448", + "name": "Rabbit" + }, + { + "id": "4449", + "name": "Butterfly" + }, + { + "id": "4450", + "name": "Butterfly" + }, + { + "id": "4451", + "name": "Starflower" + }, + { + "id": "4452", + "name": "Starflower" + }, + { + "id": "4453", + "name": "Fairy Fixit" + }, + { + "id": "4456", + "name": "Ork" + }, + { + "id": "4460", + "name": "Fake Man" + }, + { + "id": "4461", + "name": "Held vampyre juvinate" + }, + { + "id": "4462", + "name": "Held vampyre juvinate" + }, + { + "id": "4463", + "name": "Angry juvinate" + }, + { + "id": "4464", + "name": "Angry juvinate" + }, + { + "id": "4465", + "name": "Angry juvinate" + }, + { + "id": "4466", + "name": "Benjamin" + }, + { + "id": "4467", + "name": "Liam" + }, + { + "id": "4468", + "name": "Miala" + }, + { + "id": "4469", + "name": "Verak" + }, + { + "id": "4471", + "name": "Bogrog" + }, + { + "id": "4473", + "name": "Woman" + }, + { + "id": "4475", + "name": "Ned" + }, + { + "id": "4477", + "name": "Annoyed guardian mummy" + }, + { + "id": "4478", + "name": "Tarik" + }, + { + "id": "4493", + "name": "General Bentnoze" + }, + { + "id": "4495", + "name": "Grubfoot" + }, + { + "id": "4497", + "name": "Grubfoot" + }, + { + "id": "4498", + "name": "Grubfoot" + }, + { + "id": "4500", + "name": "Scarab swarm" + }, + { + "id": "4508", + "name": "Ethereal Mimic" + }, + { + "id": "4513", + "name": "Baba Yaga" + }, + { + "id": "4514", + "name": "Pauline Polaris" + }, + { + "id": "4515", + "name": "Meteora" + }, + { + "id": "4516", + "name": "Melana Moonlander" + }, + { + "id": "4517", + "name": "Selene" + }, + { + "id": "4518", + "name": "Rimae Sirsalis" + }, + { + "id": "4519", + "name": "Sirsal Banker" + }, + { + "id": "4520", + "name": "Clan Guard" + }, + { + "id": "4522", + "name": "Enchanted Broom" + }, + { + "id": "4523", + "name": "Enchanted Broom" + }, + { + "id": "4525", + "name": "Enchanted Bucket" + }, + { + "id": "4526", + "name": "Bouquet Mac Hyacinth" + }, + { + "id": "4535", + "name": "Parrot" + }, + { + "id": "4536", + "name": "Lokar Searunner" + }, + { + "id": "4538", + "name": "Cabin boy" + }, + { + "id": "4544", + "name": "'Bird's-Eye' Jack" + }, + { + "id": "4552", + "name": "Palmer" + }, + { + "id": "4553", + "name": "'Betty' B.Boppin" + }, + { + "id": "4558", + "name": "Hirko" + }, + { + "id": "4559", + "name": "Holoy" + }, + { + "id": "4563", + "name": "Hura" + }, + { + "id": "4569", + "name": "Nick" + }, + { + "id": "4570", + "name": "Crow" + }, + { + "id": "4571", + "name": "Crow" + }, + { + "id": "4572", + "name": "Gianne jnr." + }, + { + "id": "4573", + "name": "Timble" + }, + { + "id": "4574", + "name": "Tamble" + }, + { + "id": "4575", + "name": "Spang" + }, + { + "id": "4576", + "name": "Brambickle" + }, + { + "id": "4577", + "name": "Wingstone" + }, + { + "id": "4578", + "name": "Penwie" + }, + { + "id": "4583", + "name": "Professor Manglethorp" + }, + { + "id": "4584", + "name": "Damwin" + }, + { + "id": "4586", + "name": "Professor Imblewyn" + }, + { + "id": "4587", + "name": "Perrdur" + }, + { + "id": "4588", + "name": "Dalila" + }, + { + "id": "4591", + "name": "Eebel" + }, + { + "id": "4592", + "name": "Ermin" + }, + { + "id": "4596", + "name": "Captain Lamdoo" + }, + { + "id": "4597", + "name": "Meegle" + }, + { + "id": "4598", + "name": "Wurbel" + }, + { + "id": "4599", + "name": "Sarble" + }, + { + "id": "4601", + "name": "Burkor" + }, + { + "id": "4602", + "name": "Froono" + }, + { + "id": "4609", + "name": "Brimstail" + }, + { + "id": "4612", + "name": "Gnome shop keeper" + }, + { + "id": "4613", + "name": "Cute creature" + }, + { + "id": "4616", + "name": "Cute creature" + }, + { + "id": "4618", + "name": "Evil creature" + }, + { + "id": "4619", + "name": "Cute creature" + }, + { + "id": "4621", + "name": "Evil creature" + }, + { + "id": "4622", + "name": "Cute creature" + }, + { + "id": "4624", + "name": "Evil creature" + }, + { + "id": "4625", + "name": "Cute creature" + }, + { + "id": "4627", + "name": "Evil creature" + }, + { + "id": "4628", + "name": "Cute creature" + }, + { + "id": "4630", + "name": "Evil creature" + }, + { + "id": "4631", + "name": "fluffie" + }, + { + "id": "4632", + "name": "fluffie" + }, + { + "id": "4644", + "name": "Oaknock the Engineer" + }, + { + "id": "4646", + "name": "King Healthorg" + }, + { + "id": "4647", + "name": "Hazelmere" + }, + { + "id": "4648", + "name": "Nisha" + }, + { + "id": "4649", + "name": "Tyras guard" + }, + { + "id": "4657", + "name": "Sir Prysin" + }, + { + "id": "4658", + "name": "Dark wizard" + }, + { + "id": "4662", + "name": "Denath" + }, + { + "id": "4663", + "name": "Denath" + }, + { + "id": "4664", + "name": "Wally" + }, + { + "id": "4709", + "name": "Vertida Sefalatis" + }, + { + "id": "4710", + "name": "Aeonisig Raispher" + }, + { + "id": "4711", + "name": "Safalaan" + }, + { + "id": "4714", + "name": "Sarius Guile" + }, + { + "id": "4727", + "name": "Meiyerditch citizen" + }, + { + "id": "4728", + "name": "Meiyerditch citizen" + }, + { + "id": "4729", + "name": "Meiyerditch citizen" + }, + { + "id": "4730", + "name": "Meiyerditch citizen" + }, + { + "id": "4731", + "name": "Meiyerditch citizen" + }, + { + "id": "4732", + "name": "Meiyerditch citizen" + }, + { + "id": "4742", + "name": "Meiyerditch citizen" + }, + { + "id": "4743", + "name": "Meiyerditch citizen" + }, + { + "id": "4744", + "name": "Meiyerditch citizen" + }, + { + "id": "4745", + "name": "Meiyerditch citizen" + }, + { + "id": "4758", + "name": "Meiyerditch miner" + }, + { + "id": "4760", + "name": "Meiyerditch miner" + }, + { + "id": "4761", + "name": "Meiyerditch miner" + }, + { + "id": "4762", + "name": "Shadowy figure" + }, + { + "id": "4763", + "name": "Shadowy figure" + }, + { + "id": "4764", + "name": "Shadowy figure" + }, + { + "id": "4767", + "name": "Stray dog" + }, + { + "id": "4769", + "name": "Cat" + }, + { + "id": "4770", + "name": "Boat" + }, + { + "id": "4771", + "name": "Boat" + }, + { + "id": "4781", + "name": "Held vampyre juvinate" + }, + { + "id": "4782", + "name": "Vampyre juvinate" + }, + { + "id": "4783", + "name": "Former vampyre" + }, + { + "id": "4784", + "name": "Former vampyre" + }, + { + "id": "4785", + "name": "Former vampyre" + }, + { + "id": "4786", + "name": "Former vampyre" + }, + { + "id": "4787", + "name": "Former vampyre" + }, + { + "id": "4788", + "name": "Former vampyre" + }, + { + "id": "4790", + "name": "Angry vampyre" + }, + { + "id": "4791", + "name": "Vanstrom Klause" + }, + { + "id": "4792", + "name": "Vanstrom Klause" + }, + { + "id": "4794", + "name": "Vanstrom Klause" + }, + { + "id": "4795", + "name": "Vanstrom Klause" + }, + { + "id": "4797", + "name": "Vanescula Drakan" + }, + { + "id": "4798", + "name": "Vanescula Drakan" + }, + { + "id": "4799", + "name": "Vanescula Drakan" + }, + { + "id": "4800", + "name": "Vanescula Drakan" + }, + { + "id": "4801", + "name": "Ranis Drakan" + }, + { + "id": "4802", + "name": "Ranis Drakan" + }, + { + "id": "4803", + "name": "Ranis Drakan" + }, + { + "id": "4804", + "name": "Ranis Drakan" + }, + { + "id": "4809", + "name": "Flying female vampire" + }, + { + "id": "4846", + "name": "Flying female vampire" + }, + { + "id": "4853", + "name": "Ezekial Lovecraft" + }, + { + "id": "4857", + "name": "Sarius Guile" + }, + { + "id": "4862", + "name": "Vanstrom Klause" + }, + { + "id": "4863", + "name": "Kennith" + }, + { + "id": "4864", + "name": "Kennith" + }, + { + "id": "4865", + "name": "Holgart" + }, + { + "id": "4867", + "name": "Holgart" + }, + { + "id": "4869", + "name": "Fisherman" + }, + { + "id": "4871", + "name": "Col. O'Niall" + }, + { + "id": "4873", + "name": "Col. O'Niall" + }, + { + "id": "4875", + "name": "Mayor Hobb" + }, + { + "id": "4876", + "name": "Brother Maledict" + }, + { + "id": "4879", + "name": "Brother Maledict" + }, + { + "id": "4880", + "name": "Witchaven villager" + }, + { + "id": "4884", + "name": "Witchaven villager" + }, + { + "id": "4886", + "name": "Witchaven villager" + }, + { + "id": "4888", + "name": "Witchaven villager" + }, + { + "id": "4889", + "name": "Mother Mallum" + }, + { + "id": "4891", + "name": "Giant lobster" + }, + { + "id": "4896", + "name": "Jeb" + }, + { + "id": "4897", + "name": "Sir Tinley" + }, + { + "id": "4905", + "name": "Smithing Tutor" + }, + { + "id": "4908", + "name": "Fishing spot" + }, + { + "id": "4912", + "name": "Jig cart" + }, + { + "id": "4914", + "name": "Jig cart" + }, + { + "id": "4915", + "name": "Jig cart" + }, + { + "id": "4916", + "name": "Jig cart" + }, + { + "id": "4917", + "name": "Jig cart" + }, + { + "id": "4918", + "name": "Jig cart" + }, + { + "id": "4919", + "name": "Abidor Crank" + }, + { + "id": "4946", + "name": "Ignatius Vulcan" + }, + { + "id": "4948", + "name": "My Arm" + }, + { + "id": "4949", + "name": "My Arm" + }, + { + "id": "4950", + "name": "My Arm" + }, + { + "id": "4958", + "name": "My Arm" + }, + { + "id": "4959", + "name": "My Arm" + }, + { + "id": "4960", + "name": "Adventurer" + }, + { + "id": "4961", + "name": "Captain Barnaby" + }, + { + "id": "4963", + "name": "Murcaily" + }, + { + "id": "4964", + "name": "Jagbakoba" + }, + { + "id": "4966", + "name": "Flies" + }, + { + "id": "4968", + "name": "Unnamed troll child" + }, + { + "id": "4969", + "name": "Drunken dwarf's leg" + }, + { + "id": "4970", + "name": "Baby Roc" + }, + { + "id": "4973", + "name": "Shadow" + }, + { + "id": "4974", + "name": "Captain Barnaby" + }, + { + "id": "4976", + "name": "Male slave" + }, + { + "id": "4978", + "name": "Female slave" + }, + { + "id": "4979", + "name": "Cart Camel" + }, + { + "id": "4980", + "name": "Mine Cart" + }, + { + "id": "4981", + "name": "Mine Cart" + }, + { + "id": "4982", + "name": "Ana" + }, + { + "id": "4983", + "name": "Mercenary" + }, + { + "id": "4984", + "name": "Irena" + }, + { + "id": "5003", + "name": "Gublinch" + }, + { + "id": "5018", + "name": "Gublinch" + }, + { + "id": "5019", + "name": "Gublinch" + }, + { + "id": "5020", + "name": "Jack" + }, + { + "id": "5024", + "name": "Jill" + }, + { + "id": "5025", + "name": "Jeff" + }, + { + "id": "5044", + "name": "Penance Fighter" + }, + { + "id": "5045", + "name": "Penance Fighter" + }, + { + "id": "5046", + "name": "Jack" + }, + { + "id": "5047", + "name": "Jill" + }, + { + "id": "5049", + "name": "Auguste" + }, + { + "id": "5050", + "name": "Auguste" + }, + { + "id": "5051", + "name": "Auguste" + }, + { + "id": "5052", + "name": "Auguste" + }, + { + "id": "5053", + "name": "Assistant Serf" + }, + { + "id": "5054", + "name": "Assistant Brock" + }, + { + "id": "5055", + "name": "Assistant Marrow" + }, + { + "id": "5056", + "name": "Assistant Le Smith" + }, + { + "id": "5057", + "name": "Assistant Stan" + }, + { + "id": "5058", + "name": "Bob" + }, + { + "id": "5059", + "name": "Curly" + }, + { + "id": "5060", + "name": "Moe" + }, + { + "id": "5061", + "name": "Larry" + }, + { + "id": "5062", + "name": "Shark" + }, + { + "id": "5068", + "name": "Shark" + }, + { + "id": "5069", + "name": "Shark" + }, + { + "id": "5070", + "name": "Tropical wagtail" + }, + { + "id": "5077", + "name": "Chinchompa" + }, + { + "id": "5090", + "name": "Matthias" + }, + { + "id": "5093", + "name": "Matthias" + }, + { + "id": "5094", + "name": "Gyr Falcon" + }, + { + "id": "5095", + "name": "Gyr Falcon" + }, + { + "id": "5096", + "name": "Gyr Falcon" + }, + { + "id": "5101", + "name": "Sabre-toothed kyatt" + }, + { + "id": "5110", + "name": "Aleck" + }, + { + "id": "5118", + "name": "Eagle" + }, + { + "id": "5121", + "name": "Eagle" + }, + { + "id": "5122", + "name": "Eagle" + }, + { + "id": "5123", + "name": "Eagle" + }, + { + "id": "5124", + "name": "Nickolaus" + }, + { + "id": "5127", + "name": "Nickolaus" + }, + { + "id": "5128", + "name": "Nickolaus" + }, + { + "id": "5129", + "name": "Nickolaus" + }, + { + "id": "5134", + "name": "Kebbit" + }, + { + "id": "5138", + "name": "Charlie" + }, + { + "id": "5139", + "name": "Boulder" + }, + { + "id": "5141", + "name": "Uri" + }, + { + "id": "5142", + "name": "Uri" + }, + { + "id": "5143", + "name": "Uri" + }, + { + "id": "5148", + "name": "Sheep" + }, + { + "id": "5149", + "name": "Sheep" + }, + { + "id": "5150", + "name": "Sheep" + }, + { + "id": "5151", + "name": "Sheep" + }, + { + "id": "5152", + "name": "Sheep" + }, + { + "id": "5153", + "name": "Sheep" + }, + { + "id": "5154", + "name": "Sheep" + }, + { + "id": "5155", + "name": "Sheep" + }, + { + "id": "5156", + "name": "Sheep" + }, + { + "id": "5157", + "name": "Sheep" + }, + { + "id": "5158", + "name": "Sheep" + }, + { + "id": "5159", + "name": "Sheep" + }, + { + "id": "5160", + "name": "Sheep" + }, + { + "id": "5161", + "name": "Sheep" + }, + { + "id": "5165", + "name": "Sheep" + }, + { + "id": "5174", + "name": "Ogre chieftain" + }, + { + "id": "5175", + "name": "Ogre shaman" + }, + { + "id": "5177", + "name": "Ogre shaman" + }, + { + "id": "5179", + "name": "Elkoy" + }, + { + "id": "5180", + "name": "Ogre shaman" + }, + { + "id": "5182", + "name": "Elkoy" + }, + { + "id": "5183", + "name": "Ogre shaman" + }, + { + "id": "5185", + "name": "Biggleswade" + }, + { + "id": "5186", + "name": "Ogre shaman" + }, + { + "id": "5189", + "name": "Ogre shaman" + }, + { + "id": "5191", + "name": "Blaze Sharpeye" + }, + { + "id": "5192", + "name": "Ogre shaman" + }, + { + "id": "5194", + "name": "Blaze Sharpeye" + }, + { + "id": "5199", + "name": "Witch" + }, + { + "id": "5201", + "name": "Alice's husband" + }, + { + "id": "5203", + "name": "Alice's husband" + }, + { + "id": "5205", + "name": "Alice's husband" + }, + { + "id": "5206", + "name": "Tree" + }, + { + "id": "5208", + "name": "Undead tree" + }, + { + "id": "5209", + "name": " Sneaky undead fowl" + }, + { + "id": "5210", + "name": "Cow1337killr" + }, + { + "id": "5212", + "name": "Alice" + }, + { + "id": "5213", + "name": "Penance Fighter" + }, + { + "id": "5214", + "name": "Penance Fighter" + }, + { + "id": "5215", + "name": "Penance Fighter" + }, + { + "id": "5216", + "name": "Penance Fighter" + }, + { + "id": "5217", + "name": "Penance Fighter" + }, + { + "id": "5218", + "name": "Penance Fighter" + }, + { + "id": "5219", + "name": "Penance Fighter" + }, + { + "id": "5220", + "name": "Penance Runner" + }, + { + "id": "5221", + "name": "Penance Runner" + }, + { + "id": "5222", + "name": "Penance Runner" + }, + { + "id": "5223", + "name": "Penance Runner" + }, + { + "id": "5224", + "name": "Penance Runner" + }, + { + "id": "5225", + "name": "Penance Runner" + }, + { + "id": "5226", + "name": "Penance Runner" + }, + { + "id": "5227", + "name": "Penance Runner" + }, + { + "id": "5228", + "name": "Penance Runner" + }, + { + "id": "5230", + "name": "Penance Ranger" + }, + { + "id": "5231", + "name": "Penance Ranger" + }, + { + "id": "5232", + "name": "Penance Ranger" + }, + { + "id": "5233", + "name": "Penance Ranger" + }, + { + "id": "5234", + "name": "Penance Ranger" + }, + { + "id": "5235", + "name": "Penance Ranger" + }, + { + "id": "5236", + "name": "Penance Ranger" + }, + { + "id": "5238", + "name": "Penance Healer" + }, + { + "id": "5239", + "name": "Penance Healer" + }, + { + "id": "5240", + "name": "Penance Healer" + }, + { + "id": "5241", + "name": "Penance Healer" + }, + { + "id": "5242", + "name": "Penance Healer" + }, + { + "id": "5243", + "name": "Penance Healer" + }, + { + "id": "5244", + "name": "Penance Healer" + }, + { + "id": "5245", + "name": "Penance Healer" + }, + { + "id": "5246", + "name": "Penance Healer" + }, + { + "id": "5255", + "name": "Locust rider" + }, + { + "id": "5256", + "name": "Locust rider" + }, + { + "id": "5257", + "name": "Banker" + }, + { + "id": "5259", + "name": "Banker" + }, + { + "id": "5261", + "name": "Stonemason" + }, + { + "id": "5263", + "name": "Nathifa" + }, + { + "id": "5265", + "name": "Urbi" + }, + { + "id": "5267", + "name": "Jamila" + }, + { + "id": "5269", + "name": "Sophanem guard" + }, + { + "id": "5271", + "name": "Sophanem guard" + }, + { + "id": "5273", + "name": "Sophanem guard" + }, + { + "id": "5275", + "name": "Sophanem guard" + }, + { + "id": "5278", + "name": "Coenus" + }, + { + "id": "5279", + "name": "Jex" + }, + { + "id": "5280", + "name": "Maisa" + }, + { + "id": "5282", + "name": "Osman" + }, + { + "id": "5286", + "name": "Osman" + }, + { + "id": "5287", + "name": "Osman" + }, + { + "id": "5288", + "name": "Embalmer" + }, + { + "id": "5289", + "name": "Carpenter" + }, + { + "id": "5290", + "name": "Linen worker" + }, + { + "id": "5291", + "name": "Priest" + }, + { + "id": "5292", + "name": "Giant scarab" + }, + { + "id": "5360", + "name": "Mummy ashes" + }, + { + "id": "5383", + "name": "Odovacar" + }, + { + "id": "5415", + "name": "Terror dog statue" + }, + { + "id": "5416", + "name": "Terror dog statue" + }, + { + "id": "5419", + "name": "Tarn" + }, + { + "id": "5423", + "name": "Larry" + }, + { + "id": "5425", + "name": "Larry" + }, + { + "id": "5426", + "name": "Larry" + }, + { + "id": "5427", + "name": "Penguin" + }, + { + "id": "5429", + "name": "Penguin" + }, + { + "id": "5430", + "name": "Penguin" + }, + { + "id": "5431", + "name": "KGP Guard" + }, + { + "id": "5432", + "name": "Pescaling Pax" + }, + { + "id": "5433", + "name": "Ping" + }, + { + "id": "5434", + "name": "Ping" + }, + { + "id": "5435", + "name": "Pong" + }, + { + "id": "5436", + "name": "Pong" + }, + { + "id": "5437", + "name": "Ping" + }, + { + "id": "5438", + "name": "Pong" + }, + { + "id": "5443", + "name": "Noodle" + }, + { + "id": "5445", + "name": "Penguin" + }, + { + "id": "5446", + "name": "Penguin suit" + }, + { + "id": "5449", + "name": "Penguin" + }, + { + "id": "5450", + "name": "Penguin" + }, + { + "id": "5451", + "name": "Penguin" + }, + { + "id": "5456", + "name": "Crusher" + }, + { + "id": "5457", + "name": "Crusher" + }, + { + "id": "5458", + "name": "Crusher" + }, + { + "id": "5459", + "name": "Crusher" + }, + { + "id": "5460", + "name": "Tree" + }, + { + "id": "5461", + "name": "Jungle Tree" + }, + { + "id": "5462", + "name": "Tolna" + }, + { + "id": "5463", + "name": "Honour guard" + }, + { + "id": "5464", + "name": "Honour guard" + }, + { + "id": "5465", + "name": "Fridleif Shieldson" + }, + { + "id": "5466", + "name": "Thakkrad Sigmundson" + }, + { + "id": "5467", + "name": "Iceberg" + }, + { + "id": "5468", + "name": "Iceberg" + }, + { + "id": "5469", + "name": "Arctic Pine" + }, + { + "id": "5470", + "name": "Fishing spot" + }, + { + "id": "5471", + "name": "Fishing spot" + }, + { + "id": "5477", + "name": "Bork Sigmundson" + }, + { + "id": "5481", + "name": "Mord Gunnars" + }, + { + "id": "5482", + "name": "Mord Gunnars" + }, + { + "id": "5498", + "name": "Miner" + }, + { + "id": "5502", + "name": "Grundt" + }, + { + "id": "5503", + "name": "Mawnis Burowgar" + }, + { + "id": "5504", + "name": "Mawnis Burowgar" + }, + { + "id": "5505", + "name": "Fridleif Shieldson" + }, + { + "id": "5506", + "name": "Thakkrad Sigmundson" + }, + { + "id": "5507", + "name": "Maria Gunnars" + }, + { + "id": "5508", + "name": "Maria Gunnars" + }, + { + "id": "5509", + "name": "Jofridr Mordstatter" + }, + { + "id": "5510", + "name": "Morten Holdstrom" + }, + { + "id": "5511", + "name": "Gunnar Holdstrom" + }, + { + "id": "5512", + "name": "Anne Isaakson" + }, + { + "id": "5513", + "name": "Lisse Isaakson" + }, + { + "id": "5518", + "name": "Kjedelig Uppsen" + }, + { + "id": "5519", + "name": "Trogen Konungarde" + }, + { + "id": "5520", + "name": "Slug Hemligssen" + }, + { + "id": "5528", + "name": "Ice troll grunt" + }, + { + "id": "5530", + "name": "Sorceress" + }, + { + "id": "5560", + "name": "Osman" + }, + { + "id": "5562", + "name": "Del-Monty" + }, + { + "id": "5564", + "name": "Bouncer" + }, + { + "id": "5565", + "name": "Bouncer" + }, + { + "id": "5566", + "name": "General Khazard" + }, + { + "id": "5567", + "name": "Scout" + }, + { + "id": "5568", + "name": "Scout" + }, + { + "id": "5569", + "name": "Scout" + }, + { + "id": "5570", + "name": "Scout" + }, + { + "id": "5573", + "name": "Effigy" + }, + { + "id": "5579", + "name": "Effigy" + }, + { + "id": "5580", + "name": "Bonafido" + }, + { + "id": "5582", + "name": "Homunculus" + }, + { + "id": "5583", + "name": "Homunculus" + }, + { + "id": "5585", + "name": "'Transmute' The Alchemist" + }, + { + "id": "5586", + "name": "'Transmute' The Alchemist" + }, + { + "id": "5587", + "name": "'Currency' The Alchemist" + }, + { + "id": "5588", + "name": "'Currency' The Alchemist" + }, + { + "id": "5592", + "name": "'The Guns'" + }, + { + "id": "5598", + "name": "Unicow" + }, + { + "id": "5604", + "name": "Elfinlocks" + }, + { + "id": "5605", + "name": "Clockwork cat" + }, + { + "id": "5606", + "name": "Clockwork cat" + }, + { + "id": "5612", + "name": "Rufus" + }, + { + "id": "5613", + "name": "Mi-Gor" + }, + { + "id": "5615", + "name": "Puffin" + }, + { + "id": "5616", + "name": "Brother Tranquility" + }, + { + "id": "5617", + "name": "Brother Tranquility" + }, + { + "id": "5618", + "name": "Brother Tranquility" + }, + { + "id": "5623", + "name": "Zombie monk" + }, + { + "id": "5624", + "name": "Zombie monk" + }, + { + "id": "5625", + "name": "Zombie monk" + }, + { + "id": "5626", + "name": "Zombie monk" + }, + { + "id": "5667", + "name": "Undead Lumberjack" + }, + { + "id": "5679", + "name": "Undead Lumberjack" + }, + { + "id": "5681", + "name": "Undead Lumberjack" + }, + { + "id": "5682", + "name": "Undead Lumberjack" + }, + { + "id": "5683", + "name": "Undead Lumberjack" + }, + { + "id": "5684", + "name": "Undead Lumberjack" + }, + { + "id": "5685", + "name": "Undead Lumberjack" + }, + { + "id": "5686", + "name": "Undead Lumberjack" + }, + { + "id": "5687", + "name": "Undead Lumberjack" + }, + { + "id": "5688", + "name": "Undead Lumberjack" + }, + { + "id": "5689", + "name": "Undead Lumberjack" + }, + { + "id": "5690", + "name": "Undead Lumberjack" + }, + { + "id": "5691", + "name": "Undead Lumberjack" + }, + { + "id": "5692", + "name": "Undead Lumberjack" + }, + { + "id": "5693", + "name": "Undead Lumberjack" + }, + { + "id": "5694", + "name": "Undead Lumberjack" + }, + { + "id": "5695", + "name": "Undead Lumberjack" + }, + { + "id": "5696", + "name": "Undead Lumberjack" + }, + { + "id": "5697", + "name": "Undead Lumberjack" + }, + { + "id": "5698", + "name": "Undead Lumberjack" + }, + { + "id": "5699", + "name": "Undead Lumberjack" + }, + { + "id": "5700", + "name": "Undead Lumberjack" + }, + { + "id": "5701", + "name": "Undead Lumberjack" + }, + { + "id": "5702", + "name": "Undead Lumberjack" + }, + { + "id": "5703", + "name": "Undead Lumberjack" + }, + { + "id": "5704", + "name": "Undead Lumberjack" + }, + { + "id": "5705", + "name": "Undead Lumberjack" + }, + { + "id": "5706", + "name": "Undead Lumberjack" + }, + { + "id": "5707", + "name": "Undead Lumberjack" + }, + { + "id": "5708", + "name": "Undead Lumberjack" + }, + { + "id": "5709", + "name": "Undead Lumberjack" + }, + { + "id": "5710", + "name": "Undead Lumberjack" + }, + { + "id": "5711", + "name": "Undead Lumberjack" + }, + { + "id": "5712", + "name": "Undead Lumberjack" + }, + { + "id": "5713", + "name": "Undead Lumberjack" + }, + { + "id": "5714", + "name": "Undead Lumberjack" + }, + { + "id": "5715", + "name": "Undead Lumberjack" + }, + { + "id": "5716", + "name": "Undead Lumberjack" + }, + { + "id": "5717", + "name": "Undead Lumberjack" + }, + { + "id": "5718", + "name": "Undead Lumberjack" + }, + { + "id": "5719", + "name": "Undead Lumberjack" + }, + { + "id": "5720", + "name": "Undead Lumberjack" + }, + { + "id": "5721", + "name": "Undead Lumberjack" + }, + { + "id": "5722", + "name": "Undead Lumberjack" + }, + { + "id": "5723", + "name": "Undead Lumberjack" + }, + { + "id": "5724", + "name": "Undead Lumberjack" + }, + { + "id": "5725", + "name": "Undead Lumberjack" + }, + { + "id": "5726", + "name": "Undead Lumberjack" + }, + { + "id": "5727", + "name": "Undead Lumberjack" + }, + { + "id": "5728", + "name": "Undead Lumberjack" + }, + { + "id": "5729", + "name": "Undead Lumberjack" + }, + { + "id": "5730", + "name": "Undead Lumberjack" + }, + { + "id": "5731", + "name": "Undead Lumberjack" + }, + { + "id": "5732", + "name": "Undead Lumberjack" + }, + { + "id": "5733", + "name": "Undead Lumberjack" + }, + { + "id": "5734", + "name": "Undead Lumberjack" + }, + { + "id": "5735", + "name": "Undead Lumberjack" + }, + { + "id": "5736", + "name": "Undead Lumberjack" + }, + { + "id": "5737", + "name": "Undead Lumberjack" + }, + { + "id": "5738", + "name": "Undead Lumberjack" + }, + { + "id": "5739", + "name": "Undead Lumberjack" + }, + { + "id": "5740", + "name": "Undead Lumberjack" + }, + { + "id": "5741", + "name": "Undead Lumberjack" + }, + { + "id": "5742", + "name": "Undead Lumberjack" + }, + { + "id": "5743", + "name": "Undead Lumberjack" + }, + { + "id": "5744", + "name": "Undead Lumberjack" + }, + { + "id": "5745", + "name": "Undead Lumberjack" + }, + { + "id": "5746", + "name": "Undead Lumberjack" + }, + { + "id": "5747", + "name": "Undead Lumberjack" + }, + { + "id": "5748", + "name": "Fishing spot" + }, + { + "id": "5749", + "name": "Fishing spot" + }, + { + "id": "5770", + "name": "Ur-zek" + }, + { + "id": "5771", + "name": "Ur-vass" + }, + { + "id": "5772", + "name": "Ur-taal" + }, + { + "id": "5773", + "name": "Ur-meg" + }, + { + "id": "5774", + "name": "Ur-lun" + }, + { + "id": "5775", + "name": "Ur-pel" + }, + { + "id": "5778", + "name": "Bartak" + }, + { + "id": "5779", + "name": "Turgall" + }, + { + "id": "5780", + "name": "Reldak" + }, + { + "id": "5781", + "name": "Miltog" + }, + { + "id": "5782", + "name": "Mernik" + }, + { + "id": "5787", + "name": "Gourmet" + }, + { + "id": "5789", + "name": "Gourmet" + }, + { + "id": "5790", + "name": "Gourmet" + }, + { + "id": "5791", + "name": "Gourmet" + }, + { + "id": "5792", + "name": "Turgok" + }, + { + "id": "5793", + "name": "Markog" + }, + { + "id": "5794", + "name": "Durgok" + }, + { + "id": "5795", + "name": "Tindar" + }, + { + "id": "5796", + "name": "Gundik" + }, + { + "id": "5797", + "name": "Zenkog" + }, + { + "id": "5798", + "name": "Lurgon" + }, + { + "id": "5799", + "name": "Ur-tag" + }, + { + "id": "5802", + "name": "Young 'un" + }, + { + "id": "5804", + "name": "Tyke" + }, + { + "id": "5806", + "name": "Nipper" + }, + { + "id": "5825", + "name": "Movario" + }, + { + "id": "5826", + "name": "Darve" + }, + { + "id": "5828", + "name": "Barlak" + }, + { + "id": "5830", + "name": "Rat Burgiss" + }, + { + "id": "5835", + "name": "Surok Magis" + }, + { + "id": "5836", + "name": "Zaff" + }, + { + "id": "5837", + "name": "Anna Jones" + }, + { + "id": "5838", + "name": "King Roald" + }, + { + "id": "5839", + "name": "Mishkal'un Dorn" + }, + { + "id": "5840", + "name": "Dakh'thoulan Aegis" + }, + { + "id": "5841", + "name": "Sil'as Dahcsnu" + }, + { + "id": "5853", + "name": "Bench" + }, + { + "id": "5857", + "name": "Zanik" + }, + { + "id": "5858", + "name": "Ur-tag" + }, + { + "id": "5862", + "name": "Sigmund and Zanik" + }, + { + "id": "5863", + "name": "Ambassador Alvijar" + }, + { + "id": "5868", + "name": "Tegdak" + }, + { + "id": "5869", + "name": "Zanik" + }, + { + "id": "5871", + "name": "Sergeant Mossfists" + }, + { + "id": "5872", + "name": "Sergeant Slimetoes" + }, + { + "id": "5887", + "name": "Cyrisus" + }, + { + "id": "5894", + "name": "Cyrisus" + }, + { + "id": "5895", + "name": "Cyrisus" + }, + { + "id": "5896", + "name": "Cyrisus" + }, + { + "id": "5897", + "name": "Cyrisus" + }, + { + "id": "5898", + "name": "'Bird's-Eye' Jack" + }, + { + "id": "5899", + "name": "The Inadequacy" + }, + { + "id": "5907", + "name": "The Illusive" + }, + { + "id": "5912", + "name": "Banker" + }, + { + "id": "5913", + "name": "Banker" + }, + { + "id": "5915", + "name": "Elsie" + }, + { + "id": "5918", + "name": "Stray dog" + }, + { + "id": "5932", + "name": "Barnabus Hurma" + }, + { + "id": "5933", + "name": "Marius Giste" + }, + { + "id": "5934", + "name": "Caden Azro" + }, + { + "id": "5935", + "name": "Thias Leacke" + }, + { + "id": "5936", + "name": "Sinco Doar" + }, + { + "id": "5937", + "name": "Tinse Torpe" + }, + { + "id": "5939", + "name": "Torrcs" + }, + { + "id": "5940", + "name": "Marfet" + }, + { + "id": "5941", + "name": "Museum guard" + }, + { + "id": "5942", + "name": "Museum guard" + }, + { + "id": "5943", + "name": "Museum guard" + }, + { + "id": "5946", + "name": "Schoolboy" + }, + { + "id": "5948", + "name": "Teacher and pupil" + }, + { + "id": "5949", + "name": "Schoolboy" + }, + { + "id": "5950", + "name": "Teacher" + }, + { + "id": "5951", + "name": "Schoolgirl" + }, + { + "id": "5953", + "name": "Workman" + }, + { + "id": "5955", + "name": "Workman" + }, + { + "id": "5957", + "name": "Schoolgirl" + }, + { + "id": "5964", + "name": "Ed Wood" + }, + { + "id": "5965", + "name": "Orlando Smith" + }, + { + "id": "5967", + "name": "Natural historian" + }, + { + "id": "5968", + "name": "Natural historian" + }, + { + "id": "5969", + "name": "Natural historian" + }, + { + "id": "5970", + "name": "Natural historian" + }, + { + "id": "5983", + "name": "Schoolgirl" + }, + { + "id": "5984", + "name": "Schoolgirl" + }, + { + "id": "5985", + "name": "Schoolgirl" + }, + { + "id": "5988", + "name": "Miazrqa" + }, + { + "id": "5989", + "name": "Grimgnash" + }, + { + "id": "5991", + "name": "Drain pipe" + }, + { + "id": "5995", + "name": "Mouse" + }, + { + "id": "5997", + "name": "Rupert the Beard" + }, + { + "id": "6000", + "name": "Rupert the Beard" + }, + { + "id": "6002", + "name": "Gnome" + }, + { + "id": "6003", + "name": "Winkin" + }, + { + "id": "6004", + "name": "Gnome" + }, + { + "id": "6005", + "name": "Cage" + }, + { + "id": "6071", + "name": "Immenizz" + }, + { + "id": "6075", + "name": "Cyclops" + }, + { + "id": "6082", + "name": "Captain Ned" + }, + { + "id": "6085", + "name": "Cabin boy Jenkins" + }, + { + "id": "6086", + "name": "Cabin boy Jenkins" + }, + { + "id": "6087", + "name": "Elvarg" + }, + { + "id": "6114", + "name": "Drake" + }, + { + "id": "6119", + "name": "Observatory professor" + }, + { + "id": "6130", + "name": "Clothears" + }, + { + "id": "6138", + "name": "Town crier" + }, + { + "id": "6139", + "name": "Town crier" + }, + { + "id": "6158", + "name": "Sir Lucan" + }, + { + "id": "6160", + "name": "Sir Lancelot" + }, + { + "id": "6161", + "name": "Sir Bedivere" + }, + { + "id": "6162", + "name": "Sir Tristram" + }, + { + "id": "6163", + "name": "Sir Pelleas" + }, + { + "id": "6164", + "name": "Sir Gawain" + }, + { + "id": "6165", + "name": "Sir Kay" + }, + { + "id": "6166", + "name": "Sir Pelleas" + }, + { + "id": "6167", + "name": "Sir Gawain" + }, + { + "id": "6168", + "name": "Sir Kay" + }, + { + "id": "6171", + "name": "Sir Kay" + }, + { + "id": "6172", + "name": "Sir Gawain" + }, + { + "id": "6173", + "name": "Sir Lucan" + }, + { + "id": "6174", + "name": "Bandit" + }, + { + "id": "6175", + "name": "Sir Tristram" + }, + { + "id": "6176", + "name": "Sir Pelleas" + }, + { + "id": "6177", + "name": "Sir Bedivere" + }, + { + "id": "6178", + "name": "Anna" + }, + { + "id": "6179", + "name": "David" + }, + { + "id": "6180", + "name": "Anna" + }, + { + "id": "6181", + "name": "Court judge" + }, + { + "id": "6182", + "name": "Jury" + }, + { + "id": "6185", + "name": "Prosecutor" + }, + { + "id": "6186", + "name": "Morgan Le Faye" + }, + { + "id": "6191", + "name": "Sinclair" + }, + { + "id": "6199", + "name": "Banker" + }, + { + "id": "6202", + "name": "K'ril Tsutsaroth" + }, + { + "id": "6284", + "name": "Warped terrorbird" + }, + { + "id": "6298", + "name": "Jeffery" + }, + { + "id": "6299", + "name": "Big monolith" + }, + { + "id": "6300", + "name": "Small monolith" + }, + { + "id": "6301", + "name": "Cute creature" + }, + { + "id": "6302", + "name": "Evil creature" + }, + { + "id": "6303", + "name": "Yewnock the engineer" + }, + { + "id": "6304", + "name": "Bolrie" + }, + { + "id": "6305", + "name": "Hazelmere" + }, + { + "id": "6307", + "name": "Advisor" + }, + { + "id": "6308", + "name": "King Argenthorg" + }, + { + "id": "6309", + "name": "Prince Argenthorg" + }, + { + "id": "6310", + "name": "Cute creature" + }, + { + "id": "6312", + "name": "Evil creature" + }, + { + "id": "6313", + "name": "Terrorbird servant" + }, + { + "id": "6316", + "name": "Guard no. 21" + }, + { + "id": "6317", + "name": "Guard no. 72" + }, + { + "id": "6318", + "name": "Longramble" + }, + { + "id": "6319", + "name": "Spirit tree" + }, + { + "id": "6321", + "name": "Spirit tree" + }, + { + "id": "6333", + "name": "Child" + }, + { + "id": "6340", + "name": "Child" + }, + { + "id": "6341", + "name": "Child" + }, + { + "id": "6342", + "name": "Child" + }, + { + "id": "6343", + "name": "Child" + }, + { + "id": "6345", + "name": "Child" + }, + { + "id": "6357", + "name": "Street urchin" + }, + { + "id": "6359", + "name": "Street urchin" + }, + { + "id": "6360", + "name": "Street urchin" + }, + { + "id": "6361", + "name": "Street urchin" + }, + { + "id": "6362", + "name": "Eniola" + }, + { + "id": "6373", + "name": "Kennith" + }, + { + "id": "6375", + "name": "Wizard Cromperty" + }, + { + "id": "6384", + "name": "Karamjan Jungle Eagle" + }, + { + "id": "6386", + "name": "Bandit" + }, + { + "id": "6391", + "name": "Glough" + }, + { + "id": "6392", + "name": "Oldak" + }, + { + "id": "6393", + "name": "Zanik" + }, + { + "id": "6394", + "name": "Zanik" + }, + { + "id": "6396", + "name": "Zanik" + }, + { + "id": "6398", + "name": "Zanik" + }, + { + "id": "6400", + "name": "Oldak" + }, + { + "id": "6468", + "name": "Skoblin" + }, + { + "id": "6474", + "name": "Snothead" + }, + { + "id": "6475", + "name": "Snailfeet" + }, + { + "id": "6476", + "name": "Mosschin" + }, + { + "id": "6477", + "name": "Redeyes" + }, + { + "id": "6478", + "name": "Strongbones" + }, + { + "id": "6479", + "name": "Grubfoot" + }, + { + "id": "6480", + "name": "Grubfoot" + }, + { + "id": "6483", + "name": "Priest" + }, + { + "id": "6484", + "name": "Priest" + }, + { + "id": "6485", + "name": "Priest" + }, + { + "id": "6486", + "name": "Priest" + }, + { + "id": "6487", + "name": "Priest" + }, + { + "id": "6489", + "name": "High priest" + }, + { + "id": "6505", + "name": "Registrar 1" + }, + { + "id": "6511", + "name": "Jury" + }, + { + "id": "6513", + "name": "Spectator" + }, + { + "id": "6515", + "name": "Spectator" + }, + { + "id": "6517", + "name": "Spectator" + }, + { + "id": "6519", + "name": "Spectator" + }, + { + "id": "6520", + "name": "Head Registrar" + }, + { + "id": "6537", + "name": "Mandrith" + }, + { + "id": "6538", + "name": "Banker" + }, + { + "id": "6539", + "name": "Charley the Cleaner" + }, + { + "id": "6540", + "name": "Scotty the Cleaner" + }, + { + "id": "6541", + "name": "Sanchez the Cleaner" + }, + { + "id": "6542", + "name": "Summer Bonde" + }, + { + "id": "6566", + "name": "Broken grave marker" + }, + { + "id": "6567", + "name": "Collapsing grave marker" + }, + { + "id": "6568", + "name": "Grave marker" + }, + { + "id": "6569", + "name": "Broken grave marker" + }, + { + "id": "6570", + "name": "Collapsing grave marker" + }, + { + "id": "6571", + "name": "Gravestone" + }, + { + "id": "6572", + "name": "Broken gravestone" + }, + { + "id": "6573", + "name": "Collapsing gravestone" + }, + { + "id": "6574", + "name": "Gravestone" + }, + { + "id": "6575", + "name": "Broken gravestone" + }, + { + "id": "6576", + "name": "Collapsing gravestone" + }, + { + "id": "6577", + "name": "Gravestone" + }, + { + "id": "6578", + "name": "Broken gravestone" + }, + { + "id": "6579", + "name": "Collapsing gravestone" + }, + { + "id": "6580", + "name": "Stele" + }, + { + "id": "6581", + "name": "Broken stele" + }, + { + "id": "6582", + "name": "Collapsing stele" + }, + { + "id": "6583", + "name": "Saradomin symbol" + }, + { + "id": "6584", + "name": "Broken Saradomin symbol" + }, + { + "id": "6585", + "name": "Collapsing Saradomin symbol" + }, + { + "id": "6586", + "name": "Zamorak symbol" + }, + { + "id": "6587", + "name": "Broken Zamorak symbol" + }, + { + "id": "6588", + "name": "Collapsing Zamorak symbol" + }, + { + "id": "6589", + "name": "Guthix symbol" + }, + { + "id": "6590", + "name": "Broken Guthix symbol" + }, + { + "id": "6591", + "name": "Collapsing Guthix symbol" + }, + { + "id": "6592", + "name": "Bandos symbol" + }, + { + "id": "6593", + "name": "Broken Bandos symbol" + }, + { + "id": "6594", + "name": "Collapsing Bandos symbol" + }, + { + "id": "6595", + "name": "Armadyl symbol" + }, + { + "id": "6596", + "name": "Broken Armadyl symbol" + }, + { + "id": "6597", + "name": "Collapsing Armadyl symbol" + }, + { + "id": "6598", + "name": "Memorial stone" + }, + { + "id": "6599", + "name": "Broken memorial stone" + }, + { + "id": "6600", + "name": "Collapsing memorial stone" + }, + { + "id": "6601", + "name": "Memorial stone" + }, + { + "id": "6602", + "name": "Broken memorial stone" + }, + { + "id": "6603", + "name": "Collapsing memorial stone" + }, + { + "id": "6732", + "name": "Snow imp" + }, + { + "id": "6733", + "name": "Snow imp" + }, + { + "id": "6734", + "name": "Snow imp" + }, + { + "id": "6735", + "name": "Snow imp" + }, + { + "id": "6736", + "name": "Snow imp" + }, + { + "id": "6737", + "name": "Snow imp" + }, + { + "id": "6738", + "name": "Snow imp" + }, + { + "id": "6741", + "name": "Snow" + }, + { + "id": "6746", + "name": "Snowman" + }, + { + "id": "6751", + "name": "Bulldog" + }, + { + "id": "6753", + "name": "Mummy" + }, + { + "id": "6754", + "name": "Mummy" + }, + { + "id": "6755", + "name": "Mummy" + }, + { + "id": "6756", + "name": "Mummy" + }, + { + "id": "6757", + "name": "Mummy" + }, + { + "id": "6758", + "name": "Mummy" + }, + { + "id": "6759", + "name": "Mummy" + }, + { + "id": "6760", + "name": "Mummy" + }, + { + "id": "6771", + "name": "Giant scarab" + }, + { + "id": "6775", + "name": "Scabaras priest" + }, + { + "id": "6782", + "name": "Maisa" + }, + { + "id": "6783", + "name": "Maisa" + }, + { + "id": "6784", + "name": "Priest" + }, + { + "id": "6791", + "name": "High Priest of Scabaras" + }, + { + "id": "6792", + "name": "Vulture" + }, + { + "id": "6793", + "name": "Spirit terrorbird" + }, + { + "id": "6808", + "name": "Beaver" + }, + { + "id": "6898", + "name": "Pet shop owner" + }, + { + "id": "6899", + "name": "Bulldog" + }, + { + "id": "6908", + "name": "Baby penguin" + }, + { + "id": "6909", + "name": "Penguin" + }, + { + "id": "6910", + "name": "Penguin" + }, + { + "id": "6911", + "name": "Raven chick" + }, + { + "id": "6912", + "name": "Raven" + }, + { + "id": "6913", + "name": "Baby raccoon" + }, + { + "id": "6914", + "name": "Raccoon" + }, + { + "id": "6915", + "name": "Baby gecko" + }, + { + "id": "6916", + "name": "Gecko" + }, + { + "id": "6918", + "name": "Gecko" + }, + { + "id": "6919", + "name": "Baby squirrel" + }, + { + "id": "6920", + "name": "Squirrel" + }, + { + "id": "6922", + "name": "Baby chameleon" + }, + { + "id": "6923", + "name": "Chameleon" + }, + { + "id": "6924", + "name": "Baby chameleon" + }, + { + "id": "6925", + "name": "Chameleon" + }, + { + "id": "6926", + "name": "Baby chameleon" + }, + { + "id": "6927", + "name": "Chameleon" + }, + { + "id": "6928", + "name": "Baby chameleon" + }, + { + "id": "6929", + "name": "Chameleon" + }, + { + "id": "6930", + "name": "Baby chameleon" + }, + { + "id": "6931", + "name": "Chameleon" + }, + { + "id": "6932", + "name": "Baby chameleon" + }, + { + "id": "6933", + "name": "Chameleon" + }, + { + "id": "6934", + "name": "Baby chameleon" + }, + { + "id": "6935", + "name": "Chameleon" + }, + { + "id": "6936", + "name": "Baby chameleon" + }, + { + "id": "6937", + "name": "Chameleon" + }, + { + "id": "6938", + "name": "Baby chameleon" + }, + { + "id": "6939", + "name": "Chameleon" + }, + { + "id": "6940", + "name": "Baby chameleon" + }, + { + "id": "6941", + "name": "Chameleon" + }, + { + "id": "6945", + "name": "Vulture chick" + }, + { + "id": "6946", + "name": "Vulture" + }, + { + "id": "6947", + "name": "Baby giant crab" + }, + { + "id": "6948", + "name": "Giant crab" + }, + { + "id": "6949", + "name": "Saradomin chick" + }, + { + "id": "6950", + "name": "Saradomin bird" + }, + { + "id": "6951", + "name": "Saradomin owl" + }, + { + "id": "6952", + "name": "Zamorak chick" + }, + { + "id": "6953", + "name": "Zamorak bird" + }, + { + "id": "6954", + "name": "Zamorak hawk" + }, + { + "id": "6955", + "name": "Guthix chick" + }, + { + "id": "6956", + "name": "Guthix bird" + }, + { + "id": "6957", + "name": "Guthix raptor" + }, + { + "id": "6970", + "name": "Pikkupstix" + }, + { + "id": "6988", + "name": "Giant wolpertinger" + }, + { + "id": "6991", + "name": "Ibis" + }, + { + "id": "6996", + "name": "Fishing spot" + }, + { + "id": "7000", + "name": "Dark Squall" + }, + { + "id": "7002", + "name": "Surok Magis" + }, + { + "id": "7006", + "name": "Grenwall" + }, + { + "id": "7015", + "name": "Platypus" + }, + { + "id": "7016", + "name": "Platypus" + }, + { + "id": "7017", + "name": "Platypus" + }, + { + "id": "7018", + "name": "Baby platypus" + }, + { + "id": "7019", + "name": "Baby platypus" + }, + { + "id": "7020", + "name": "Baby platypus" + }, + { + "id": "7022", + "name": "Platypus" + }, + { + "id": "7023", + "name": "Platypus" + }, + { + "id": "7025", + "name": "Baby platypus" + }, + { + "id": "7026", + "name": "Baby platypus" + }, + { + "id": "7027", + "name": "Patrick" + }, + { + "id": "7028", + "name": "Penelope" + }, + { + "id": "7029", + "name": "Peter" + }, + { + "id": "7030", + "name": "Peanut" + }, + { + "id": "7032", + "name": "Diseased kebbit" + }, + { + "id": "7040", + "name": "Fishing spot" + }, + { + "id": "7045", + "name": "Fishing spot" + }, + { + "id": "7046", + "name": "Fishing spot" + }, + { + "id": "7048", + "name": "Frawd" + }, + { + "id": "7050", + "name": "Ogress banker" + }, + { + "id": "7052", + "name": "Seegud" + }, + { + "id": "7053", + "name": "Chargurr" + }, + { + "id": "7054", + "name": "Chargurr" + }, + { + "id": "7055", + "name": "Snurgh" + }, + { + "id": "7058", + "name": "Kringk" + }, + { + "id": "7059", + "name": "Thump" + }, + { + "id": "7060", + "name": "Massage table" + }, + { + "id": "7061", + "name": "Thump" + }, + { + "id": "7062", + "name": "Muggh" + }, + { + "id": "7063", + "name": "Kringk" + }, + { + "id": "7064", + "name": "Hairdryer" + }, + { + "id": "7065", + "name": "Snert" + }, + { + "id": "7068", + "name": "Tyke" + }, + { + "id": "7069", + "name": "Snarrl" + }, + { + "id": "7070", + "name": "Snarrk" + }, + { + "id": "7071", + "name": "I'rk" + }, + { + "id": "7072", + "name": "Thuddley" + }, + { + "id": "7073", + "name": "Grr'bah" + }, + { + "id": "7074", + "name": "Chomp" + }, + { + "id": "7075", + "name": "Grubb" + }, + { + "id": "7076", + "name": "Grunther" + }, + { + "id": "7077", + "name": "Glum" + }, + { + "id": "7083", + "name": "Flying bugs" + }, + { + "id": "7087", + "name": "Balnea" + }, + { + "id": "7088", + "name": "Chief Tess" + }, + { + "id": "7089", + "name": "Chargurr" + }, + { + "id": "7090", + "name": "Wise Old Man" + }, + { + "id": "7091", + "name": "Dawg" + }, + { + "id": "7116", + "name": "Drunken sailor" + }, + { + "id": "7117", + "name": "Drunken sailor" + }, + { + "id": "7118", + "name": "Catapult engineer" + }, + { + "id": "7119", + "name": "Tyras guard" + }, + { + "id": "7121", + "name": "General Hining" + }, + { + "id": "7122", + "name": "Githan" + }, + { + "id": "7123", + "name": "Amulet of Nature" + }, + { + "id": "7124", + "name": "Mud" + }, + { + "id": "7136", + "name": "Surok Magis" + }, + { + "id": "7143", + "name": "Professor Henry" + }, + { + "id": "7163", + "name": "Villager" + }, + { + "id": "7165", + "name": "Villager" + }, + { + "id": "7166", + "name": "Villager" + }, + { + "id": "7167", + "name": "Villager" + }, + { + "id": "7169", + "name": "Kimberly" + }, + { + "id": "7170", + "name": "Kimberly" + }, + { + "id": "7171", + "name": "Kennith" + }, + { + "id": "7172", + "name": "Kennith" + }, + { + "id": "7173", + "name": "Kennith" + }, + { + "id": "7174", + "name": "Kennith" + }, + { + "id": "7175", + "name": "Kennith" + }, + { + "id": "7176", + "name": "Villager" + }, + { + "id": "7184", + "name": "Ezekial Lovecraft" + }, + { + "id": "7185", + "name": "Clive" + }, + { + "id": "7186", + "name": "Katherine" + }, + { + "id": "7187", + "name": "Katherine" + }, + { + "id": "7188", + "name": "Clive" + }, + { + "id": "7189", + "name": "Kent" + }, + { + "id": "7190", + "name": "Rabbit hole" + }, + { + "id": "7197", + "name": "Easter Bunny" + }, + { + "id": "7198", + "name": "Bunny" + }, + { + "id": "7199", + "name": "Bunny" + }, + { + "id": "7200", + "name": "Guard bunny" + }, + { + "id": "7201", + "name": "Chocatrice" + }, + { + "id": "7203", + "name": "Void Knight" + }, + { + "id": "7205", + "name": "Mouse" + }, + { + "id": "7208", + "name": "Rabbit" + }, + { + "id": "7261", + "name": "Raven chick" + }, + { + "id": "7262", + "name": "Raven" + }, + { + "id": "7263", + "name": "Raven chick" + }, + { + "id": "7264", + "name": "Raven" + }, + { + "id": "7265", + "name": "Raven chick" + }, + { + "id": "7266", + "name": "Raven" + }, + { + "id": "7267", + "name": "Raven chick" + }, + { + "id": "7268", + "name": "Raven" + }, + { + "id": "7269", + "name": "Raven chick" + }, + { + "id": "7270", + "name": "Raven" + }, + { + "id": "7271", + "name": "Baby raccoon" + }, + { + "id": "7272", + "name": "Raccoon" + }, + { + "id": "7273", + "name": "Baby raccoon" + }, + { + "id": "7274", + "name": "Raccoon" + }, + { + "id": "7276", + "name": "Baby raccoon" + }, + { + "id": "7277", + "name": "Baby gecko" + }, + { + "id": "7278", + "name": "Baby gecko" + }, + { + "id": "7279", + "name": "Baby gecko" + }, + { + "id": "7280", + "name": "Baby gecko" + }, + { + "id": "7281", + "name": "Gecko" + }, + { + "id": "7282", + "name": "Gecko" + }, + { + "id": "7283", + "name": "Gecko" + }, + { + "id": "7284", + "name": "Gecko" + }, + { + "id": "7286", + "name": "Baby gecko" + }, + { + "id": "7287", + "name": "Baby gecko" + }, + { + "id": "7288", + "name": "Baby gecko" + }, + { + "id": "7289", + "name": "Gecko" + }, + { + "id": "7290", + "name": "Gecko" + }, + { + "id": "7291", + "name": "Gecko" + }, + { + "id": "7292", + "name": "Gecko" + }, + { + "id": "7293", + "name": "Baby giant crab" + }, + { + "id": "7294", + "name": "Giant crab" + }, + { + "id": "7295", + "name": "Baby giant crab" + }, + { + "id": "7296", + "name": "Giant crab" + }, + { + "id": "7297", + "name": "Baby giant crab" + }, + { + "id": "7298", + "name": "Giant crab" + }, + { + "id": "7299", + "name": "Baby giant crab" + }, + { + "id": "7300", + "name": "Giant crab" + }, + { + "id": "7301", + "name": "Baby squirrel" + }, + { + "id": "7302", + "name": "Squirrel" + }, + { + "id": "7303", + "name": "Baby squirrel" + }, + { + "id": "7304", + "name": "Squirrel" + }, + { + "id": "7305", + "name": "Baby squirrel" + }, + { + "id": "7306", + "name": "Squirrel" + }, + { + "id": "7307", + "name": "Baby squirrel" + }, + { + "id": "7308", + "name": "Squirrel" + }, + { + "id": "7309", + "name": "Baby squirrel" + }, + { + "id": "7310", + "name": "Baby squirrel" + }, + { + "id": "7311", + "name": "Baby squirrel" + }, + { + "id": "7312", + "name": "Baby squirrel" + }, + { + "id": "7313", + "name": "Baby penguin" + }, + { + "id": "7314", + "name": "Penguin" + }, + { + "id": "7315", + "name": "Penguin" + }, + { + "id": "7316", + "name": "Baby penguin" + }, + { + "id": "7317", + "name": "Penguin" + }, + { + "id": "7318", + "name": "Penguin" + }, + { + "id": "7319", + "name": "Vulture chick" + }, + { + "id": "7320", + "name": "Vulture" + }, + { + "id": "7321", + "name": "Vulture chick" + }, + { + "id": "7322", + "name": "Vulture" + }, + { + "id": "7323", + "name": "Vulture chick" + }, + { + "id": "7324", + "name": "Vulture" + }, + { + "id": "7325", + "name": "Vulture chick" + }, + { + "id": "7326", + "name": "Vulture" + }, + { + "id": "7327", + "name": "Vulture chick" + }, + { + "id": "7328", + "name": "Vulture" + }, + { + "id": "7369", + "name": "Void shifter" + }, + { + "id": "7372", + "name": "Ravenous locust" + }, + { + "id": "7383", + "name": "Uberlass" + }, + { + "id": "7384", + "name": "Uberlass" + }, + { + "id": "7385", + "name": "Uberlass" + }, + { + "id": "7386", + "name": "Uberlass" + }, + { + "id": "7387", + "name": "Sannytea" + }, + { + "id": "7388", + "name": "Sannytea" + }, + { + "id": "7389", + "name": "Irollsixes" + }, + { + "id": "7390", + "name": "Irollsixes" + }, + { + "id": "7391", + "name": "Foxyhunter" + }, + { + "id": "7392", + "name": "Foxyhunter" + }, + { + "id": "7393", + "name": "Foxyhunter" + }, + { + "id": "7394", + "name": "Gabriela" + }, + { + "id": "7395", + "name": "Teodor" + }, + { + "id": "7396", + "name": "Aurel" + }, + { + "id": "7397", + "name": "Cornelius" + }, + { + "id": "7399", + "name": "Sorin" + }, + { + "id": "7400", + "name": "Luscion" + }, + { + "id": "7401", + "name": "Sergiu" + }, + { + "id": "7402", + "name": "Radu" + }, + { + "id": "7403", + "name": "Grigore" + }, + { + "id": "7404", + "name": "Ileana" + }, + { + "id": "7405", + "name": "Valeria" + }, + { + "id": "7406", + "name": "Emilia" + }, + { + "id": "7407", + "name": "Florin" + }, + { + "id": "7408", + "name": "Catalina" + }, + { + "id": "7409", + "name": "Ivan" + }, + { + "id": "7410", + "name": "Victor" + }, + { + "id": "7411", + "name": "Helena" + }, + { + "id": "7412", + "name": "Mihail" + }, + { + "id": "7413", + "name": "Nicoleta" + }, + { + "id": "7414", + "name": "Vasile" + }, + { + "id": "7415", + "name": "Razvan" + }, + { + "id": "7416", + "name": "Luminata" + }, + { + "id": "7418", + "name": "Juvinate" + }, + { + "id": "7419", + "name": "Held vampyre juvinate" + }, + { + "id": "7420", + "name": "Hieronymus Avlafrim" + }, + { + "id": "7421", + "name": "Sasquine Huburns" + }, + { + "id": "7422", + "name": "Sasquine Huburns" + }, + { + "id": "7423", + "name": "Lollery" + }, + { + "id": "7424", + "name": "Wigglewoo" + }, + { + "id": "7427", + "name": "Orangeowns" + }, + { + "id": "7428", + "name": "I like m0m" + }, + { + "id": "7429", + "name": "I like m0m" + }, + { + "id": "7430", + "name": "Qutiedoll" + }, + { + "id": "7431", + "name": "Goreu" + }, + { + "id": "7432", + "name": "Ysgawyn" + }, + { + "id": "7433", + "name": "Arvel" + }, + { + "id": "7434", + "name": "Mawrth" + }, + { + "id": "7435", + "name": "Kelyn" + }, + { + "id": "7436", + "name": "Eoin" + }, + { + "id": "7437", + "name": "Iona" + }, + { + "id": "7442", + "name": "Arianwyn" + }, + { + "id": "7444", + "name": "Oronwen" + }, + { + "id": "7445", + "name": "Banker" + }, + { + "id": "7446", + "name": "Banker" + }, + { + "id": "7447", + "name": "Dalldav" + }, + { + "id": "7448", + "name": "Gethin" + }, + { + "id": "7449", + "name": "Amaethwr" + }, + { + "id": "7450", + "name": "Teclyn" + }, + { + "id": "7451", + "name": "Butterfly" + }, + { + "id": "7452", + "name": "Lapsang" + }, + { + "id": "7453", + "name": "Lapsang" + }, + { + "id": "7454", + "name": "Souchong" + }, + { + "id": "7455", + "name": "Souchong" + }, + { + "id": "7456", + "name": "Earlgrey" + }, + { + "id": "7457", + "name": "Earlgrey" + }, + { + "id": "7458", + "name": "Fairtrade" + }, + { + "id": "7464", + "name": "Sliceoflemon" + }, + { + "id": "7465", + "name": "Sliceoflemon" + }, + { + "id": "7466", + "name": "Milknosugar" + }, + { + "id": "7467", + "name": "Milknosugar" + }, + { + "id": "7468", + "name": "Randomdood" + }, + { + "id": "7469", + "name": "Employedman" + }, + { + "id": "7470", + "name": "Heidiggle" + }, + { + "id": "7471", + "name": "Dodgy Penny" + }, + { + "id": "7472", + "name": "Shadydude98" + }, + { + "id": "7473", + "name": "Madam C" + }, + { + "id": "7474", + "name": "M0m Online" + }, + { + "id": "7478", + "name": "Learking" + }, + { + "id": "7489", + "name": "Moglewee" + }, + { + "id": "7490", + "name": "Moglewee" + }, + { + "id": "7491", + "name": "Sarah Domin" + }, + { + "id": "7498", + "name": "Snowy knight" + }, + { + "id": "7499", + "name": "Sapphire glacialis" + }, + { + "id": "7509", + "name": "Evil Wibbler" + }, + { + "id": "7516", + "name": "Heresjohnny" + }, + { + "id": "7517", + "name": "Mogglewump" + }, + { + "id": "7521", + "name": "Renderorder" + }, + { + "id": "7522", + "name": "Boolean" + }, + { + "id": "7523", + "name": "Stress Diva" + }, + { + "id": "7524", + "name": "Treadsoftly" + }, + { + "id": "7525", + "name": "Helphelphelp" + }, + { + "id": "7526", + "name": "Doorbellpl0x" + }, + { + "id": "7527", + "name": "Fixmydoorup" + }, + { + "id": "7529", + "name": "Wallscaler" + }, + { + "id": "7530", + "name": "2scompany" + }, + { + "id": "7531", + "name": "2scompany" + }, + { + "id": "7533", + "name": "4sjustsilly" + }, + { + "id": "7534", + "name": "Roadblocked" + }, + { + "id": "7535", + "name": "Barricade" + }, + { + "id": "7536", + "name": "Barricade" + }, + { + "id": "7537", + "name": "Yoinker" + }, + { + "id": "7538", + "name": "Yoinker" + }, + { + "id": "7539", + "name": "Stopthief" + }, + { + "id": "7540", + "name": "Stopthief" + }, + { + "id": "7541", + "name": "Knickknack" + }, + { + "id": "7542", + "name": "Paddywhack" + }, + { + "id": "7543", + "name": "Giveadog" + }, + { + "id": "7544", + "name": "Spacebadgers" + }, + { + "id": "7545", + "name": "Freakypeaky" + }, + { + "id": "7546", + "name": "Rollinghome" + }, + { + "id": "7547", + "name": "Nullpointer" + }, + { + "id": "7548", + "name": "Badgerfreak" + }, + { + "id": "7549", + "name": "Windstrike32" + }, + { + "id": "7550", + "name": "Void Knight" + }, + { + "id": "7567", + "name": "Wraithboss" + }, + { + "id": "7568", + "name": "What Goudron" + }, + { + "id": "7574", + "name": "Lvzyoda" + }, + { + "id": "7575", + "name": "Airstriker" + }, + { + "id": "7576", + "name": "Droepedoff" + }, + { + "id": "7577", + "name": "Plzpudding" + }, + { + "id": "7578", + "name": "Assassin10" + }, + { + "id": "7579", + "name": "Steallake" + }, + { + "id": "7581", + "name": "Deepkiwi" + }, + { + "id": "7584", + "name": "Bigface Oz" + }, + { + "id": "7587", + "name": "Torcher" + }, + { + "id": "7588", + "name": "Torcher" + }, + { + "id": "7589", + "name": "Defiler" + }, + { + "id": "7590", + "name": "Defiler" + }, + { + "id": "7591", + "name": "Shifter" + }, + { + "id": "7592", + "name": "Shifter" + }, + { + "id": "7594", + "name": "Shifter" + }, + { + "id": "7595", + "name": "Splatter" + }, + { + "id": "7596", + "name": "Splatter" + }, + { + "id": "7597", + "name": "Splatter" + }, + { + "id": "7598", + "name": "Spinner" + }, + { + "id": "7599", + "name": "Ravager" + }, + { + "id": "7600", + "name": "Fiara" + }, + { + "id": "7601", + "name": "Reggie" + }, + { + "id": "7602", + "name": "Getorix" + }, + { + "id": "7603", + "name": "Pontimer" + }, + { + "id": "7604", + "name": "Alran" + }, + { + "id": "7610", + "name": "Flying female vampire" + }, + { + "id": "7611", + "name": "Flying female vampire" + }, + { + "id": "7612", + "name": "Flying female vampire" + }, + { + "id": "7613", + "name": "Flying female vampire" + }, + { + "id": "7622", + "name": "Vyrewatch" + }, + { + "id": "7623", + "name": "Vyrewatch" + }, + { + "id": "7624", + "name": "Vyrewatch" + }, + { + "id": "7625", + "name": "Vyrewatch" + }, + { + "id": "7630", + "name": "Vyrewatch" + }, + { + "id": "7633", + "name": "Vyrewatch" + }, + { + "id": "7636", + "name": "Fishing spot" + }, + { + "id": "7637", + "name": "Skeletal hand" + }, + { + "id": "7652", + "name": "Zaromark Sliver" + }, + { + "id": "7653", + "name": "Zaromark Sliver" + }, + { + "id": "7662", + "name": "Fistandantilus" + }, + { + "id": "7663", + "name": "Fistandantilus" + }, + { + "id": "7664", + "name": "Mercenary Adventurer" + }, + { + "id": "7665", + "name": "Ivan Strom" + }, + { + "id": "7666", + "name": "Mysterious person" + }, + { + "id": "7667", + "name": "Mysterious person" + }, + { + "id": "7668", + "name": "Mysterious person" + }, + { + "id": "7669", + "name": "Mysterious person" + }, + { + "id": "7670", + "name": "Mysterious person" + }, + { + "id": "7671", + "name": "Mysterious person" + }, + { + "id": "7672", + "name": "Flaygian Screwte" + }, + { + "id": "7673", + "name": "Mekritus A'hara" + }, + { + "id": "7674", + "name": "Andiess Juip" + }, + { + "id": "7675", + "name": "Kael Forshaw" + }, + { + "id": "7676", + "name": "Andiess Juip" + }, + { + "id": "7677", + "name": "Kael Forshaw" + }, + { + "id": "7678", + "name": "Safalaan" + }, + { + "id": "7679", + "name": "Andiess Juip" + }, + { + "id": "7680", + "name": "Kael Forshaw" + }, + { + "id": "7681", + "name": "Safalaan" + }, + { + "id": "7684", + "name": "Vyrewatch" + }, + { + "id": "7685", + "name": "Vyrewatch" + }, + { + "id": "7686", + "name": "Safalaan" + }, + { + "id": "7687", + "name": "Spectral Vyrewatch" + }, + { + "id": "7688", + "name": "Drezel" + }, + { + "id": "7708", + "name": "Temple guardian" + }, + { + "id": "7712", + "name": "Baby icefiend" + }, + { + "id": "7718", + "name": "Brother Bordiss" + }, + { + "id": "7719", + "name": "Brother Althric" + }, + { + "id": "7720", + "name": "Drorkar" + }, + { + "id": "7721", + "name": "Nurmof" + }, + { + "id": "7722", + "name": "Lakki the delivery dwarf" + }, + { + "id": "7723", + "name": "Drorkar" + }, + { + "id": "7724", + "name": "Brother Bordiss" + }, + { + "id": "7725", + "name": "Professor Arblenap" + }, + { + "id": "7726", + "name": "Assistant" + }, + { + "id": "7728", + "name": "Baby icefiend" + }, + { + "id": "7737", + "name": "Will" + }, + { + "id": "7738", + "name": "Will" + }, + { + "id": "7739", + "name": "Phil" + }, + { + "id": "7742", + "name": "Fluffs" + }, + { + "id": "7743", + "name": "Fluffs" + }, + { + "id": "7744", + "name": "Kittens" + }, + { + "id": "7746", + "name": "TzHaar-Mej-Malk" + }, + { + "id": "7748", + "name": "TzHaar-Hur-Frok" + }, + { + "id": "7749", + "name": "TzHaar-Ket-Grol" + }, + { + "id": "7750", + "name": "TzHaar-Ket-Rok" + }, + { + "id": "7751", + "name": "TzHaar-Ket-Lurk" + }, + { + "id": "7753", + "name": "TzHaar-Mej" + }, + { + "id": "7754", + "name": "TzHaar-Hur" + }, + { + "id": "7755", + "name": "TzHaar-Xil" + }, + { + "id": "7757", + "name": "TzHaar-Hur-Brekt" + }, + { + "id": "7758", + "name": "TzHaar-Hur-Brekt" + }, + { + "id": "7759", + "name": "TzHaar-Ket-Jok" + }, + { + "id": "7760", + "name": "TzHaar-Ket-Jok" + }, + { + "id": "7761", + "name": "TzHaar-Xil-Mor" + }, + { + "id": "7762", + "name": "TzHaar-Xil-Mor" + }, + { + "id": "7763", + "name": "TzHaar-Mej-Kol" + }, + { + "id": "7764", + "name": "TzHaar-Mej-Kol" + }, + { + "id": "7765", + "name": "TzHaar-Hur-Klag" + }, + { + "id": "7766", + "name": "TzHaar-Hur-Klag" + }, + { + "id": "7770", + "name": "TokTz-Ket-Dill" + }, + { + "id": "7771", + "name": "TokTz-Ket-Dill" + }, + { + "id": "7774", + "name": "Skeleton" + }, + { + "id": "7775", + "name": "Skeleton" + }, + { + "id": "7776", + "name": "Skeleton" + }, + { + "id": "7777", + "name": "Skeleton" + }, + { + "id": "7778", + "name": "Skeleton" + }, + { + "id": "7779", + "name": "Sumona" + }, + { + "id": "7781", + "name": "Jesmona" + }, + { + "id": "7782", + "name": "Catolax" + }, + { + "id": "7783", + "name": "Ali Cat" + }, + { + "id": "7787", + "name": "Cave crawler" + }, + { + "id": "7788", + "name": "Skeleton" + }, + { + "id": "7789", + "name": "Zombie" + }, + { + "id": "7790", + "name": "Zombie" + }, + { + "id": "7791", + "name": "Zombie" + }, + { + "id": "7792", + "name": "Zombie" + }, + { + "id": "7793", + "name": "Banshee mistress" + }, + { + "id": "7794", + "name": "Banshee mistress" + }, + { + "id": "7795", + "name": "Insectoid assassin" + }, + { + "id": "7796", + "name": "Insectoid assassin" + }, + { + "id": "7797", + "name": "Kurask overlord" + }, + { + "id": "7798", + "name": "Monstrous cave crawler" + }, + { + "id": "7799", + "name": "Basilisk boss" + }, + { + "id": "7800", + "name": "Mightiest turoth" + }, + { + "id": "7801", + "name": "Aberrant spectre" + }, + { + "id": "7802", + "name": "Aberrant spectre" + }, + { + "id": "7803", + "name": "Aberrant spectre" + }, + { + "id": "7804", + "name": "Aberrant spectre" + }, + { + "id": "7805", + "name": "Kurask minion" + }, + { + "id": "7806", + "name": "Mummy warrior" + }, + { + "id": "7807", + "name": "Mummy warrior" + }, + { + "id": "7808", + "name": "Mummy warrior" + }, + { + "id": "7809", + "name": "Cat" + }, + { + "id": "7810", + "name": "Banshee" + }, + { + "id": "7811", + "name": "Kurask" + }, + { + "id": "7812", + "name": "Cave crawler" + }, + { + "id": "7813", + "name": "Basilisk" + }, + { + "id": "7814", + "name": "Turoth" + }, + { + "id": "7815", + "name": "Skeleton" + }, + { + "id": "7816", + "name": "Master" + }, + { + "id": "7817", + "name": "Zombie" + }, + { + "id": "7818", + "name": "Zombie" + }, + { + "id": "7819", + "name": "Zombie" + }, + { + "id": "7820", + "name": "Zombie" + }, + { + "id": "7821", + "name": "A wanderer." + }, + { + "id": "7822", + "name": "A wanderer." + }, + { + "id": "7824", + "name": "Osman" + }, + { + "id": "7825", + "name": "50 Ships Mufassah" + }, + { + "id": "7826", + "name": "Karamthulhu" + }, + { + "id": "7827", + "name": "Karamthulhu" + }, + { + "id": "7828", + "name": "Giant lobster" + }, + { + "id": "7829", + "name": "Giant crab" + }, + { + "id": "7830", + "name": "Customs Sergeant" + }, + { + "id": "7831", + "name": "Customs Sergeant" + }, + { + "id": "7832", + "name": "Young Ralph" + }, + { + "id": "7833", + "name": "Young Ralph" + }, + { + "id": "7834", + "name": "Young Ralph" + }, + { + "id": "7835", + "name": "Young Ralph" + }, + { + "id": "7836", + "name": "Young Ralph" + }, + { + "id": "7837", + "name": "Customs Officer" + }, + { + "id": "7838", + "name": "Customs Officer" + }, + { + "id": "7839", + "name": "Customs Officer" + }, + { + "id": "7840", + "name": "Heavy-Handed Harry" + }, + { + "id": "7841", + "name": "Player" + }, + { + "id": "7842", + "name": "Locker Officer" + }, + { + "id": "7843", + "name": "Locker Officer" + }, + { + "id": "7844", + "name": "Ex-ex-parrot" + }, + { + "id": "7845", + "name": "Pirate impling" + }, + { + "id": "7846", + "name": "Pirate impling" + }, + { + "id": "7847", + "name": "Captain Rabid Jack" + }, + { + "id": "7848", + "name": "Jack" + }, + { + "id": "7849", + "name": "Bosun Giles" + }, + { + "id": "7850", + "name": "Pirate" + }, + { + "id": "7851", + "name": "Lizzie" + }, + { + "id": "7852", + "name": "Cap'n Izzy No-Beard" + }, + { + "id": "7853", + "name": "Ralph" + }, + { + "id": "7854", + "name": "Brass Hand Harry" + }, + { + "id": "7855", + "name": "Bill Teach" + }, + { + "id": "7856", + "name": "Pirate" + }, + { + "id": "7857", + "name": "Brass Hand Harry" + }, + { + "id": "7858", + "name": "Gull" + }, + { + "id": "7861", + "name": "Jack" + }, + { + "id": "7862", + "name": "Fishing spot" + }, + { + "id": "7863", + "name": "Fishing spot" + }, + { + "id": "7864", + "name": "Fishing spot" + }, + { + "id": "7865", + "name": "Guardsman Dante" + }, + { + "id": "7866", + "name": "Guardsman DeShawn" + }, + { + "id": "7867", + "name": "Guardsman Brawn" + }, + { + "id": "7868", + "name": "Iain" + }, + { + "id": "7869", + "name": "Julian" + }, + { + "id": "7870", + "name": "Lachtopher" + }, + { + "id": "7871", + "name": "Samuel" + }, + { + "id": "7872", + "name": "Victoria" + }, + { + "id": "7873", + "name": "Man" + }, + { + "id": "7874", + "name": "Man" + }, + { + "id": "7875", + "name": "Man" + }, + { + "id": "7876", + "name": "Man" + }, + { + "id": "7877", + "name": "Man" + }, + { + "id": "7878", + "name": "Man" + }, + { + "id": "7879", + "name": "Man" + }, + { + "id": "7880", + "name": "Woman" + }, + { + "id": "7881", + "name": "Woman" + }, + { + "id": "7882", + "name": "Woman" + }, + { + "id": "7883", + "name": "Woman" + }, + { + "id": "7884", + "name": "Woman" + }, + { + "id": "7885", + "name": "Guardsman Dante" + }, + { + "id": "7886", + "name": "Guardsman DeShawn" + }, + { + "id": "7887", + "name": "Guardsman Brawn" + }, + { + "id": "7888", + "name": "Sergeant Abram" + }, + { + "id": "7889", + "name": "Guardsman Pazel" + }, + { + "id": "7890", + "name": "Guardsman Peale" + }, + { + "id": "7892", + "name": "General Wartface" + }, + { + "id": "7893", + "name": "General Bentnoze" + }, + { + "id": "7894", + "name": "General Wartface" + }, + { + "id": "7896", + "name": "General Bentnoze" + }, + { + "id": "7898", + "name": "Loar Shadow" + }, + { + "id": "7901", + "name": "Loar Shadow" + }, + { + "id": "7902", + "name": "Sergeant Abram" + }, + { + "id": "7903", + "name": "Guardsman Pazel" + }, + { + "id": "7904", + "name": "Guardsman Peale" + }, + { + "id": "7905", + "name": "Barricade guard" + }, + { + "id": "7906", + "name": "Barricade guard" + }, + { + "id": "7907", + "name": "Barricade guard" + }, + { + "id": "7908", + "name": "Barricade guard" + }, + { + "id": "7909", + "name": "Barricade guard" + }, + { + "id": "7910", + "name": "Barricade guard" + }, + { + "id": "7911", + "name": "Barricade guard" + }, + { + "id": "7912", + "name": "Border guard" + }, + { + "id": "7913", + "name": "Iain" + }, + { + "id": "7914", + "name": "Julian" + }, + { + "id": "7915", + "name": "Lachtopher" + }, + { + "id": "7916", + "name": "Samuel" + }, + { + "id": "7917", + "name": "Victoria" + }, + { + "id": "7918", + "name": "Man" + }, + { + "id": "7919", + "name": "Man" + }, + { + "id": "7920", + "name": "Man" + }, + { + "id": "7921", + "name": "Man" + }, + { + "id": "7922", + "name": "Man" + }, + { + "id": "7923", + "name": "Man" + }, + { + "id": "7924", + "name": "Man" + }, + { + "id": "7925", + "name": "Woman" + }, + { + "id": "7926", + "name": "Woman" + }, + { + "id": "7927", + "name": "Woman" + }, + { + "id": "7928", + "name": "Woman" + }, + { + "id": "7929", + "name": "Lumbridge Guide" + }, + { + "id": "7930", + "name": "Doomsayer" + }, + { + "id": "7931", + "name": "Donie" + }, + { + "id": "7932", + "name": "Gee" + }, + { + "id": "7933", + "name": "Duke Horacio" + }, + { + "id": "7934", + "name": "Sigmund" + }, + { + "id": "7935", + "name": "Hans" + }, + { + "id": "7936", + "name": "Cook" + }, + { + "id": "7937", + "name": "Father Aereck" + }, + { + "id": "7938", + "name": "Sir Vant" + }, + { + "id": "7939", + "name": "Sir Vant" + }, + { + "id": "7940", + "name": "Sir Vant" + }, + { + "id": "7941", + "name": "Sir Vant" + }, + { + "id": "7942", + "name": "Sir Vant" + }, + { + "id": "7943", + "name": "Dragon" + }, + { + "id": "7944", + "name": "Dragon" + }, + { + "id": "7945", + "name": "Dragon" + }, + { + "id": "7946", + "name": "Dragon" + }, + { + "id": "7947", + "name": "Dragon" + }, + { + "id": "7948", + "name": "Dragon" + }, + { + "id": "7949", + "name": "Lumbridge Guide" + }, + { + "id": "7950", + "name": "Melee Tutor" + }, + { + "id": "7951", + "name": "Ranged Tutor" + }, + { + "id": "7952", + "name": "Magic Tutor" + }, + { + "id": "7953", + "name": "Cooking Tutor" + }, + { + "id": "7954", + "name": "Crafting Tutor" + }, + { + "id": "7955", + "name": "Fishing Tutor" + }, + { + "id": "7956", + "name": "Mining Tutor" + }, + { + "id": "7957", + "name": "Prayer Tutor" + }, + { + "id": "7960", + "name": "Woodcutting Tutor" + }, + { + "id": "7961", + "name": "Bank Tutor" + }, + { + "id": "7962", + "name": "Gee" + }, + { + "id": "7963", + "name": "Spirit" + }, + { + "id": "7964", + "name": "Goblin" + }, + { + "id": "7965", + "name": "Goblin" + }, + { + "id": "7966", + "name": "Chaos druid" + }, + { + "id": "7967", + "name": "Shopkeeper" + }, + { + "id": "7968", + "name": "Explorer Jack" + }, + { + "id": "7970", + "name": "Smithing Tutor" + }, + { + "id": "7971", + "name": "Mining Tutor" + }, + { + "id": "7972", + "name": "Spirit" + }, + { + "id": "7977", + "name": "Spirit" + }, + { + "id": "7978", + "name": "Spirit" + }, + { + "id": "7979", + "name": "Spirit" + }, + { + "id": "7980", + "name": "Spirit" + }, + { + "id": "7981", + "name": "Spirit" + }, + { + "id": "7982", + "name": "Spirit" + }, + { + "id": "7983", + "name": "Spirit" + }, + { + "id": "7984", + "name": "Spirit" + }, + { + "id": "7985", + "name": "Summer Bonde" + }, + { + "id": "7987", + "name": "Spirit" + }, + { + "id": "7988", + "name": "Spirit" + }, + { + "id": "7989", + "name": "Erik Bonde" + }, + { + "id": "7990", + "name": "Spirit" + }, + { + "id": "7991", + "name": "Jallek Lenkin" + }, + { + "id": "7992", + "name": "Spirit" + }, + { + "id": "7993", + "name": "Meranek Thanatos" + }, + { + "id": "7994", + "name": "Ghostly warrior" + }, + { + "id": "7995", + "name": "Spirit Beast" + }, + { + "id": "7996", + "name": "Spirit Beast" + }, + { + "id": "7997", + "name": "Spirit Beast" + }, + { + "id": "7998", + "name": "Ghost" + }, + { + "id": "7999", + "name": "Ghost" + }, + { + "id": "8000", + "name": "Goth leprechaun" + }, + { + "id": "8001", + "name": "Jack" + }, + { + "id": "8003", + "name": "Sarah" + }, + { + "id": "8004", + "name": "Laura" + }, + { + "id": "8005", + "name": "Laura" + }, + { + "id": "8006", + "name": "Roger" + }, + { + "id": "8007", + "name": "Jorral" + }, + { + "id": "8008", + "name": "Guthix" + }, + { + "id": "8009", + "name": "Max the traveller" + }, + { + "id": "8010", + "name": "Man" + }, + { + "id": "8011", + "name": "Man" + }, + { + "id": "8012", + "name": "Woman" + }, + { + "id": "8013", + "name": "Woman" + }, + { + "id": "8014", + "name": "Haluned" + }, + { + "id": "8015", + "name": "Jack" + }, + { + "id": "8016", + "name": "Baby Sarah" + }, + { + "id": "8017", + "name": "Snowy" + }, + { + "id": "8018", + "name": "Roger" + }, + { + "id": "8019", + "name": "Portal" + }, + { + "id": "8020", + "name": "Portal" + }, + { + "id": "8021", + "name": "Yellow orb" + }, + { + "id": "8023", + "name": "Yellow orb" + }, + { + "id": "8024", + "name": "Yellow orb" + }, + { + "id": "8025", + "name": "Green orb" + }, + { + "id": "8027", + "name": "Green orb" + }, + { + "id": "8028", + "name": "Green orb" + }, + { + "id": "8029", + "name": "Wizard Korvak" + }, + { + "id": "8030", + "name": "Wizard Vief" + }, + { + "id": "8031", + "name": "Wizard Acantha" + }, + { + "id": "8032", + "name": "Wizard Elriss" + }, + { + "id": "8033", + "name": "Wizard" + }, + { + "id": "8034", + "name": "Wizard" + }, + { + "id": "8035", + "name": "Wizard" + }, + { + "id": "8036", + "name": "Wizard" + }, + { + "id": "8037", + "name": "Wizard" + }, + { + "id": "8038", + "name": "Wizard" + }, + { + "id": "8039", + "name": "Wizard" + }, + { + "id": "8040", + "name": "Wizard" + }, + { + "id": "8042", + "name": "Squire Fyre" + }, + { + "id": "8043", + "name": "Squire Fyre" + }, + { + "id": "8044", + "name": "Orry" + }, + { + "id": "8045", + "name": "Orry" + }, + { + "id": "8046", + "name": "Ube" + }, + { + "id": "8047", + "name": "Ube" + }, + { + "id": "8048", + "name": "Waldo" + }, + { + "id": "8049", + "name": "Waldo" + }, + { + "id": "8050", + "name": "Gjalp" + }, + { + "id": "8051", + "name": "Gjalp" + }, + { + "id": "8052", + "name": "Brother Fintan" + }, + { + "id": "8053", + "name": "Brother Fintan" + }, + { + "id": "8054", + "name": "Stubthumb" + }, + { + "id": "8055", + "name": "Stubthumb" + }, + { + "id": "8056", + "name": "Stubthumb" + }, + { + "id": "8057", + "name": "Doronbol" + }, + { + "id": "8058", + "name": "Doronbol" + }, + { + "id": "8059", + "name": "Crate" + }, + { + "id": "8060", + "name": "Crate" + }, + { + "id": "8061", + "name": "Egg" + }, + { + "id": "8062", + "name": "Egg" + }, + { + "id": "8063", + "name": "Nanuq" + }, + { + "id": "8064", + "name": "Nanuq" + }, + { + "id": "8065", + "name": "Pumpkin" + }, + { + "id": "8078", + "name": "Maggie" + }, + { + "id": "8079", + "name": "Circus barker" + }, + { + "id": "8080", + "name": "Circus barker" + }, + { + "id": "8081", + "name": "Circus barker" + }, + { + "id": "8082", + "name": "Agility assistant" + }, + { + "id": "8083", + "name": "Magic assistant" + }, + { + "id": "8084", + "name": "Ranged assistant" + }, + { + "id": "8085", + "name": "Ringmaster" + }, + { + "id": "8086", + "name": "Audience" + }, + { + "id": "8087", + "name": "Audience" + }, + { + "id": "8088", + "name": "Ticket vendor" + }, + { + "id": "8089", + "name": "Rock" + }, + { + "id": "8091", + "name": "Star sprite" + }, + { + "id": "8092", + "name": "Shooting star shadow" + }, + { + "id": "8093", + "name": "Penguin" + }, + { + "id": "8094", + "name": "Penguin" + }, + { + "id": "8095", + "name": "Penguin" + }, + { + "id": "8096", + "name": "Penguin" + }, + { + "id": "8097", + "name": "Penguin" + }, + { + "id": "8098", + "name": "Penguin" + }, + { + "id": "8099", + "name": "Penguin" + }, + { + "id": "8100", + "name": "Penguin" + }, + { + "id": "8101", + "name": "Penguin" + }, + { + "id": "8102", + "name": "Penguin" + }, + { + "id": "8103", + "name": "Penguin" + }, + { + "id": "8104", + "name": "Barrel" + }, + { + "id": "8105", + "name": "Bush" + }, + { + "id": "8106", + "name": "Bush" + }, + { + "id": "8107", + "name": "Cactus" + }, + { + "id": "8108", + "name": "Crate" + }, + { + "id": "8109", + "name": "Rock" + }, + { + "id": "8110", + "name": "Toadstool" + }, + { + "id": "8111", + "name": "Calladin" + }, + { + "id": "8112", + "name": "Summer Bonde" + }, + { + "id": "8114", + "name": "Summer Bonde" + }, + { + "id": "8115", + "name": "Erik Bonde" + }, + { + "id": "8116", + "name": "Erik Bonde" + }, + { + "id": "8117", + "name": "Jallek Lenkin" + }, + { + "id": "8118", + "name": "Jallek Lenkin" + }, + { + "id": "8119", + "name": "Meranek Thanatos" + }, + { + "id": "8120", + "name": "Meranek Thanatos" + }, + { + "id": "8121", + "name": "Spirit" + }, + { + "id": "8122", + "name": "Rogue" + }, + { + "id": "8123", + "name": "Tormented wraith" + }, + { + "id": "8126", + "name": "Dark energy core" + }, + { + "id": "8127", + "name": "Dark energy core" + }, + { + "id": "8128", + "name": "Spirit Beast" + }, + { + "id": "8129", + "name": "Spirit Beast" + }, + { + "id": "8130", + "name": "Spirit Beast" + }, + { + "id": "8131", + "name": "Spirit Beast" + }, + { + "id": "8132", + "name": "Spirit Beast" + }, + { + "id": "8134", + "name": "Spirit" + }, + { + "id": "8135", + "name": "Summer Bonde" + }, + { + "id": "8136", + "name": "Erik Bonde" + }, + { + "id": "8137", + "name": "Jallek Lenkin" + }, + { + "id": "8138", + "name": "Meranek Thanatos" + }, + { + "id": "8139", + "name": "Hartwin" + }, + { + "id": "8140", + "name": "Hartwin" + }, + { + "id": "8141", + "name": "Zombie" + }, + { + "id": "8143", + "name": "Zombie" + }, + { + "id": "8144", + "name": "Zombie" + }, + { + "id": "8145", + "name": "Zombie" + }, + { + "id": "8146", + "name": "Zemouregal" + }, + { + "id": "8147", + "name": "Zemouregal" + }, + { + "id": "8152", + "name": "Armoured zombie" + }, + { + "id": "8153", + "name": "Armoured zombie" + }, + { + "id": "8154", + "name": "Armoured zombie" + }, + { + "id": "8155", + "name": "Armoured zombie" + }, + { + "id": "8156", + "name": "Armoured zombie" + }, + { + "id": "8157", + "name": "Armoured zombie" + }, + { + "id": "8158", + "name": "Armoured zombie" + }, + { + "id": "8159", + "name": "Armoured zombie" + }, + { + "id": "8160", + "name": "Armoured zombie" + }, + { + "id": "8161", + "name": "Armoured zombie" + }, + { + "id": "8162", + "name": "Armoured zombie" + }, + { + "id": "8163", + "name": "Armoured zombie" + }, + { + "id": "8164", + "name": "Armoured zombie" + }, + { + "id": "8165", + "name": "Sharathteerk" + }, + { + "id": "8166", + "name": "Sharathteerk" + }, + { + "id": "8168", + "name": "Arrav" + }, + { + "id": "8169", + "name": "Arrav" + }, + { + "id": "8170", + "name": "Ramarno" + }, + { + "id": "8171", + "name": "Dimintheis" + }, + { + "id": "8172", + "name": "Dimintheis" + }, + { + "id": "8173", + "name": "Guard" + }, + { + "id": "8174", + "name": "Clive" + }, + { + "id": "8175", + "name": "Ellamaria" + }, + { + "id": "8176", + "name": "Fish" + }, + { + "id": "8177", + "name": "Fish" + }, + { + "id": "8178", + "name": "Monk of Zamorak" + }, + { + "id": "8179", + "name": "Ellamaria" + }, + { + "id": "8180", + "name": "Traiborn" + }, + { + "id": "8181", + "name": "Fenkenstrain's Monster" + }, + { + "id": "8182", + "name": "Wise Old Man" + }, + { + "id": "8183", + "name": "Acrobat" + }, + { + "id": "8186", + "name": "Acrobat" + }, + { + "id": "8187", + "name": "Acrobat" + }, + { + "id": "8188", + "name": "Acrobat" + }, + { + "id": "8189", + "name": "Acrobat" + }, + { + "id": "8190", + "name": "Acrobat" + }, + { + "id": "8191", + "name": "Acrobat" + }, + { + "id": "8192", + "name": "Acrobat" + }, + { + "id": "8193", + "name": "Acrobat" + }, + { + "id": "8194", + "name": "Acrobat" + }, + { + "id": "8195", + "name": "Acrobat" + }, + { + "id": "8196", + "name": "Acrobat" + }, + { + "id": "8197", + "name": "Acrobat" + }, + { + "id": "8198", + "name": "Acrobat" + }, + { + "id": "8199", + "name": "Acrobat" + }, + { + "id": "8200", + "name": "Acrobat" + }, + { + "id": "8201", + "name": "Wendy" + }, + { + "id": "8202", + "name": "Trogs" + }, + { + "id": "8203", + "name": "Norman" + }, + { + "id": "8204", + "name": "Babe" + }, + { + "id": "8205", + "name": "Gus" + }, + { + "id": "8206", + "name": "Lottie" + }, + { + "id": "8207", + "name": "Aggie" + }, + { + "id": "8208", + "name": "Bat" + }, + { + "id": "8209", + "name": "Rat" + }, + { + "id": "8210", + "name": "Lizard" + }, + { + "id": "8211", + "name": "Blackbird" + }, + { + "id": "8212", + "name": "Spider" + }, + { + "id": "8213", + "name": "Snail" + }, + { + "id": "8214", + "name": "Cat" + }, + { + "id": "8215", + "name": "Lazy cat" + }, + { + "id": "8216", + "name": "Overgrown cat" + }, + { + "id": "8217", + "name": "Kitten" + }, + { + "id": "8218", + "name": "Wily cat" + }, + { + "id": "8219", + "name": "Guardian of Armadyl" + }, + { + "id": "8227", + "name": "Head mystic" + }, + { + "id": "8228", + "name": "Rewards mystic" + }, + { + "id": "8229", + "name": "Mystic" + }, + { + "id": "8230", + "name": "Mystic" + }, + { + "id": "8231", + "name": "Mystic" + }, + { + "id": "8232", + "name": "Mystic" + }, + { + "id": "8233", + "name": "Mystic" + }, + { + "id": "8234", + "name": "Mystic" + }, + { + "id": "8235", + "name": "Mystic" + }, + { + "id": "8236", + "name": "Mystic" + }, + { + "id": "8237", + "name": "Mystic" + }, + { + "id": "8238", + "name": "Mystic" + }, + { + "id": "8239", + "name": "Head mystic" + }, + { + "id": "8240", + "name": "Clay familiar (class 1)" + }, + { + "id": "8241", + "name": "Clay familiar (class 1)" + }, + { + "id": "8242", + "name": "Clay familiar (class 2)" + }, + { + "id": "8243", + "name": "Clay familiar (class 2)" + }, + { + "id": "8244", + "name": "Clay familiar (class 3)" + }, + { + "id": "8245", + "name": "Clay familiar (class 3)" + }, + { + "id": "8246", + "name": "Clay familiar (class 4)" + }, + { + "id": "8247", + "name": "Clay familiar (class 4)" + }, + { + "id": "8248", + "name": "Clay familiar (class 5)" + }, + { + "id": "8249", + "name": "Clay familiar (class 5)" + }, + { + "id": "8250", + "name": "Grindxplox" + }, + { + "id": "8251", + "name": "Grindxplox" + }, + { + "id": "8252", + "name": "Stealing Creation team" + }, + { + "id": "8253", + "name": "Resource NPC" + }, + { + "id": "8254", + "name": "Game NPC" + }, + { + "id": "8255", + "name": "Resource NPC" + }, + { + "id": "8257", + "name": "Harrallak Menarous" + }, + { + "id": "8269", + "name": "Yadech Strongarm" + }, + { + "id": "8271", + "name": "Turael" + }, + { + "id": "8274", + "name": "Mazchna" + }, + { + "id": "8275", + "name": "Duradel" + }, + { + "id": "8276", + "name": "Cyrisus" + }, + { + "id": "8280", + "name": "Sloane" + }, + { + "id": "8281", + "name": "Balance Elemental" + }, + { + "id": "8282", + "name": "Balance Elemental" + }, + { + "id": "8283", + "name": "Balance Elemental" + }, + { + "id": "8284", + "name": "Balance Elemental" + }, + { + "id": "8285", + "name": "Balance Elemental" + }, + { + "id": "8286", + "name": "Undead hero" + }, + { + "id": "8287", + "name": "Undead hero" + }, + { + "id": "8288", + "name": "Undead hero" + }, + { + "id": "8289", + "name": "Undead hero" + }, + { + "id": "8290", + "name": "Undead hero" + }, + { + "id": "8291", + "name": "Undead hero" + }, + { + "id": "8292", + "name": "Undead hero" + }, + { + "id": "8293", + "name": "Undead hero" + }, + { + "id": "8294", + "name": "Undead hero" + }, + { + "id": "8295", + "name": "Undead hero" + }, + { + "id": "8296", + "name": "Undead hero" + }, + { + "id": "8297", + "name": "Undead hero" + }, + { + "id": "8298", + "name": "Stone block" + }, + { + "id": "8299", + "name": "Harrallak Menarous" + }, + { + "id": "8300", + "name": "Harrallak Menarous" + }, + { + "id": "8301", + "name": "Harrallak Menarous" + }, + { + "id": "8302", + "name": "Turael" + }, + { + "id": "8303", + "name": "Turael" + }, + { + "id": "8304", + "name": "Cyrisus" + }, + { + "id": "8305", + "name": "Cyrisus" + }, + { + "id": "8306", + "name": "Ghommal" + }, + { + "id": "8307", + "name": "Mazchna" + }, + { + "id": "8308", + "name": "Mazchna" + }, + { + "id": "8309", + "name": "Mazchna" + }, + { + "id": "8310", + "name": "Duradel" + }, + { + "id": "8311", + "name": "Sloane" + }, + { + "id": "8317", + "name": "Elite Dark Ranger" + }, + { + "id": "8318", + "name": "Elite Dark Ranger" + }, + { + "id": "8319", + "name": "Elite Dark Ranger" + }, + { + "id": "8320", + "name": "Elite Dark Mage" + }, + { + "id": "8321", + "name": "Elite Dark Mage" + }, + { + "id": "8322", + "name": "Elite Dark Mage" + }, + { + "id": "8323", + "name": "Elite Dark Mage" + }, + { + "id": "8324", + "name": "Elite Black Knight" + }, + { + "id": "8325", + "name": "Elite Black Knight" + }, + { + "id": "8326", + "name": "Elite Black Knight" + }, + { + "id": "8327", + "name": "Elite Black Knight" + }, + { + "id": "8328", + "name": "Elite Black Knight" + }, + { + "id": "8329", + "name": "Elite Black Knight" + }, + { + "id": "8330", + "name": "Elite Black Knight" + }, + { + "id": "8331", + "name": "Guardian of Armadyl" + }, + { + "id": "8332", + "name": "Guardian of Armadyl" + }, + { + "id": "8333", + "name": "Guardian of Armadyl" + }, + { + "id": "8334", + "name": "Mercenary axeman" + }, + { + "id": "8335", + "name": "Mercenary mage" + }, + { + "id": "8336", + "name": "Idria" + }, + { + "id": "8337", + "name": "Idria" + }, + { + "id": "8338", + "name": "Akrisae" + }, + { + "id": "8339", + "name": "Shady stranger" + }, + { + "id": "8340", + "name": "Shady stranger" + }, + { + "id": "8341", + "name": "Shady stranger" + }, + { + "id": "8342", + "name": "Guardian of Armadyl" + }, + { + "id": "8344", + "name": "Guardian of Armadyl" + }, + { + "id": "8345", + "name": "Local thug" + }, + { + "id": "8347", + "name": "Local mage" + }, + { + "id": "8367", + "name": "Undead troll" + }, + { + "id": "8378", + "name": "Undead troll" + }, + { + "id": "8379", + "name": "Undead troll" + }, + { + "id": "8380", + "name": "Undead troll" + }, + { + "id": "8381", + "name": "Undead troll" + }, + { + "id": "8382", + "name": "Undead troll" + }, + { + "id": "8383", + "name": "Undead troll" + }, + { + "id": "8384", + "name": "Undead troll" + }, + { + "id": "8385", + "name": "Undead troll" + }, + { + "id": "8386", + "name": "Undead troll" + }, + { + "id": "8387", + "name": "Undead troll" + }, + { + "id": "8388", + "name": "Undead troll" + }, + { + "id": "8389", + "name": "Undead troll" + }, + { + "id": "8390", + "name": "Undead troll" + }, + { + "id": "8391", + "name": "Undead troll" + }, + { + "id": "8392", + "name": "Undead troll" + }, + { + "id": "8393", + "name": "Vasador" + }, + { + "id": "8394", + "name": "Valator" + }, + { + "id": "8395", + "name": "Vaasdor" + }, + { + "id": "8396", + "name": "Varosad" + }, + { + "id": "8397", + "name": "Verisad" + }, + { + "id": "8398", + "name": "Vudisor" + }, + { + "id": "8399", + "name": "Vlatoad" + }, + { + "id": "8400", + "name": "Vedolas" + }, + { + "id": "8401", + "name": "Vundiar" + }, + { + "id": "8402", + "name": "Versita" + }, + { + "id": "8403", + "name": "Vislota" + }, + { + "id": "8404", + "name": "Vanjuta" + }, + { + "id": "8405", + "name": "Vasador" + }, + { + "id": "8406", + "name": "Valator" + }, + { + "id": "8407", + "name": "Vaasdor" + }, + { + "id": "8408", + "name": "Varosad" + }, + { + "id": "8409", + "name": "Verisad" + }, + { + "id": "8410", + "name": "Vudisor" + }, + { + "id": "8411", + "name": "Vlatoad" + }, + { + "id": "8412", + "name": "Vedolas" + }, + { + "id": "8413", + "name": "Vundiar" + }, + { + "id": "8414", + "name": "Versita" + }, + { + "id": "8415", + "name": "Vislota" + }, + { + "id": "8416", + "name": "Vanjuta" + }, + { + "id": "8417", + "name": "Ivy Sophista" + }, + { + "id": "8418", + "name": "Thaerisk Cemphier" + }, + { + "id": "8419", + "name": "Thaerisk Cemphier" + }, + { + "id": "8420", + "name": "Assassin" + }, + { + "id": "8423", + "name": "Assassin" + }, + { + "id": "8424", + "name": "Mithril dragon" + }, + { + "id": "8425", + "name": "Dragon head" + }, + { + "id": "8426", + "name": "Dragon head" + }, + { + "id": "8427", + "name": "Dragon head" + }, + { + "id": "8428", + "name": "Khazard launderer" + }, + { + "id": "8429", + "name": "Khazard cook" + }, + { + "id": "8430", + "name": "Silif" + }, + { + "id": "8431", + "name": "Silif" + }, + { + "id": "8432", + "name": "Silif" + }, + { + "id": "8433", + "name": "Silif" + }, + { + "id": "8434", + "name": "Silif" + }, + { + "id": "8435", + "name": "Shady stranger" + }, + { + "id": "8436", + "name": "Suspicious outsider" + }, + { + "id": "8437", + "name": "Elite Khazard guard" + }, + { + "id": "8438", + "name": "Elite Khazard guard" + }, + { + "id": "8439", + "name": "Elite Khazard guard" + }, + { + "id": "8440", + "name": "Elite Khazard guard" + }, + { + "id": "8441", + "name": "Dark Squall" + }, + { + "id": "8442", + "name": "Surok Magis" + }, + { + "id": "8443", + "name": "Lucien" + }, + { + "id": "8444", + "name": "Druid" + }, + { + "id": "8445", + "name": "Druid" + }, + { + "id": "8446", + "name": "Druid" + }, + { + "id": "8447", + "name": "Druid bodyguard" + }, + { + "id": "8448", + "name": "Druid bodyguard" + }, + { + "id": "8449", + "name": "Movario" + }, + { + "id": "8450", + "name": "Darve" + }, + { + "id": "8451", + "name": "Cave goblin" + }, + { + "id": "8452", + "name": "Movario" + }, + { + "id": "8453", + "name": "Darve" + }, + { + "id": "8454", + "name": "Light creature" + }, + { + "id": "8455", + "name": "Light creature" + }, + { + "id": "8456", + "name": "Druid spirit" + }, + { + "id": "8457", + "name": "Druid spirit" + }, + { + "id": "8458", + "name": "Druid spirit" + }, + { + "id": "8459", + "name": "Druid spirit" + }, + { + "id": "8460", + "name": "Turael" + }, + { + "id": "8462", + "name": "Spria" + }, + { + "id": "8463", + "name": "Mazchna" + }, + { + "id": "8464", + "name": "Mazchna" + }, + { + "id": "8465", + "name": "Achtryn" + }, + { + "id": "8466", + "name": "Duradel" + }, + { + "id": "8467", + "name": "Lapalok" + }, + { + "id": "8468", + "name": "Laidee Gnonock" + }, + { + "id": "8485", + "name": "Hazelmere" + }, + { + "id": "8486", + "name": "Undead mage" + }, + { + "id": "8487", + "name": "Wild broav" + }, + { + "id": "8488", + "name": "Hazelmere" + }, + { + "id": "8490", + "name": "Hazelmere" + }, + { + "id": "8491", + "name": "Broav" + }, + { + "id": "8492", + "name": "Sithaph" + }, + { + "id": "8494", + "name": "Strisath" + }, + { + "id": "8495", + "name": "Sakirth" + }, + { + "id": "8496", + "name": "Hazelmere's hat" + }, + { + "id": "8497", + "name": "Lucien" + }, + { + "id": "8498", + "name": "A lazy Khazard guard" + }, + { + "id": "8499", + "name": "Thanksgiving Turkey" + }, + { + "id": "8500", + "name": "Cook's brother" + }, + { + "id": "8501", + "name": "Turkey" + }, + { + "id": "8502", + "name": "Cactus" + }, + { + "id": "8503", + "name": "Cactus" + }, + { + "id": "8504", + "name": "Bush" + }, + { + "id": "8505", + "name": "Toadstool" + }, + { + "id": "8506", + "name": "Barrel" + }, + { + "id": "8507", + "name": "Bush" + }, + { + "id": "8508", + "name": "Crate" + }, + { + "id": "8509", + "name": "Bush" + }, + { + "id": "8510", + "name": "Rock" + }, + { + "id": "8511", + "name": "Bush" + }, + { + "id": "8512", + "name": "Marvin" + }, + { + "id": "8513", + "name": "Marius" + }, + { + "id": "8514", + "name": "Benny" + }, + { + "id": "8515", + "name": "Yeti" + }, + { + "id": "8516", + "name": "Yeti" + }, + { + "id": "8517", + "name": "Jack Frost" + }, + { + "id": "8518", + "name": "Jack Frost" + }, + { + "id": "8519", + "name": "Jack Frost" + }, + { + "id": "8520", + "name": "Jack Frost" + }, + { + "id": "8521", + "name": "Snow imp" + }, + { + "id": "8537", + "name": "Snow imp" + }, + { + "id": "8538", + "name": "Snow imp" + }, + { + "id": "8539", + "name": "Queen of Snow" + }, + { + "id": "8540", + "name": "Santa Claus" + }, + { + "id": "8541", + "name": "Head snow imp" + }, + { + "id": "8542", + "name": "Head snow imp" + }, + { + "id": "8543", + "name": "Head snow imp" + }, + { + "id": "8544", + "name": "Isidor" + }, + { + "id": "8545", + "name": "Mystic" + }, + { + "id": "8546", + "name": "Balance Elemental" + }, + { + "id": "8547", + "name": "Wounded phoenix" + }, + { + "id": "8548", + "name": "Phoenix" + }, + { + "id": "8549", + "name": "Phoenix" + }, + { + "id": "8550", + "name": "Phoenix eggling" + }, + { + "id": "8551", + "name": "Phoenix eggling" + }, + { + "id": "8552", + "name": "Large egg" + }, + { + "id": "8553", + "name": "Priest of Guthix" + }, + { + "id": "8556", + "name": "Brian Twitcher" + }, + { + "id": "8557", + "name": "Lesser reborn warrior" + }, + { + "id": "8558", + "name": "Lesser reborn warrior" + }, + { + "id": "8559", + "name": "Greater reborn warrior" + }, + { + "id": "8560", + "name": "Greater reborn warrior" + }, + { + "id": "8561", + "name": "Lesser reborn ranger" + }, + { + "id": "8562", + "name": "Lesser reborn ranger" + }, + { + "id": "8563", + "name": "Greater reborn ranger" + }, + { + "id": "8564", + "name": "Greater reborn ranger" + }, + { + "id": "8565", + "name": "Lesser reborn mage" + }, + { + "id": "8566", + "name": "Lesser reborn mage" + }, + { + "id": "8567", + "name": "Greater reborn mage" + }, + { + "id": "8568", + "name": "Greater reborn mage" + }, + { + "id": "8569", + "name": "Lesser reborn warrior" + }, + { + "id": "8570", + "name": "Greater reborn warrior" + }, + { + "id": "8571", + "name": "Lesser reborn ranger" + }, + { + "id": "8572", + "name": "Greater reborn ranger" + }, + { + "id": "8573", + "name": "Lesser reborn mage" + }, + { + "id": "8574", + "name": "Greater reborn mage" + }, + { + "id": "8575", + "name": "Phoenix" + }, + { + "id": "8576", + "name": "Phoenix" + }, + { + "id": "8577", + "name": "Phoenix eggling" + }, + { + "id": "8578", + "name": "Phoenix eggling" + }, + { + "id": "8579", + "name": "Karma the chameleon" + }, + { + "id": "8581", + "name": "Karma the chameleon" + }, + { + "id": "8582", + "name": "Karma the chameleon" + }, + { + "id": "8583", + "name": "Karma the chameleon" + }, + { + "id": "8584", + "name": "Karma the chameleon" + }, + { + "id": "8585", + "name": "Karma the chameleon" + }, + { + "id": "8586", + "name": "Karma the chameleon" + }, + { + "id": "8587", + "name": "Karma the chameleon" + }, + { + "id": "8588", + "name": "Karma the chameleon" + }, + { + "id": "8589", + "name": "Karma the chameleon" + }, + { + "id": "8590", + "name": "Geoffrey" + }, { "examine": "Ooh, shiny things!", "name": "Magpie Impling", From 6e9f3cb8b93db7ae8cb3381540333dd88f75696e Mon Sep 17 00:00:00 2001 From: Ceikry Date: Sat, 1 Feb 2025 13:48:18 +0000 Subject: [PATCH 185/306] Disabled the ability to create new HCIM accounts Disabled the ability to select HCIM 10x xp rate Existing HCIM will turn back to standard players after their next death (all permadeath rules still apply for that death) Players on HCIM 10x will be reverted to 5x after their next death If the player is in combat and disconnects via AFK timeout, then their forced logout timer has been reduced to 30 seconds from 15 minutes If the player is in combat and x-logs or disconnects via network issues, then their forced logout timer has been reduced to 5 minutes from 15 minutes --- .../dialogue/TutorialMagicTutorDialogue.kt | 39 +++++++++++-------- .../core/game/node/entity/player/Player.java | 2 + .../world/repository/DisconnectionQueue.kt | 9 +++-- .../main/core/net/packet/PacketProcessor.kt | 3 ++ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt b/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt index 83813a0bf..a92d70916 100644 --- a/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt +++ b/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt @@ -1,22 +1,22 @@ package content.region.misc.tutisland.dialogue +import content.global.handlers.iface.RulesAndInfo import content.region.misc.tutisland.handlers.* +import core.ServerConstants import core.api.* import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.entity.player.link.IronmanMode import core.game.node.entity.player.link.TeleportManager import core.game.node.item.Item +import core.game.world.GameWorld import core.game.world.map.Location import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.worker.ManagementEvents import org.rs09.consts.Items import org.rs09.consts.NPCs import proto.management.JoinClanRequest -import core.ServerConstants -import content.global.handlers.iface.RulesAndInfo -import core.game.world.GameWorld -import core.tools.END_DIALOGUE -import core.worker.ManagementEvents /** * Handles the magic tutor's dialogue @@ -95,8 +95,8 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di 71 -> when(stage){ 0 -> options("Set Ironman Mode (current: ${player.ironmanManager.mode.name})", "Change XP Rate (current: ${player.skills.experienceMultiplier}x)", "I'm ready now.").also { stage++ } 1 -> when(buttonId){ - 1 -> options("None","Standard","Hardcore (Permadeath!)","Ultimate","Nevermind.").also { stage = 10 } - 2 -> options("1.0x","2.5x","5.0x","10x").also { stage = 20 } + 1 -> options("None","Standard","Ultimate","Nevermind.").also { stage = 10 } + 2 -> options("1.0x","2.5x","5.0x").also { stage = 20 } 3 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, you're all finished here now. I'll give you a reasonable number of starting items when you leave.").also { stage = 30 } } @@ -104,22 +104,31 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di stage = 0 if(buttonId < 5) { - val mode = IronmanMode.values()[buttonId - 1] + val mode = when (buttonId - 1) + { + 0 -> IronmanMode.NONE + 1 -> IronmanMode.STANDARD + 2 -> IronmanMode.ULTIMATE + else -> IronmanMode.NONE + } + if (mode != IronmanMode.NONE) stage = 11 player.dialogueInterpreter.sendDialogue("You set your ironman mode to: ${mode.name}.") player.ironmanManager.mode = mode - if (player.skills.experienceMultiplier == 10.0 && mode != IronmanMode.HARDCORE) player.skills.experienceMultiplier = 5.0 + if (player.skills.experienceMultiplier == 10.0) player.skills.experienceMultiplier = 5.0 } else { handle(interfaceId, 0) } } + 11 -> player.dialogueInterpreter.sendPlainMessage(false, *splitLines("WARNING: You have selected an ironman mode. This is an uncompromising mode that WILL completely restrict your ability to trade. This MAY leave you unable to complete certain content, including quests.")).also { stage = 0 } 20 -> { - val rates = arrayOf(1.0,2.5,5.0,10.0) + val rates = arrayOf(1.0,2.5,5.0) val rate = rates[buttonId - 1] - if(rate == 10.0 && player.ironmanManager.mode != IronmanMode.HARDCORE) { - player.dialogueInterpreter.sendDialogue("10.0x is only available to Hardcore Ironmen!") + if(rate == 10.0) { + player.dialogueInterpreter.sendDialogue("10.0x is no longer available!") + player.skills.experienceMultiplier = 5.0 stage = 0 return true } @@ -150,11 +159,7 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di player.inventory.add(*STARTER_PACK) player.bank.add(*STARTER_BANK) - if(player.ironmanManager.mode == IronmanMode.HARDCORE) - { - setAttribute(player, "/save:permadeath", true) - } - else if(player.skills.experienceMultiplier == 10.0) + if(player.skills.experienceMultiplier == 10.0) { player.skills.experienceMultiplier = 5.0 } diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 63fd5f611..13e6e7d31 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -130,6 +130,8 @@ public class Player extends Entity { public HashMap> logoutListeners = new HashMap<>(); + public Boolean isAfkLogout; + /** * The inventory. */ diff --git a/Server/src/main/core/game/world/repository/DisconnectionQueue.kt b/Server/src/main/core/game/world/repository/DisconnectionQueue.kt index b1fcf12ea..dd0c7ee98 100644 --- a/Server/src/main/core/game/world/repository/DisconnectionQueue.kt +++ b/Server/src/main/core/game/world/repository/DisconnectionQueue.kt @@ -4,11 +4,9 @@ import core.api.log import core.game.node.entity.player.Player import core.game.node.entity.player.info.login.PlayerParser import core.game.system.task.TaskExecutor -import core.tools.SystemLogger import core.game.world.GameWorld import core.tools.Log -import java.util.* -import java.util.concurrent.ConcurrentHashMap +import core.tools.secondsToTicks /** * Handles disconnecting players queuing. @@ -37,7 +35,10 @@ class DisconnectionQueue { else { //Make sure there's no room for the disconnection queue to stroke out and leave someone logged in for 10 years. queueTimers[it.key] = (queueTimers[it.key] ?: 0) + 3 - if ((queueTimers[it.key] ?: Int.MAX_VALUE) >= 1500) { + val isValidAFKLogout = it.value?.player?.isAfkLogout == true + val seconds = if (isValidAFKLogout) 30 else 5 * 60 //30 seconds for AFK logout, 5 minutes for normal logout + val ticksNeeded = secondsToTicks(seconds) + if ((queueTimers[it.key] ?: Int.MAX_VALUE) >= ticksNeeded) { it.value?.player?.let { player -> player.finishClear() Repository.removePlayer(player) diff --git a/Server/src/main/core/net/packet/PacketProcessor.kt b/Server/src/main/core/net/packet/PacketProcessor.kt index ca967213c..a171b9c63 100644 --- a/Server/src/main/core/net/packet/PacketProcessor.kt +++ b/Server/src/main/core/net/packet/PacketProcessor.kt @@ -308,7 +308,10 @@ object PacketProcessor { } is Packet.TrackingAfkTimeout -> { if (pkt.player.details.rights != Rights.ADMINISTRATOR) + { + pkt.player.isAfkLogout = true pkt.player.packetDispatch.sendLogout() + } } is Packet.TrackingCameraPos -> { //TODO Refactor the player monitor to be actually useful and log this From 3d7e93b6c2c45707cec1d6394d1c9ff0aa60b1cb Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Sat, 1 Feb 2025 13:53:10 +0000 Subject: [PATCH 186/306] Refactored Antifire potion effect Relicym Balm can now cure disease Antifire potion effect now persists through log out --- .../content/data/consumables/Consumables.java | 7 +-- .../consumables/effects/CureDiseaseEffect.kt | 21 +++++++++ Server/src/main/core/api/ContentAPI.kt | 2 +- .../system/timer/impl/DragonFireImmunity.kt | 47 +++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 Server/src/main/content/data/consumables/effects/CureDiseaseEffect.kt create mode 100644 Server/src/main/core/game/system/timer/impl/DragonFireImmunity.kt diff --git a/Server/src/main/content/data/consumables/Consumables.java b/Server/src/main/content/data/consumables/Consumables.java index 89e90496a..ead89d9d2 100644 --- a/Server/src/main/content/data/consumables/Consumables.java +++ b/Server/src/main/content/data/consumables/Consumables.java @@ -328,7 +328,7 @@ public enum Consumables { ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new AddTimerEffect("poison:immunity", minutesToTicks(9)))), ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new AddTimerEffect("poison:immunity", minutesToTicks(12)))), SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new AddTimerEffect("poison:immunity", minutesToTicks(6)))), - RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveTimerEffect("disease")))), + RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new CureDiseaseEffect())), AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))), HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))), RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))), @@ -340,7 +340,7 @@ public enum Consumables { PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))), SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new RestoreEffect(8, 0.25, true))), ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), - ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))), + ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new AddTimerEffect("dragonfire:immunity", 600, true))), GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))), MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))), SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25, true), new AddTimerEffect("poison:immunity", secondsToTicks(90)), new RemoveTimerEffect("disease")))), @@ -352,7 +352,7 @@ public enum Consumables { ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))), ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new AddTimerEffect("poison:immunity", secondsToTicks(90)), new HealingEffect(3)))), - RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveTimerEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))), + RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new CureDiseaseEffect(), new HealingEffect(3)))), STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))), RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))), SUPER_RESTO_MIX(new BarbarianMix(new int [] {11493, 11495}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25), new HealingEffect(6)))), @@ -367,6 +367,7 @@ public enum Consumables { SUPER_STR_MIX(new BarbarianMix(new int[] {11485, 11487}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 5, 0.15), new HealingEffect(6)))), ANTIDOTE_PLUS_MIX(new BarbarianMix(new int[] {11501, 11503}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(9)), new RandomHealthEffect(3, 7)))), ANTIP_SUPERMIX(new BarbarianMix(new int[] {11473, 11475}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(6)), new RandomHealthEffect(3, 7)))), + ANTIFIRE_MIX(new BarbarianMix(new int[] {11505, 11507}, new MultiEffect(new AddTimerEffect("dragonfire:immunity", 600, true), new RandomHealthEffect(3, 7)))), /** Stealing creation potions */ SC_PRAYER(new Potion(new int[] {14207, 14209, 14211, 14213, 14215}, new PrayerEffect(7, 0.25))), diff --git a/Server/src/main/content/data/consumables/effects/CureDiseaseEffect.kt b/Server/src/main/content/data/consumables/effects/CureDiseaseEffect.kt new file mode 100644 index 000000000..4c63c6e99 --- /dev/null +++ b/Server/src/main/content/data/consumables/effects/CureDiseaseEffect.kt @@ -0,0 +1,21 @@ +package content.data.consumables.effects + +import core.api.* +import core.game.consumable.ConsumableEffect +import core.game.node.entity.player.Player +import core.game.system.timer.impl.Disease + +class CureDiseaseEffect () : ConsumableEffect() { + override fun activate (p: Player) { + val existingTimer = getTimer(p) + if (existingTimer != null) { + existingTimer.hitsLeft -= 9 + if (existingTimer.hitsLeft <= 0) { + sendMessage(p, "The disease has been cured.") + removeTimer(p) + }else{ + sendMessage(p,"You feel slightly better.") + } + } + } +} diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index b4e936906..908accc6d 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -3122,7 +3122,7 @@ fun calculateDragonfireMaxHit(entity: Entity, maxDamage: Int, wyvern: Boolean = if (entity is Player) { hasShield = hasDragonfireShieldProtection(entity, wyvern) - hasPotion = !wyvern && getAttribute(entity, "fire:immune", 0) >= getWorldTicks() + hasPotion = !wyvern && hasTimerActive(entity) hasPrayer = entity.prayer.get(PrayerType.PROTECT_FROM_MAGIC) if (sendMessage) { diff --git a/Server/src/main/core/game/system/timer/impl/DragonFireImmunity.kt b/Server/src/main/core/game/system/timer/impl/DragonFireImmunity.kt new file mode 100644 index 000000000..2f2a2b9e5 --- /dev/null +++ b/Server/src/main/core/game/system/timer/impl/DragonFireImmunity.kt @@ -0,0 +1,47 @@ +package core.game.system.timer.impl + +import core.game.system.timer.* +import core.api.* +import core.tools.* +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import org.json.simple.* +import org.rs09.consts.Sounds + +/** + * A timer that replicates the behavior of Dragon Fire immunity mechanics. Runs every tick. + * Will notify the player of various levels of remaining Dragon Fire immunity, and then remove itself once it has run out. + * This timer is a "soft" timer, meaning it will tick down even while other timers would normally stall (e.g. during entity delays or when the entity has a modal open.) +**/ +class DragonFireImmunity : PersistTimer (1, "dragonfire:immunity", isSoft = true, flags = arrayOf(TimerFlag.ClearOnDeath)) { + var ticksRemaining = 0 + + override fun save (root: JSONObject, entity: Entity) { + root["ticksRemaining"] = ticksRemaining.toString() + } + + override fun parse (root: JSONObject, entity: Entity) { + ticksRemaining = root["ticksRemaining"].toString().toInt() + } + + override fun run (entity: Entity) : Boolean { + ticksRemaining-- + + if (entity is Player && ticksRemaining == secondsToTicks(30)) { + sendMessage(entity, colorize("%RYou have 30 seconds remaining on your antifire potion.")) + playAudio(entity, Sounds.CLOCK_TICK_1_3120, 0, 3) + } + else if (entity is Player && ticksRemaining == 0) { + sendMessage(entity, colorize("%RYour antifire potion has expired.")) + playAudio(entity, Sounds.DRAGON_POTION_FINISHED_2607) + } + + return ticksRemaining > 0 + } + + override fun getTimer (vararg args: Any) : RSTimer { + val t = DragonFireImmunity() + t.ticksRemaining = args.getOrNull(0) as? Int ?: 100 + return t + } +} From fcbea5acdc80df01b26126f693cdfe207d8a91c5 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 13:58:55 +0000 Subject: [PATCH 187/306] Fixed some incorrect replacement doors in Rellekka Disabled the unimplemented TzHaar door Fixed some doors causing buggy player movement --- Server/data/configs/door_configs.json | 4 ++-- .../DeathPlateauInteractionListener.kt | 23 ++++++++----------- .../tzhaar/handlers/TzhaarCityPlugin.java | 13 +++++++---- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Server/data/configs/door_configs.json b/Server/data/configs/door_configs.json index 50cf42836..8da3736ee 100644 --- a/Server/data/configs/door_configs.json +++ b/Server/data/configs/door_configs.json @@ -943,7 +943,7 @@ }, { "id": "4148", - "replaceId": "4248", + "replaceId": "4246", "fence": "false", "metal": "false" }, @@ -1759,7 +1759,7 @@ }, { "id": "14245", - "replaceId": "14248", + "replaceId": "14246", "fence": "true", "metal": "false" }, diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt index ed6850780..dde461532 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt @@ -24,22 +24,19 @@ class DeathPlateauInteractionListener : InteractionListener { ) } override fun defineListeners() { - on(Scenery.DOOR_3747, SCENERY, "open") { player, _ -> - // Harold's Door - if (player.location == location(2906, 3543, 1)) { - openDialogue(player, DeathPlateauDoorDialogueFile(1)) - } else { - DoorActionHandler.handleAutowalkDoor(player, getScenery(2906, 3543, 1)) + on(Scenery.DOOR_3747, SCENERY, "open") { player, node -> + // Harold's door + when (player.location) { + location(2906, 3543, 1), location(2905, 3543, 1), location(2907, 3543, 1) -> openDialogue(player, DeathPlateauDoorDialogueFile(1)) + else -> DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } return@on true } on(Scenery.DOOR_3745, SCENERY, "open") { player, node -> - if (node.location == location(2823, 3555, 0)) { - // 1st Door to Tenzing - openDialogue(player, DeathPlateauDoorDialogueFile(2)) - } else if (node.location == location(2820, 3558, 0)) { - // 2nd Door to chicken pen - openDialogue(player, DeathPlateauDoorDialogueFile(3)) + when (node.location) { + location(2823, 3555, 0) -> openDialogue(player, DeathPlateauDoorDialogueFile(2)) //1st door to Tenzing + location(2820, 3558, 0) -> openDialogue(player, DeathPlateauDoorDialogueFile(3)) //2nd door to chicken pen + else -> DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } return@on true } @@ -94,4 +91,4 @@ class DeathPlateauInteractionListener : InteractionListener { return@on true } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarCityPlugin.java b/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarCityPlugin.java index b4b23b029..669df926a 100644 --- a/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarCityPlugin.java +++ b/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarCityPlugin.java @@ -27,12 +27,11 @@ public final class TzhaarCityPlugin extends OptionHandler { @Override public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(31284).getHandlers().put("option:enter", this);// karamja - // cave. - SceneryDefinition.forId(9359).getHandlers().put("option:enter", this);// tzhaar - // exit + SceneryDefinition.forId(31284).getHandlers().put("option:enter", this); //karamja cave. + SceneryDefinition.forId(9359).getHandlers().put("option:enter", this); //tzhaar exit SceneryDefinition.forId(9356).getHandlers().put("option:enter", this); SceneryDefinition.forId(9369).getHandlers().put("option:pass", this); + SceneryDefinition.forId(31292).getHandlers().put("option:go-through", this); //unimplemented door near fairy ring new TzhaarDialogue().init(); return this; } @@ -65,6 +64,12 @@ public final class TzhaarCityPlugin extends OptionHandler { break; } break; + case "go-through": + switch (id) { + case 31292: + return false; + } + break; } return true; } From c3929cf06c87a946a0d7656b06d7a51f792f037d Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 14:00:59 +0000 Subject: [PATCH 188/306] Fixed telegrab through walls --- .../content/minigame/mta/TelekineticGrabSpell.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java index e2d496492..72728d1e6 100644 --- a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java +++ b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java @@ -4,6 +4,7 @@ import content.minigame.mta.impl.TelekineticZone; import core.game.interaction.SpecialGroundItems; import core.game.node.Node; import core.game.node.entity.Entity; +import core.game.node.entity.combat.CombatSwingHandler; import core.game.node.entity.combat.spell.SpellType; import core.game.node.entity.combat.spell.SpellBlocks; import core.game.node.entity.impl.Projectile; @@ -24,7 +25,7 @@ import core.game.global.action.PickupHandler; import core.game.world.GameWorld; import org.rs09.consts.Sounds; -import static core.api.ContentAPIKt.playAudio; +import static core.api.ContentAPIKt.*; /** * Represents the telekenitic grab spell. @@ -176,8 +177,12 @@ public final class TelekineticGrabSpell extends MagicSpell { } if (entity instanceof Player) { final Player player = (Player) entity; - if (!player.getInventory().hasSpaceFor(((Item) item))) { - player.getPacketDispatch().sendMessage("You don't have enough inventory space."); + if (!CombatSwingHandler.isProjectileClipped(player, item, false)) { + sendMessage(player, "I can't reach that."); //TODO authentic message? + return false; + } + if (!hasSpaceFor(player, item)) { + sendMessage(player, "You don't have enough inventory space."); return false; } if (!PickupHandler.canTake(player, item, 1)) { From 0a26d5039a0705c0e2a9a758807a1275346f64d9 Mon Sep 17 00:00:00 2001 From: troido <13134814-troidio@users.noreply.gitlab.com> Date: Sat, 1 Feb 2025 14:04:03 +0000 Subject: [PATCH 189/306] Aggressive NPCs will no longer always attack the last player to enter the area --- .../node/entity/npc/agg/AggressiveBehavior.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java index 0e525cf95..50f93be3f 100644 --- a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java +++ b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java @@ -72,9 +72,9 @@ public class AggressiveBehavior { if (entity instanceof NPC && target instanceof Player) { NPC npc = (NPC) entity; if (npc.getAggressiveHandler() != null && npc.getAggressiveHandler().isAllowTolerance() && !WildernessZone.isInZone(npc)) { - if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) { - return false; - } + if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) { + return false; + } } } int level = target.getProperties().getCurrentCombatLevel(); @@ -84,9 +84,9 @@ public class AggressiveBehavior { return true; } - public boolean ignoreCombatLevelDifference() { - return false; - } + public boolean ignoreCombatLevelDifference() { + return false; + } /** * Gets the priority flag. @@ -132,9 +132,9 @@ public class AggressiveBehavior { */ public Entity getLogicalTarget(Entity entity, List possibleTargets) { Entity target = null; - int comparingFlag = Integer.MAX_VALUE; + double comparingFlag = Double.MAX_VALUE; for (Entity e : possibleTargets) { - int flag = getPriorityFlag(e); + double flag = (double)getPriorityFlag(e) + Math.random(); if (flag <= comparingFlag) { comparingFlag = flag; target = e; From cd43f8d26946fa603c3ee9a0ab9c10353f7d95d9 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 14:07:03 +0000 Subject: [PATCH 190/306] Star sprite bonus now drops bonus ore if inventory is full Rocks mined attribute now takes into account bonus ore --- .../content/global/skill/gather/mining/MiningListener.kt | 7 +++---- .../content/global/skill/gather/mining/MiningSkillPulse.kt | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/global/skill/gather/mining/MiningListener.kt b/Server/src/main/content/global/skill/gather/mining/MiningListener.kt index d744b0a8f..1e6bb3aa3 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningListener.kt +++ b/Server/src/main/content/global/skill/gather/mining/MiningListener.kt @@ -106,10 +106,9 @@ class MiningListener : InteractionListener { } // Give the mining reward, increment 'rocks mined' attribute - if(addItem(player, reward, rewardAmount)) { - var rocksMined = getAttribute(player, "$STATS_BASE:$STATS_ROCKS", 0) - setAttribute(player, "/save:$STATS_BASE:$STATS_ROCKS", ++rocksMined) - } + addItemOrDrop(player, reward, rewardAmount) + var rocksMined = getAttribute(player, "$STATS_BASE:$STATS_ROCKS", 0) + setAttribute(player, "/save:$STATS_BASE:$STATS_ROCKS", rocksMined + rewardAmount) // Calculate bonus gem chance while mining if (!isEssence) { diff --git a/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt b/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt index aa7ef70e6..31a47cc4b 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt +++ b/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt @@ -164,10 +164,9 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul } // Give the mining reward, increment 'rocks mined' attribute - if(addItem(player, reward, rewardAmount)) { - var rocksMined = getAttribute(player, "$STATS_BASE:$STATS_ROCKS", 0) - setAttribute(player, "/save:$STATS_BASE:$STATS_ROCKS", ++rocksMined) - } + addItemOrDrop(player, reward, rewardAmount) + var rocksMined = getAttribute(player, "$STATS_BASE:$STATS_ROCKS", 0) + setAttribute(player, "/save:$STATS_BASE:$STATS_ROCKS", rocksMined + rewardAmount) // Calculate bonus gem chance while mining if (!isMiningEssence) { From 4a016d45e59ed35641ec7f682ea13887e9c64b3a Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 14:08:55 +0000 Subject: [PATCH 191/306] Fixed farming patches wrongly getting diseased during offline catchup --- Server/src/main/core/game/system/timer/RSTimer.kt | 7 +++++++ Server/src/main/core/game/system/timer/TimerManager.kt | 3 ++- Server/src/main/core/game/system/timer/impl/Disease.kt | 2 +- Server/src/main/core/game/system/timer/impl/Frozen.kt | 2 +- Server/src/main/core/game/system/timer/impl/Miasmic.kt | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/system/timer/RSTimer.kt b/Server/src/main/core/game/system/timer/RSTimer.kt index a995bac75..75770b7bc 100644 --- a/Server/src/main/core/game/system/timer/RSTimer.kt +++ b/Server/src/main/core/game/system/timer/RSTimer.kt @@ -24,8 +24,15 @@ abstract class RSTimer (var runInterval: Int, val identifier: String = "generict **/ open fun getInitialRunDelay() : Int { return runInterval } + /** + * Called by core code before the timer is first registered. Called after parse on PersistTimers. + * Called before the timer has been added to the timer list. + **/ + open fun beforeRegister (entity: Entity) {} + /** * Called by core code when the timer is first registered. Called after parse on PersistTimers. + * Called after the timer has been added to the timer list. **/ open fun onRegister (entity: Entity) {} diff --git a/Server/src/main/core/game/system/timer/TimerManager.kt b/Server/src/main/core/game/system/timer/TimerManager.kt index fd63b7ec5..92bd50e8c 100644 --- a/Server/src/main/core/game/system/timer/TimerManager.kt +++ b/Server/src/main/core/game/system/timer/TimerManager.kt @@ -13,8 +13,9 @@ class TimerManager (val entity: Entity) { val toRemoveTimers = ArrayList() fun registerTimer (timer: RSTimer) { + timer.beforeRegister(entity) + newTimers.add(timer) timer.onRegister(entity) - newTimers.add (timer) } fun processTimers () { diff --git a/Server/src/main/core/game/system/timer/impl/Disease.kt b/Server/src/main/core/game/system/timer/impl/Disease.kt index 7d270e0a9..cfc72ac84 100644 --- a/Server/src/main/core/game/system/timer/impl/Disease.kt +++ b/Server/src/main/core/game/system/timer/impl/Disease.kt @@ -20,7 +20,7 @@ class Disease : PersistTimer (30, "disease", flags = arrayOf(TimerFlag.ClearOnDe hitsLeft = root["hitsLeft"].toString().toInt() } - override fun onRegister (entity: Entity) { + override fun beforeRegister (entity: Entity) { if (hasTimerActive(entity)) removeTimer(entity, this) else if (entity is Player) diff --git a/Server/src/main/core/game/system/timer/impl/Frozen.kt b/Server/src/main/core/game/system/timer/impl/Frozen.kt index 94c5456a4..97fd002f8 100644 --- a/Server/src/main/core/game/system/timer/impl/Frozen.kt +++ b/Server/src/main/core/game/system/timer/impl/Frozen.kt @@ -20,7 +20,7 @@ class Frozen : PersistTimer (1, "frozen", flags = arrayOf(TimerFlag.ClearOnDeath shouldApplyImmunity = root["applyImmunity"] as? Boolean ?: false } - override fun onRegister (entity: Entity) { + override fun beforeRegister (entity: Entity) { if (hasTimerActive(entity)) { removeTimer(entity, this) return diff --git a/Server/src/main/core/game/system/timer/impl/Miasmic.kt b/Server/src/main/core/game/system/timer/impl/Miasmic.kt index d9c1eca18..9af8ee3ad 100644 --- a/Server/src/main/core/game/system/timer/impl/Miasmic.kt +++ b/Server/src/main/core/game/system/timer/impl/Miasmic.kt @@ -15,7 +15,7 @@ class Miasmic : PersistTimer (1, "miasmic", flags = arrayOf(TimerFlag.ClearOnDea return false } - override fun onRegister (entity: Entity) { + override fun beforeRegister (entity: Entity) { if (hasTimerActive(entity)) removeTimer(entity, this) if (hasTimerActive(entity)) From 2cf839269172bb779bd29c92dedcfdd2b5af6fc5 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 14:13:26 +0000 Subject: [PATCH 192/306] Fixed incubator appearing to lose contents --- .../global/skill/summoning/pet/IncubatorHandler.kt | 3 --- .../global/skill/summoning/pet/IncubatorTimer.kt | 13 ++++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/pet/IncubatorHandler.kt b/Server/src/main/content/global/skill/summoning/pet/IncubatorHandler.kt index 79ef7c12d..edb11ca18 100644 --- a/Server/src/main/content/global/skill/summoning/pet/IncubatorHandler.kt +++ b/Server/src/main/content/global/skill/summoning/pet/IncubatorHandler.kt @@ -1,11 +1,8 @@ package content.global.skill.summoning.pet import core.api.* -import core.cache.def.impl.SceneryDefinition import core.game.node.Node import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.node.item.GroundItemManager import core.game.interaction.* import core.tools.StringUtils diff --git a/Server/src/main/content/global/skill/summoning/pet/IncubatorTimer.kt b/Server/src/main/content/global/skill/summoning/pet/IncubatorTimer.kt index 6395a79eb..899deee2a 100644 --- a/Server/src/main/content/global/skill/summoning/pet/IncubatorTimer.kt +++ b/Server/src/main/content/global/skill/summoning/pet/IncubatorTimer.kt @@ -42,6 +42,13 @@ class IncubatorTimer : PersistTimer (500, "incubation") { root["eggs"] = arr } + override fun onRegister(entity: Entity) { + if (entity !is Player) return + for ((region, _) in incubatingEggs) { + setVarbit(entity.asPlayer(), varbitForRegion(region), 1, true) + } + } + override fun run (entity: Entity) : Boolean { if (entity !is Player) return false for ((_, egg) in incubatingEggs) { @@ -60,14 +67,14 @@ class IncubatorTimer : PersistTimer (500, "incubation") { } companion object { - val TAVERLY_REGION = 11573 - val TAVERLY_VARBIT = 4277 + val TAVERLEY_REGION = 11573 + val TAVERLEY_VARBIT = 4277 val YANILLE_REGION = 10288 val YANILLE_VARBIT = 4221 fun varbitForRegion (region: Int) : Int { return when (region) { - TAVERLY_REGION -> TAVERLY_VARBIT + TAVERLEY_REGION -> TAVERLEY_VARBIT YANILLE_REGION -> YANILLE_VARBIT else -> -1 } From 1b858088851fe28fa457355ab27104c24338b590 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sat, 1 Feb 2025 14:15:44 +0000 Subject: [PATCH 193/306] Fixed hostile random events attacking other players Fixed players being able to attack hostile random events for other players Hostile random events now authentically only reward 1/16th xp (except for pheasants, which give 0 xp) --- .../main/content/global/ame/RandomEventNPC.kt | 32 +++++++++++++++++-- .../ame/events/HostileRandomEventBehavior.kt | 19 +++++++++++ .../strangeplant/StrangePlantBehavior.kt | 6 +++- .../MordautDialogue.kt | 2 +- .../MysteriousOldManDialogue.kt | 2 +- .../{ => surpriseexam}/MysteriousOldManNPC.kt | 0 .../SEDoorDialogue.kt | 2 +- .../SEPatternInterface.kt | 2 +- .../SupriseExamListeners.kt | 2 +- .../SurpriseExamUtils.kt | 2 +- .../main/core/game/node/entity/Entity.java | 2 +- 11 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 Server/src/main/content/global/ame/events/HostileRandomEventBehavior.kt rename Server/src/main/content/global/ame/events/{supriseexam => surpriseexam}/MordautDialogue.kt (98%) rename Server/src/main/content/global/ame/events/{ => surpriseexam}/MysteriousOldManDialogue.kt (94%) rename Server/src/main/content/global/ame/events/{ => surpriseexam}/MysteriousOldManNPC.kt (100%) rename Server/src/main/content/global/ame/events/{supriseexam => surpriseexam}/SEDoorDialogue.kt (90%) rename Server/src/main/content/global/ame/events/{supriseexam => surpriseexam}/SEPatternInterface.kt (96%) rename Server/src/main/content/global/ame/events/{supriseexam => surpriseexam}/SupriseExamListeners.kt (98%) rename Server/src/main/content/global/ame/events/{supriseexam => surpriseexam}/SurpriseExamUtils.kt (98%) diff --git a/Server/src/main/content/global/ame/RandomEventNPC.kt b/Server/src/main/content/global/ame/RandomEventNPC.kt index c0aba00af..716420e25 100644 --- a/Server/src/main/content/global/ame/RandomEventNPC.kt +++ b/Server/src/main/content/global/ame/RandomEventNPC.kt @@ -3,9 +3,15 @@ package content.global.ame import content.global.ame.events.MysteriousOldManNPC import core.api.playGlobalAudio import core.api.poofClear +import core.api.sendMessage +import core.api.utils.WeightBasedTable import core.game.interaction.MovementPulse +import core.game.node.entity.Entity +import core.game.node.entity.combat.CombatStyle import core.game.node.entity.impl.PulseType import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.agg.AggressiveBehavior +import core.game.node.entity.npc.agg.AggressiveHandler import core.game.node.entity.player.Player import core.game.node.item.Item import core.game.world.map.Location @@ -13,10 +19,11 @@ import core.game.world.map.RegionManager import core.game.world.map.path.Pathfinder import core.game.world.update.flag.context.Graphics import core.integrations.discord.Discord -import core.api.utils.WeightBasedTable import core.tools.secondsToTicks import core.tools.ticksToCycles import org.rs09.consts.Sounds +import kotlin.math.ceil +import kotlin.math.min import kotlin.random.Random import kotlin.reflect.full.createInstance @@ -66,7 +73,6 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { if (!player.getAttribute("random:pause", false)) { ticksLeft-- } - if (!pulseManager.hasPulseRunning() && !finalized) { follow() } @@ -87,6 +93,11 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { location = spawnLocation player.setAttribute("re-npc", this) super.init() + super.aggressiveHandler = AggressiveHandler(this, object : AggressiveBehavior() { + override fun canSelectTarget(entity: Entity, target: Entity): Boolean { + return target == player + } + }) } open fun onTimeUp() { @@ -118,4 +129,19 @@ abstract class RandomEventNPC(id: Int) : NPC(id) { } abstract fun talkTo(npc: NPC) -} \ No newline at end of file + + override fun isAttackable(entity: Entity, style: CombatStyle, message: Boolean): Boolean { + if (entity != player) { + if (entity is Player) { + sendMessage(entity, "It isn't interested in fighting you.") //TODO authentic message + } + return false + } + return super.isAttackable(entity, style, message) + } + + fun idForCombatLevel(ids: List, player: Player): Int { + val index = min(ids.size, ceil(player.properties.currentCombatLevel / 20.0).toInt()) - 1 + return ids[index] + } +} diff --git a/Server/src/main/content/global/ame/events/HostileRandomEventBehavior.kt b/Server/src/main/content/global/ame/events/HostileRandomEventBehavior.kt new file mode 100644 index 000000000..37083b045 --- /dev/null +++ b/Server/src/main/content/global/ame/events/HostileRandomEventBehavior.kt @@ -0,0 +1,19 @@ +package content.global.ame.events + +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import org.rs09.consts.NPCs + +class HostileRandomEventBehavior : NPCBehavior( + NPCs.EVIL_CHICKEN_2463, NPCs.EVIL_CHICKEN_2464, NPCs.EVIL_CHICKEN_2465, NPCs.EVIL_CHICKEN_2466, NPCs.EVIL_CHICKEN_2467, NPCs.EVIL_CHICKEN_2468, + NPCs.RIVER_TROLL_391, NPCs.RIVER_TROLL_392, NPCs.RIVER_TROLL_393, NPCs.RIVER_TROLL_394, NPCs.RIVER_TROLL_395, NPCs.RIVER_TROLL_396, + NPCs.ROCK_GOLEM_413, NPCs.ROCK_GOLEM_414, NPCs.ROCK_GOLEM_415, NPCs.ROCK_GOLEM_416, NPCs.ROCK_GOLEM_417, NPCs.ROCK_GOLEM_418, + NPCs.SHADE_425, NPCs.SHADE_426, NPCs.SHADE_427, NPCs.SHADE_428, NPCs.SHADE_429, NPCs.SHADE_430, NPCs.SHADE_431, + NPCs.TREE_SPIRIT_438, NPCs.TREE_SPIRIT_439, NPCs.TREE_SPIRIT_440, NPCs.TREE_SPIRIT_441, NPCs.TREE_SPIRIT_442, NPCs.TREE_SPIRIT_443, + NPCs.ZOMBIE_419, NPCs.ZOMBIE_420, NPCs.ZOMBIE_421, NPCs.ZOMBIE_422, NPCs.ZOMBIE_423, NPCs.ZOMBIE_424 +) { + override fun getXpMultiplier(self: NPC, attacker: Entity): Double { + return super.getXpMultiplier(self, attacker) / 16.0 + } +} diff --git a/Server/src/main/content/global/ame/events/strangeplant/StrangePlantBehavior.kt b/Server/src/main/content/global/ame/events/strangeplant/StrangePlantBehavior.kt index cd80ad3d9..0491e01bc 100644 --- a/Server/src/main/content/global/ame/events/strangeplant/StrangePlantBehavior.kt +++ b/Server/src/main/content/global/ame/events/strangeplant/StrangePlantBehavior.kt @@ -32,4 +32,8 @@ class StrangePlantBehavior() : NPCBehavior(NPCs.STRANGE_PLANT_408) { override fun onDeathStarted(self: NPC, killer: Entity) { AntiMacro.terminateEventNpc(killer.asPlayer()) } -} \ No newline at end of file + + override fun getXpMultiplier(self: NPC, attacker: Entity): Double { + return super.getXpMultiplier(self, attacker) / 16.0 + } +} diff --git a/Server/src/main/content/global/ame/events/supriseexam/MordautDialogue.kt b/Server/src/main/content/global/ame/events/surpriseexam/MordautDialogue.kt similarity index 98% rename from Server/src/main/content/global/ame/events/supriseexam/MordautDialogue.kt rename to Server/src/main/content/global/ame/events/surpriseexam/MordautDialogue.kt index ca0e61c3f..d3bd04af0 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/MordautDialogue.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/MordautDialogue.kt @@ -1,4 +1,4 @@ -package content.global.ame.events.supriseexam +package content.global.ame.events.surpriseexam import core.game.component.Component import core.game.dialogue.FacialExpression diff --git a/Server/src/main/content/global/ame/events/MysteriousOldManDialogue.kt b/Server/src/main/content/global/ame/events/surpriseexam/MysteriousOldManDialogue.kt similarity index 94% rename from Server/src/main/content/global/ame/events/MysteriousOldManDialogue.kt rename to Server/src/main/content/global/ame/events/surpriseexam/MysteriousOldManDialogue.kt index 628a3c8f0..1415317a6 100644 --- a/Server/src/main/content/global/ame/events/MysteriousOldManDialogue.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/MysteriousOldManDialogue.kt @@ -1,7 +1,7 @@ package content.global.ame.events import core.game.node.entity.player.Player -import content.global.ame.events.supriseexam.SurpriseExamUtils +import content.global.ame.events.surpriseexam.SurpriseExamUtils import core.game.dialogue.DialogueFile import core.game.system.timer.impl.AntiMacro diff --git a/Server/src/main/content/global/ame/events/MysteriousOldManNPC.kt b/Server/src/main/content/global/ame/events/surpriseexam/MysteriousOldManNPC.kt similarity index 100% rename from Server/src/main/content/global/ame/events/MysteriousOldManNPC.kt rename to Server/src/main/content/global/ame/events/surpriseexam/MysteriousOldManNPC.kt diff --git a/Server/src/main/content/global/ame/events/supriseexam/SEDoorDialogue.kt b/Server/src/main/content/global/ame/events/surpriseexam/SEDoorDialogue.kt similarity index 90% rename from Server/src/main/content/global/ame/events/supriseexam/SEDoorDialogue.kt rename to Server/src/main/content/global/ame/events/surpriseexam/SEDoorDialogue.kt index 3fffea71b..221f4b4fe 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SEDoorDialogue.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SEDoorDialogue.kt @@ -1,4 +1,4 @@ -package content.global.ame.events.supriseexam +package content.global.ame.events.surpriseexam import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE diff --git a/Server/src/main/content/global/ame/events/supriseexam/SEPatternInterface.kt b/Server/src/main/content/global/ame/events/surpriseexam/SEPatternInterface.kt similarity index 96% rename from Server/src/main/content/global/ame/events/supriseexam/SEPatternInterface.kt rename to Server/src/main/content/global/ame/events/surpriseexam/SEPatternInterface.kt index e445c5145..3ba12a8c0 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SEPatternInterface.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SEPatternInterface.kt @@ -1,4 +1,4 @@ -package content.global.ame.events.supriseexam +package content.global.ame.events.surpriseexam import core.game.node.entity.npc.NPC import org.rs09.consts.Components diff --git a/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt b/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt similarity index 98% rename from Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt rename to Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt index 55d61ca09..3fbe1cdc7 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SupriseExamListeners.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt @@ -1,4 +1,4 @@ -package content.global.ame.events.supriseexam +package content.global.ame.events.surpriseexam import core.game.component.Component import core.game.node.entity.player.Player diff --git a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt b/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt similarity index 98% rename from Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt rename to Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt index aa7797b59..1c729efc0 100644 --- a/Server/src/main/content/global/ame/events/supriseexam/SurpriseExamUtils.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt @@ -1,4 +1,4 @@ -package content.global.ame.events.supriseexam +package content.global.ame.events.surpriseexam import core.Server import core.api.* diff --git a/Server/src/main/core/game/node/entity/Entity.java b/Server/src/main/core/game/node/entity/Entity.java index 8058376f9..b566cccb0 100644 --- a/Server/src/main/core/game/node/entity/Entity.java +++ b/Server/src/main/core/game/node/entity/Entity.java @@ -489,7 +489,7 @@ public abstract class Entity extends Node { } /** - * Checks if an entity can continue it's attack. + * Checks if an entity can continue its attack. * @param target the target. * @param style the style. * @return {@code True} if so. From acc6c182a5ee18d60d8284a5f20561ca16cf6ebd Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sat, 1 Feb 2025 14:20:43 +0000 Subject: [PATCH 194/306] Implemented Tears of Guthix Quest Implemented Tears of Guthix Minigame --- Server/data/configs/item_configs.json | 10 +- Server/data/configs/npc_spawns.json | 2 +- .../npc/HouseServantDialogue.java | 2 +- .../global/skill/gather/SkillingResource.java | 13 +- .../skill/gather/mining/MiningNode.java | 18 +- .../handlers/LumbridgeBasementPlugin.java | 89 ---- .../quest/tearsofguthix/JunaDialogue.kt | 203 +++++++++ .../tearsofguthix/LightCreatureBehavior.kt | 129 ++++++ .../quest/tearsofguthix/TearsOfGuthix.kt | 133 ++++++ .../tearsofguthix/TearsOfGuthixListeners.kt | 142 +++++++ .../tearsofguthix/TearsOfGuthixMinigame.kt | 401 ++++++++++++++++++ .../main/core/game/node/entity/npc/NPC.java | 3 + .../command/sets/AnimationCommandSet.kt | 22 +- .../game/world/map/zone/impl/DarkZone.java | 1 + 14 files changed, 1059 insertions(+), 109 deletions(-) create mode 100644 Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt create mode 100644 Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/LightCreatureBehavior.kt create mode 100644 Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt create mode 100644 Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt create mode 100644 Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 91c5fc970..d43d541e9 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -43126,13 +43126,13 @@ "id": "4702" }, { - "shop_price": "975000", - "examine": "A magic stone to make high-level furniture.", - "grand_exchange_price": "977755", + "shop_price": "1", + "examine": "Doesn't look very special.", + "grand_exchange_price": "0", "durability": null, "name": "Magic stone", - "tradeable": "true", - "weight": "1", + "tradeable": "false", + "weight": "2.267", "archery_ticket_price": "0", "id": "4703" }, diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index cd347d1b0..51afed861 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -4609,7 +4609,7 @@ }, { "npc_id": "2021", - "loc_data": "{3222,9525,2,1,3}-{3216,9522,2,1,3}-{3219,9518,2,1,3}-{3224,9521,2,1,3}-{3218,9523,2,1,3}-{3215,9521,2,1,3}-{3213,9522,2,1,3}-{3227,9517,2,1,3}-" + "loc_data": "{3224,9516,2,1,0}-{3224,9517,2,1,0}-{3224,9518,2,1,0}-{3225,9516,2,1,0}-{3225,9517,2,1,0}-{3225,9518,2,1,0}-{3226,9516,2,1,0}-{3226,9517,2,1,0}-{3226,9518,2,1,0}-" }, { "npc_id": "2031", diff --git a/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java b/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java index 4fd2d8c47..ddb967ebe 100644 --- a/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java +++ b/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java @@ -360,7 +360,7 @@ public class HouseServantDialogue extends DialoguePlugin { bankFetch(player, new Item(Items.MARBLE_BLOCK_8786)); break; case 3: //magic stones - bankFetch(player, new Item(Items.MAGIC_STONE_4703)); + bankFetch(player, new Item(Items.MAGIC_STONE_8788)); break; } break; diff --git a/Server/src/main/content/global/skill/gather/SkillingResource.java b/Server/src/main/content/global/skill/gather/SkillingResource.java index 178f6679b..2d2b43e65 100644 --- a/Server/src/main/content/global/skill/gather/SkillingResource.java +++ b/Server/src/main/content/global/skill/gather/SkillingResource.java @@ -612,9 +612,6 @@ public enum SkillingResource { */ RUNITE_ORE_0(2107, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 452, Skills.MINING), RUNITE_ORE_1(2106, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 450, Skills.MINING), - RUNITE_ORE_2(6669, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 21296, Skills.MINING), - RUNITE_ORE_3(6671, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 21298, Skills.MINING), - RUNITE_ORE_4(6670, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 21297, Skills.MINING), RUNITE_ORE_5(14861, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 25373, Skills.MINING), RUNITE_ORE_6(14860, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 25372, Skills.MINING), RUNITE_ORE_7(14859, 85, 0.95, 1250 | 2500 << 16, 125.0, 451, 1, "runite rocks", null, 25371, Skills.MINING), @@ -632,7 +629,15 @@ public enum SkillingResource { */ GEM_ROCK_0(23567, 40, 0.95, 166 | 175 << 16, 65, 1625, 1, "gem rocks", null, 21297, Skills.MINING), GEM_ROCK_1(23566, 40, 0.95, 166 | 175 << 16, 65, 1625, 1, "gem rocks", null, 21296, Skills.MINING), - GEM_ROCK_2(23568, 40, 0.95, 166 | 175 << 16, 65, 1625, 1, "gem rocks", null, 21298, Skills.MINING); + GEM_ROCK_2(23568, 40, 0.95, 166 | 175 << 16, 65, 1625, 1, "gem rocks", null, 21298, Skills.MINING), + + /** + * Magic stone. + */ + MAGIC_STONE_0(6669, 20, 0.3, 100 | 200 << 16, 0.0, 4703, 1, "magic stone", null, 21296, Skills.MINING), + MAGIC_STONE_1(6671, 20, 0.3, 100 | 200 << 16, 0.0, 4703, 1, "magic stone", null, 21298, Skills.MINING), + MAGIC_STONE_2(6670, 20, 0.3, 100 | 200 << 16, 0.0, 4703, 1, "magic stone", null, 21297, Skills.MINING); + /** * The resources mapping. diff --git a/Server/src/main/content/global/skill/gather/mining/MiningNode.java b/Server/src/main/content/global/skill/gather/mining/MiningNode.java index 5f7f00cf3..b271fdee2 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningNode.java +++ b/Server/src/main/content/global/skill/gather/mining/MiningNode.java @@ -403,9 +403,6 @@ public enum MiningNode{ //Runite RUNITE_ORE_0( 2107, 452, (byte) 12), RUNITE_ORE_1( 2106, 450, (byte) 12), - RUNITE_ORE_2( 6669, 21296, (byte) 12), - RUNITE_ORE_3( 6671, 21298, (byte) 12), - RUNITE_ORE_4( 6670, 21297, (byte) 12), RUNITE_ORE_5( 14861,25373, (byte) 12), RUNITE_ORE_6( 14860,25372, (byte) 12), RUNITE_ORE_7( 14859,25371, (byte) 12), @@ -437,8 +434,14 @@ public enum MiningNode{ GRANITE(10947,10945, (byte) 16), //Rubium? - RUBIUM(29746,29747, (byte) 17); + RUBIUM(29746,29747, (byte) 17), + //Magic stone (Tears of Guthix) + MAGIC_STONE_0( 6669, 21296, (byte) 18), // Was mistaken for RUNITE_ORE_2 + MAGIC_STONE_1( 6671, 21298, (byte) 18), // Was mistaken for RUNITE_ORE_3 + MAGIC_STONE_2( 6670, 21297, (byte) 18), // Was mistaken for RUNITE_ORE_4 + + ; public static List gemRockGems = new ArrayList<>(20); @@ -573,6 +576,13 @@ public enum MiningNode{ reward = 12630; level = 46; break; + case 18: + respawnRate = 100 | 200 << 16; + experience = 0.0; + rate = 0.3; + reward = 4703; + level = 20; + break; } } private static HashMap NODE_MAP = new HashMap<>(); diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java index ecdbd5bed..39350352d 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java @@ -55,7 +55,6 @@ public class LumbridgeBasementPlugin extends OptionHandler { SceneryDefinition.forId(40849).getHandlers().put("option:jump-down", this); SceneryDefinition.forId(40260).getHandlers().put("option:climb-through", this); SceneryDefinition.forId(41077).getHandlers().put("option:crawl-through", this); - ClassScanner.definePlugins(new LightCreatureNPC(), new LightCreatureHandler()); SceneryBuilder.add(new Scenery(40260, Location.create(2526, 5828, 2), 2)); return this; } @@ -170,92 +169,4 @@ public class LumbridgeBasementPlugin extends OptionHandler { return null; } - /** - * Handles the sapphire lantern on a light creature. - * @author Vexia - * - */ - public class LightCreatureHandler extends UseWithHandler { - - /** - * Constructs the {@code LightCreatureHandler} - */ - public LightCreatureHandler() { - super( 4700, 4701, 4702); - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - addHandler(2021, NPC_TYPE, this); - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - if (!hasRequirement(player, "While Guthix Sleeps")) - return true; - player.lock(2); - player.teleport(Location.create(2538, 5881, 0)); - return true; - } - - @Override - public Location getDestination(Player player, Node with) { - if (player.getLocation().withinDistance(with.getLocation())) { - return player.getLocation(); - } - return null; - } - - } - - - /** - * Handles the light creature npc. - * @author Vexia - * - */ - public class LightCreatureNPC extends AbstractNPC { - - /** - * Constructs the {@code LightCreatureNPC} - */ - public LightCreatureNPC() { - super(0, null); - this.setWalks(true); - this.setWalkRadius(10); - } - - /** - * Constructs the {@code LightCreatureNPC} - */ - public LightCreatureNPC(int id, Location location) { - super(id, location); - } - - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new LightCreatureNPC(id, location); - } - - @Override - public void handleTickActions() { - if (!getLocks().isMovementLocked()) { - if (isWalks() && !getPulseManager().hasPulseRunning() && nextWalk < GameWorld.getTicks()) { - setNextWalk(); - Location l = getLocation().transform(-5 + RandomFunction.random(getWalkRadius()), -5 + RandomFunction.random(getWalkRadius()), 0); - if (canMove(l)) { - Pathfinder.find(this, l, true, Pathfinder.PROJECTILE).walk(this); - } - } - } - } - - @Override - public int[] getIds() { - return new int[] {2021}; - } - - } } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt new file mode 100644 index 000000000..c319e4988 --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt @@ -0,0 +1,203 @@ +package content.region.misthalin.lumbridge.quest.tearsofguthix + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +/** + * Anim 2056 - Juna puts head into itself + * Anim 2055 - Juna lifts tail + */ +class JunaDialogue : InteractionListener { + override fun defineListeners() { + // Juna is a scenery. + on(Scenery.JUNA_31302, SCENERY, "talk-to") { player, _ -> + openDialogue(player, JunaDialogueFile(), NPC(NPCs.JUNA_2023)) + return@on true + } + // This is quest varbit 451 controlled. When it is set to 2, JUNA changes in ID + on(Scenery.JUNA_31303, SCENERY, "talk-to") { player, node -> + openDialogue(player, JunaDialogueFile(), NPC(NPCs.JUNA_2023)) + return@on true + } + } +} + +class JunaDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(TearsOfGuthix.questName, 0) + .branch { player -> if(TearsOfGuthix.hasRequirements(player)) { 1 } else { 0 } } + .let { branch -> + branch.onValue(0) + // Inauthentic, but absolutely no source on this... + .npcl(FacialExpression.OLD_NORMAL, "You are not strong enough of an adventurer to partake this quest. Come back when you are stronger.") + .linel("You do not meet the quest requirements for Tears of Guthix.") + .end() + return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch. + }.onValue(1) + .npcl(FacialExpression.OLD_NORMAL, "Tell me... a story...") + .playerl(FacialExpression.THINKING, "A story?") + .npcl(FacialExpression.OLD_NORMAL, "I have been waiting here three thousand years, guarding the Tears of Guthix. I serve my master faithfully, but I am bored.") + .npcl(FacialExpression.OLD_NORMAL, "An adventurer such as yourself must have many tales to tell. If you can entertain me, I will let you into the cave for a time.") + .npcl(FacialExpression.OLD_NORMAL, "The more I enjoy your story, the more time I will give you in the cave.") + .npcl(FacialExpression.OLD_NORMAL, "Then you can drink of the power of balance, which will make you stronger in whatever area you are weakest.") + + .let { builder -> + val returnJoin = b.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + + optionBuilder.option_playerl("Okay...") + .linel("You tell Juna some stories of your adventures.") + // Yes I know. + .playerl("Blah blah blah something about recent quest I did that I'm forced to talk about, but looks like you want me to shut up.") + .npcl(FacialExpression.OLD_NORMAL,"Blah blah blah that's so cool, I'm totally interested in what you are saying and am totally not falling asleep at this point.") + // ^ I'm not going to type out 120 fucking quest dialogue for shit you wouldn't care reading. + .npcl(FacialExpression.OLD_NORMAL,"Your stories have entertained me. I will let you into the cave for a short time.") + .npcl(FacialExpression.OLD_NORMAL,"But first you will need to make a bowl in which to collect the tears.") + // The camera pans south to the part of the cave containing guthix-infused rocks. + .npcl(FacialExpression.OLD_NORMAL,"There is a cave on the south side of the chasm that is similarly infused with the power of Guthix. The stone in that cave is the only substance that can catch the Tears of Guthix.") + .npcl(FacialExpression.OLD_NORMAL,"Mine some stone from that cave, make it into a bowl, and bring it to me, and then I will let you catch the Tears.") + .endWith { _, player -> + if(getQuestStage(player, TearsOfGuthix.questName) == 0) { + setQuestStage(player, TearsOfGuthix.questName, 1) + } + } + + optionBuilder.option_playerl("Not now.") + .end() + + optionBuilder.option_playerl("What are the Tears of Guthix?") + .npcl(FacialExpression.OLD_NORMAL, "The Third Age of the world was a time of great conflict, of destruction never seen before or since, when all the gods save Guthix warred for control.") + .npcl(FacialExpression.OLD_NORMAL, "The colossal Wyrms, of whom today's dragons are a pale reflection, turned all the sky to fire, while on the ground armies of foot soldiers, goblins and trolls and humans, filled the valleys and plains with blood.") + .npcl(FacialExpression.OLD_NORMAL, "In time the noise of the conflict woke Guthix from His deep slumber, and He rose and stood in the centre of the battlefield so that the splendour of His wrath filled the world, and He called for the conflict to cease!") + .npcl(FacialExpression.OLD_NORMAL, "Silence fell, for the gods knew that none could challenge the power of the mighty Guthix -- for His power is that of nature itself, to which all other things are subject, in the end.") + .npcl(FacialExpression.OLD_NORMAL, "Guthix reclaimed that which had been stolen from Him, and went back underground to return to His sleep and continue to draw the world's power into Himself.") + .npcl(FacialExpression.OLD_NORMAL, "But on His way into the depths of the earth He sat and rested in this cave; and, thinking of the battle-scarred desert that now stretched from one side of His world to the other, He wept.") + .npcl(FacialExpression.OLD_NORMAL, "And so great was His sorrow, and so great was His life- giving power, that the rocks themselves began to weep with Him.") + .npcl(FacialExpression.OLD_NORMAL, "Later, Guthix noticed that the rocks continued to weep, and that their tears were infused with a small part of His power.") + .npcl(FacialExpression.OLD_NORMAL, "So He set me, His servant, to guard the cave, and He entrusted to me the task of judging who was and was not worthy to access the tears.") + .npcl(FacialExpression.OLD_NORMAL, "Tell me... a story...") + .goto(returnJoin) + } + return@let builder.goto(returnJoin) + } + + + b.onQuestStages(TearsOfGuthix.questName, 1) + .npc(FacialExpression.OLD_NORMAL, "Before you can collect the Tears of Guthix you must", "make a bowl out of the stone in the cave on the south", "of the chasm.") + .branch { player -> if(inInventory(player, Items.STONE_BOWL_4704)) { 1 } else { 0 } } + .let{ branch -> + branch.onValue(0) + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("But I don't know how to reach the cave!") + .npcl(FacialExpression.OLD_NORMAL, "I will tell you the story of the light-creatures.") + .npcl(FacialExpression.OLD_NORMAL, "Myriad and beautiful were the creatures and civilizations of the early ages of the world. Gielinor was a work of art, shaped lovingly over the millennia by the creative mind of Guthix.") + .npcl(FacialExpression.OLD_NORMAL, "Only the sturdiest races survived the Godwars, and even then only by abandoning their high culture and gearing their societies towards war. Of the more delicate races there is now no trace, and almost no memory.") + .npcl(FacialExpression.OLD_NORMAL, "One such race had bodies as fragile as snowflakes, yet they built crystal cities that stood for a thousand years.") + .npcl(FacialExpression.OLD_NORMAL, "The wind would whisper through the spires and fill them with sweet harmonies, and the rising sun would shine through the precious gems that studded the towers and create inter plays of light as if rainbows were dancing.") + .npcl(FacialExpression.OLD_NORMAL, "Indeed, so marvellous was this light-show at its height that the patterns of light themselves became alive, and great flocks of luminous creatures rode along the gem- cast beams, each drawn to its own colour.") + .npcl(FacialExpression.OLD_NORMAL, "The creatures you see floating in this chasm are the last sorry remnants of that age. I do not know how they made their way here and survived to this time, but I am grateful for their company.") + .end() + + optionBuilder.option_playerl("What are the Tears of Guthix?") + .npcl(FacialExpression.OLD_NORMAL, "The Third Age of the world was a time of great conflict, of destruction never seen before or since, when all the gods save Guthix warred for control.") + .npcl(FacialExpression.OLD_NORMAL, "The colossal Wyrms, of whom today's dragons are a pale reflection, turned all the sky to fire, while on the ground armies of foot soldiers, goblins and trolls and humans, filled the valleys and plains with blood.") + .npcl(FacialExpression.OLD_NORMAL, "In time the noise of the conflict woke Guthix from His deep slumber, and He rose and stood in the centre of the battlefield so that the splendour of His wrath filled the world, and He called for the conflict to cease!") + .npcl(FacialExpression.OLD_NORMAL, "Silence fell, for the gods knew that none could challenge the power of the mighty Guthix -- for His power is that of nature itself, to which all other things are subject, in the end.") + .npcl(FacialExpression.OLD_NORMAL, "Guthix reclaimed that which had been stolen from Him, and went back underground to return to His sleep and continue to draw the world's power into Himself.") + .npcl(FacialExpression.OLD_NORMAL, "But on His way into the depths of the earth He sat and rested in this cave; and, thinking of the battle-scarred desert that now stretched from one side of His world to the other, He wept.") + .npcl(FacialExpression.OLD_NORMAL, "And so great was His sorrow, and so great was His life- giving power, that the rocks themselves began to weep with Him.") + .npcl(FacialExpression.OLD_NORMAL, "Later, Guthix noticed that the rocks continued to weep, and that their tears were infused with a small part of His power.") + .npcl(FacialExpression.OLD_NORMAL, "So He set me, His servant, to guard the cave, and He entrusted to me the task of judging who was and was not worthy to access the tears.") + .end() + + optionBuilder.option_playerl("Not now.") + .end() + } + return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch. + }.onValue(1) + .playerl("I have a bowl.") + .npcl(FacialExpression.OLD_NORMAL, "I will keep your bowl for you, so that you may collect the tears many times in the future.") + .npcl(FacialExpression.OLD_NORMAL, "Now... tell me another story, and I will let you collect the tears for the first time.") + .endWith { _, player -> + if (removeItem(player, Items.STONE_BOWL_4704)) { + finishQuest(player, TearsOfGuthix.questName) + } + } + + b.onQuestStages(TearsOfGuthix.questName, 100) + .npcl(FacialExpression.OLD_NORMAL, "Tell me... a story...") + .let { builder -> + val returnJoin = b.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Okay...") + .linel("You tell Juna some stories of your adventures.") + // Yes I know. + .playerl("Blah blah blah something about recent quest I did that I'm forced to talk about, but looks like you want me to shut up.") + .npcl(FacialExpression.OLD_NORMAL,"Blah blah blah that's so cool, I'm totally interested in what you are saying and am totally not falling asleep at this point.") + // ^ I'm not going to type out 120 fucking quest dialogue for shit you wouldn't care reading. + .branch { player -> + if(TearsOfGuthix.daysLeft(player) > 0 && TearsOfGuthix.xpLeft(player) > 0 && TearsOfGuthix.questPointsLeft(player) > 0) { + 3 + } else if(TearsOfGuthix.xpLeft(player) > 0 && TearsOfGuthix.questPointsLeft(player) > 0) { + 2 + } else if(TearsOfGuthix.daysLeft(player) > 0) { + 1 + } else { + 0 // Success branch + } + } + .let{ branch -> + // https://www.youtube.com/watch?v=X3M9CiS_BeU if not enough time has passed. + branch.onValue(3) + .manualStage { df, player, _, _ -> npcl(FacialExpression.OLD_NORMAL,"Your stories have entertained me. But I will not permit any adventurer to access the tears more than once a week. Come back in " + TearsOfGuthix.daysLeft(player).toString() + " days.") } + .npcl(FacialExpression.OLD_NORMAL,"You should use that time to have more adventures! You may not re-enter the cave until you have more stories to tell.") + .manualStage { df, player, _, _ -> sendDialogue(player, "You cannot enter the cave again until you have gained either one quest point or " + TearsOfGuthix.xpLeft(player) + " total XP.") } + .end() + + branch.onValue(2) + .npc(FacialExpression.OLD_NORMAL,"Your story has entertained me. But it is a poor sort", "of adventurer who only tells stories of the past and", "does not find new stories to tell. I will not let you", "into the cave again until you have had more adventures.") + .manualStage { df, player, _, _ -> sendDialogue(player, "You cannot enter the cave again until you have gained either one quest point or " + TearsOfGuthix.xpLeft(player) + " total XP.") } + .end() + + branch.onValue(1) + .manualStage { df, player, _, _ -> npcl(FacialExpression.OLD_NORMAL,"Your stories have entertained me. But I will not permit any adventurer to access the tears more than once a week. Come back in " + TearsOfGuthix.daysLeft(player).toString() + " days.") } + .end() + + return@let branch + }.onValue(0) + .npcl(FacialExpression.OLD_NORMAL,"Your stories have entertained me. I will let you into the cave for a short time.") + .branch { player -> if(TearsOfGuthix.isHandsFree(player)) { 1 } else { 0 } } + .let{ branch -> + // https://www.youtube.com/watch?v=J76OGo-hHlA your hands must be free. + branch.onValue(0) + .npc(FacialExpression.OLD_NORMAL,"But you must have both hands free to carry the bowl.", "Speak to me again when your hands are free.") + .end() + return@let branch + }.onValue(1) + // https://www.youtube.com/watch?v=Mj3pW-Brv9c + .npc(FacialExpression.OLD_NORMAL,"Collect as much as you can from the blue streams. If", "you let in water from the green streams, it will take", "away from the blue. For Guthix is god of balance, and", "balance lies in the juxtaposition of opposites.") + .endWith { _, player -> + TearsOfGuthixMinigame.startGame(player) + } + + optionBuilder.option_playerl("Not now.") + .end() + } + return@let builder.goto(returnJoin) + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/LightCreatureBehavior.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/LightCreatureBehavior.kt new file mode 100644 index 000000000..daa8c6885 --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/LightCreatureBehavior.kt @@ -0,0 +1,129 @@ +package content.region.misthalin.lumbridge.quest.tearsofguthix + +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.world.GameWorld.ticks +import core.game.world.map.Location +import core.game.world.map.path.Pathfinder +import core.tools.RandomFunction +import org.rs09.consts.NPCs + +class LightCreatureBehavior : NPCBehavior(NPCs.LIGHT_CREATURE_2021) { + + companion object { + fun moveLightCreature(self: NPC, location: Location) { + self.setNextWalk() + Pathfinder.find(self, location, true, Pathfinder.PROJECTILE).walk(self) + } + + } + + override fun tick(self: NPC): Boolean { + if (!self.locks.isMovementLocked) { + self.isWalks = true + self.walkRadius = 20 + if (self.isWalks && !self.pulseManager.hasPulseRunning() && self.nextWalk < ticks) { + self.setNextWalk() + val l: Location = self.location.transform(-5 + RandomFunction.random(self.walkRadius), -5 + RandomFunction.random(self.walkRadius), 0) + if (self.canMove(l)) { + Pathfinder.find(self, l, true, Pathfinder.PROJECTILE).walk(self) + } + } + } + return true + } + +} + +/* + + /** + * Handles the sapphire lantern on a light creature. + * @author Vexia + * + */ + public class LightCreatureHandler extends UseWithHandler { + + /** + * Constructs the {@code LightCreatureHandler} + */ + public LightCreatureHandler() { + super( 4700, 4701, 4702); + } + + @Override + public Plugin newInstance(Object arg) throws Throwable { + addHandler(2021, NPC_TYPE, this); + return this; + } + + @Override + public boolean handle(NodeUsageEvent event) { + final Player player = event.getPlayer(); + if (!hasRequirement(player, "While Guthix Sleeps")) + return true; + player.lock(2); + player.teleport(Location.create(2538, 5881, 0)); + return true; + } + + @Override + public Location getDestination(Player player, Node with) { + if (player.getLocation().withinDistance(with.getLocation())) { + return player.getLocation(); + } + return null; + } + + } + + + /** + * Handles the light creature npc. + * @author Vexia + * + */ + public class LightCreatureNPC extends AbstractNPC { + + /** + * Constructs the {@code LightCreatureNPC} + */ + public LightCreatureNPC() { + super(0, null); + this.setWalks(true); + this.setWalkRadius(10); + } + + /** + * Constructs the {@code LightCreatureNPC} + */ + public LightCreatureNPC(int id, Location location) { + super(id, location); + } + + @Override + public AbstractNPC construct(int id, Location location, Object... objects) { + return new LightCreatureNPC(id, location); + } + + @Override + public void handleTickActions() { + if (!getLocks().isMovementLocked()) { + if (isWalks() && !getPulseManager().hasPulseRunning() && nextWalk < GameWorld.getTicks()) { + setNextWalk(); + Location l = getLocation().transform(-5 + RandomFunction.random(getWalkRadius()), -5 + RandomFunction.random(getWalkRadius()), 0); + if (canMove(l)) { + Pathfinder.find(this, l, true, Pathfinder.PROJECTILE).walk(this); + } + } + } + } + + @Override + public int[] getIds() { + return new int[] {2021}; + } + + } +} + */ \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt new file mode 100644 index 000000000..a27e2ba22 --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt @@ -0,0 +1,133 @@ +package content.region.misthalin.lumbridge.quest.tearsofguthix + +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items +import java.util.* + +/** + * Tears of Guthix Quest + * + * Most of the attributes are for the minigame. + * In order to reset, setQuestStage + * + * if (VARPBIT[451] > 1) return 2; if (VARPBIT[451] == 0) return 0; return 1; }; if (arg0 == 88) + */ +@Initializable +class TearsOfGuthix : Quest("Tears of Guthix", 120, 119, 1, 449, 451, 0, 1, 2) { + + companion object { + const val questName = "Tears of Guthix" + const val attributePreviousDate = "/save:quest:tearsofguthix-previousdateofaccess" // The date in milliseconds in which TOG was played. + const val attributePreviousXPAmount = "/save:quest:tearsofguthix-previousxpamount" // The last snapshot of XP user had. + const val attributePreviousQuestPoints = "/save:quest:tearsofguthix-previousquestpoints" // The last snapshot of quest points user had. + + fun isHandsFree(player: Player): Boolean { + return getItemFromEquipment(player, EquipmentSlot.WEAPON) == null + && getItemFromEquipment(player, EquipmentSlot.SHIELD) == null + } + + fun daysLeft(player: Player): Int { + val currentTime = System.currentTimeMillis() + val previousTime = getAttribute(player, attributePreviousDate, 0) + + val numberOfDaysLeft = (currentTime - previousTime) / 86400000L + return 6 - numberOfDaysLeft.toInt() + } + + fun xpLeft(player: Player): Int { + val currentXP = player.skills.totalXp + val previousXP = getAttribute(player, attributePreviousXPAmount, 0) + return 100000 - (currentXP - previousXP) + } + + fun questPointsLeft(player: Player): Int { + val currentQuestPoints = getQuestPoints(player) + val previousQuestPoints = getAttribute(player, attributePreviousQuestPoints, 0) + return 1 - (currentQuestPoints - previousQuestPoints) + } + + fun hasRequirements(player: Player): Boolean { + return arrayOf( + hasLevelStat(player, Skills.FIREMAKING, 49), + hasLevelStat(player, Skills.CRAFTING, 20), + hasLevelStat(player, Skills.MINING, 20), + ).all { it } + } + } + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player, questName) > 0 + + if (!started) { + line(player, "I can start this quest by speaking to !!Juna the serpent?? who", line++, false) + line(player, "lives deep in the !!Lumbridge Swamp Caves??.", line++, false) + line(player, "I will need to have:", line++, false) + line(player, "Level 49 firemaking", line++, hasLevelStat(player, Skills.FIREMAKING, 49)) + line(player, "!!Level 20 crafting??", line++, hasLevelStat(player, Skills.CRAFTING, 20)) + line(player, "!!Level 20 mining??", line++, hasLevelStat(player, Skills.MINING, 20)) + line(player, "!!43 quest points??", line++, getQuestPoints(player) >= 55) + line(player, "!!Level 49 crafting would be an advantage??", line++, hasLevelStat(player, Skills.CRAFTING, 49)) + line(player, "!!Level 49 smithing would be an advantage??", line++, hasLevelStat(player, Skills.SMITHING, 49)) + } else if (stage < 100) { + line(player, "I met Juna the serpent in a deep chasm beneath the", line++, true) + line(player, "Lumbridge Swamp Caves.", line++, true) + line(player, "I told her a story and she said she would let me into the", line++, false) + line(player, "Tears of Guthix cave if I brought her a !!bowl?? made from the", line++, false) + line(player, "stone in !!the cave on the South side of the chasm??.", line++, false) + } else { + line(player, "I met Juna the serpent in a deep chasm beneath the", line++, true) + line(player, "Lumbridge Swamp Caves. I made a bowl out of magical", line++, true) + line(player, "stone in order to catch the Tears of Guthix.", line++, true) + line++ + line(player,"QUEST COMPLETE!", line++) + line++ + line(player, "Now Juna will let me into the cave to collect the Tears if I", line++, false) + line(player, "!!tell her stories?? of my adventures.", line++, false) + // TOG Minigame + if (daysLeft(player) > 0 && xpLeft(player) > 0 && questPointsLeft(player) > 0) { + line(player, "I will be able to collect the Tears of Guthix !!in " + daysLeft(player) + " days??, as", line++, false) + line(player, "long as I gain either !!1 Quest Point?? or !!" + xpLeft(player) + " total XP??", line++, false) + } else if (xpLeft(player) > 0 && questPointsLeft(player) > 0) { + line(player, "I will be able to collect the Tears of Guthix, as long as I", line++, false) + line(player, "gain either !!1 Quest Point?? or !!" + xpLeft(player) + " total XP??", line++, false) + } else if (daysLeft(player) > 0) { + line(player, "I will be able to collect the Tears of Guthix !!in " + daysLeft(player) + " days??.", line++, false) + } else { + line(player, "I have had enough adventures to tell Juna more stories,", line++, false) + line(player, "and a week has passed since I last collected the Tears. I", line++, false) + line(player, "can visit Juna again now.", line++, false) + } + } + } + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed the Tears of Guthix quest!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.STONE_BOWL_4704,230,277,5) + + drawReward(player, "1 quest point", ln++) + drawReward(player, "1,000 Crafting XP", ln++) + drawReward(player, "Access to the Tears of Guthix", ln++) + drawReward(player, "cave", ln++) + + rewardXP(player, Skills.CRAFTING, 1000.0) + } + + override fun reset(player: Player) { + removeAttribute(player, attributePreviousDate) + removeAttribute(player, attributePreviousXPAmount) + removeAttribute(player, attributePreviousQuestPoints) + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt new file mode 100644 index 000000000..ef5477186 --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt @@ -0,0 +1,142 @@ +package content.region.misthalin.lumbridge.quest.tearsofguthix + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.impl.ForceMovement +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Direction +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class TearsOfGuthixListeners : InteractionListener { + + companion object { + fun crossTheChasm(player: Player, with: NPC) { + // Unless you have time to animate this, this fucking thing is waaay too complicated. + // THIS IS JUST AESTHETICS + // You have to do the following: + // 1 - Get the light creature to your location. + // 2 - Animate both you and the light creature to float up. + // 3 - Walk both YOU AND THE LIGHT CREATURE to the other side. + // 4 - Float both you and the light creature to the ground. + // + // 2046 - Magically float into the air + // 2047 - Magically float back to the ground + // 2048 - Keep floating in the air + + // Instead you will just get fucking thrown to that other side. + val lightCreature = with as NPC + sendMessage(player, "The light-creature is attracted to your beam and comes towards you...") + LightCreatureBehavior.moveLightCreature(lightCreature, player.location) + // Could also do player.appearance.setAnimations(Animation(913)) which is the group animation for floating. + if (player.location.y > 9516) { + forceMove(player, player.location, Location.create(3229, 9504, 2), 0, 400, null, 2048) + } else { + forceMove(player, player.location, Location.create(3228, 9527, 2), 0, 400, null, 2048) + } + } + } + + override fun defineListeners() { + // Similar to RockClimbShortcut.kt + on(Scenery.ROCKS_6673, SCENERY, "climb") { player, _ -> + if (player.location.x > 3240) { + ForceMovement.run(player, player.location, Location.create(player.location).transform(-2, 0, 0), Animation(1148), Animation(1148), Direction.WEST, 13).endAnimation = Animation.RESET + } else { + ForceMovement.run(player, player.location, Location.create(player.location).transform(2, 0, 0), Animation(1148), Animation(1148), Direction.WEST, 13).endAnimation = Animation.RESET + } + return@on true + } + // Similar to RockClimbShortcut.kt + on(Scenery.ROCKS_6672, SCENERY, "climb") { player, _ -> + if (player.location.x > 3239) { + sendMessage(player, "You could climb down here, but it is too uneven to climb up.") + } else { + ForceMovement.run(player, player.location, Location.create(player.location).transform(2, 0, 0), Animation(1148), Animation(1148), Direction.WEST, 13).endAnimation = Animation.RESET + } + return@on true + } + + // Please note: part of this is already done in craftBullseyeLantern() except for the swapping out which is here. + onUseWith(ITEM, Items.BULLSEYE_LANTERN_4548, Items.SAPPHIRE_1607) { player, used, with -> + sendMessage(player, "You swap the lantern's lens for a sapphire.") + if(removeItem(player, with) && removeItem(player, used)) { + addItemOrDrop(player, Items.SAPPHIRE_LANTERN_4701) + addItemOrDrop(player, Items.LANTERN_LENS_4542) + } + return@onUseWith true + } + onUseWith(ITEM, Items.SAPPHIRE_LANTERN_4701, Items.LANTERN_LENS_4542) { player, used, with -> + sendMessage(player, "You swap the lantern's sapphire for a lens.") + if(removeItem(player, with) && removeItem(player, used)) { + addItemOrDrop(player, Items.BULLSEYE_LANTERN_4548) + addItemOrDrop(player, Items.SAPPHIRE_1607) + } + return@onUseWith true + } + onUseWith(ITEM, Items.BULLSEYE_LANTERN_4549, Items.SAPPHIRE_1607) { player, used, with -> + sendMessage(player, "The lantern is too hot to do that while it is lit.") + return@onUseWith true + } + onUseWith(ITEM, Items.SAPPHIRE_LANTERN_4702, Items.LANTERN_LENS_4542) { player, used, with -> + sendMessage(player, "The lantern is too hot to do that while it is lit.") + return@onUseWith true + } + + // MAGIC_STONE are set in MiningNode, but I can't change the messages without screwing up + // When examining ore: sendMessage(player, "This rock contains a magical kind of stone.") + // When mining: sendMessage(player, "You manage to mine some stone.") + // If you have stone in your inventory: sendMessage(player, "You have already mined some stone. You don't need any more.") + + // Note: The construction MAGIC_STONE is MAGIC_STONE_8788 NOT MAGIC_STONE_4703 WHICH IS FOR TEARS OF GUTHIX + onUseWith(ITEM, Items.MAGIC_STONE_4703, Items.CHISEL_1755) { player, used, with -> + sendMessage(player, "You make a stone bowl.") + if(removeItem(player, used)) { + addItemOrDrop(player, Items.STONE_BOWL_4704) + } + return@onUseWith true + } + + onUseWith(NPC, Items.SAPPHIRE_LANTERN_4702, NPCs.LIGHT_CREATURE_2021) { player, used, with -> + if (hasRequirement(player, "While Guthix Sleeps")) { + // Options when you have WGS - B6KHH7AQc2Q + openDialogue(player, object : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + when(stage){ + 0 -> interpreter!!.sendOptions("Select an Option", "Across the Chasm.", "Into the Chasm.").also { stage++ } + 1 -> when(buttonID){ + 1 -> { + crossTheChasm(player, with as NPC) + end() + } + 2 -> { + // This was old. + player.lock(2) + player.teleport(Location.create(2538, 5881, 0)) + end() + } + } + } + } + }) + } else { + crossTheChasm(player, with as NPC) + } + return@onUseWith true + } + + } + + override fun defineDestinationOverrides() { + setDest(IntType.NPC, intArrayOf(NPCs.LIGHT_CREATURE_2021),"use"){ player, node -> + return@setDest player.location + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt new file mode 100644 index 000000000..cda71126e --- /dev/null +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt @@ -0,0 +1,401 @@ +package content.region.misthalin.lumbridge.quest.tearsofguthix + +import core.api.* +import core.game.component.Component +import core.game.event.EventHook +import core.game.event.TickEvent +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction +import core.game.world.update.flag.context.Animation +import org.rs09.consts.Components +import org.rs09.consts.Items +import org.rs09.consts.Scenery + +/** + * // ::setvarbit 454 (varp 449 7-11) 0-10 where its just time bar length + * // ::setvarbit 455 (varp 449 12-20) X where x is number of points he gets + * + * anim 2040 - Hold bowl + * anim 2041 - Walk with ToG Bowl + * anim 2042 - Run with ToG Bowl + * anim 2043 - Fill ToG bowl + * anim 2044 - Finish filling from ToG + * anim 2045 - Drink from bowl + * + */ +class TearsOfGuthixMinigame : InteractionListener, EventHook, MapArea { + companion object { + + const val varbitTimeBar = 454 + const val varbitPoints = 455 + const val attributeTicksRemaining = "minigame:tearsofguthix-ticksremaining" + const val attributeTearsCollected = "minigame:tearsofguthix-tearscollected" + const val attributeIsCollecting = "minigame:tearsofguthix-iscollecting" + + // In order specified by RS + private val rewardArray = arrayOf( + Skills.COOKING, + Skills.CRAFTING, + Skills.FIREMAKING, + Skills.FISHING, + Skills.MAGIC, + Skills.MINING, + Skills.PRAYER, + Skills.RANGE, + Skills.RUNECRAFTING, + Skills.SMITHING, + Skills.WOODCUTTING, + Skills.AGILITY, + Skills.HERBLORE, + Skills.FLETCHING, + Skills.THIEVING, + Skills.SLAYER, + Skills.ATTACK, + Skills.DEFENCE, + Skills.STRENGTH, + Skills.HITPOINTS, + Skills.FARMING, + Skills.CONSTRUCTION, + Skills.HUNTER, + Skills.SUMMONING, // This isn't but lmao. + ) + // In order specified by RS + val rewardText = arrayOf( + "You have a brief urge to cook some food.", + "Your fingers feel nimble and suited to delicate work.", + "You have a brief urge to set light to something.", + "You gain a deep understanding of the creatures of the sea.", + "You feel the power of the runes surging through you. ", + "You gain a deep understanding of the stones of the earth.", + "You suddenly feel very close to the gods.", + "Your aim improves.", + "You gain a deep understanding of runes.", + "You gain a deep understanding of all types of metal.", + "You gain a deep understanding of the trees in the wood.", + "You feel very nimble.", + "You gain a deep understanding of all kinds of strange plants.", + "You gain a deep understanding of wooden sticks.", + "You feel your respect for others' property slipping away.", + "You gain a deep understanding of many strange creatures.", + "You feel a brief surge of aggression.", + "You feel more able to defend yourself.", + "Your muscles bulge.", + "You feel very healthy.", + "You gain a deep understanding of the cycles of nature.", + "You feel homesick.", + "You briefly experience the joy of the hunt.", + "You feel at one with nature.", + ) + + /** Calculates the XP to reward. */ + fun rewardTears(player: Player) { + val lowestSkill = rewardArray.reduce{ acc, curr -> + // If you don't have construction, you cannot earn xp on it. + if (curr == Skills.CONSTRUCTION && !hasHouse(player)) { + acc + } + // If you don't have Druidic Ritual completed, you cannot earn xp on it. + else if (curr == Skills.HERBLORE && !isQuestComplete(player, "Druidic Ritual")) { + acc + } + // If you don't have Rune Mysteries, you cannot earn xp on it. + else if (curr == Skills.RUNECRAFTING && !isQuestComplete(player, "Rune Mysteries")) { + acc + } + // If you don't have Wolf Whistle, you cannot earn xp on it. + else if (curr == Skills.SUMMONING && !isQuestComplete(player, "Wolf Whistle")) { + acc + } + else if (player.skills.getExperience(acc) <= player.skills.getExperience(curr)) { + acc + } else { + curr + } + } + + var perTearXP = 60.0 // Caps at level 30, giving 60 per XP. + if (getStatLevel(player, lowestSkill) < 30) { + perTearXP = (getStatLevel(player, lowestSkill) - 1) * 1.724137 // From 50/29 + perTearXP += 10 + } + + sendMessage(player, rewardText[rewardArray.indexOf(lowestSkill)]) + + val tearsCollected = getAttribute(player, attributeTearsCollected, 0) + rewardXP(player, lowestSkill, perTearXP * tearsCollected) + } + + /** Opens interface, walks the player to the center and start game. */ + fun startGame(player: Player) { + lock(player, 15) + // Opens the Tears of Guthix Interface in the tab. + player.interfaceManager.openSingleTab(Component(Components.TOG_WATER_BOWL_4)) + // Sets up the interface varbits. + setAttribute(player, attributeTicksRemaining, getQuestPoints(player) + 15) // 15 to offset the stupid walking. + setAttribute(player, attributeTearsCollected, 0) + setVarbit(player, varbitTimeBar, 10) + setVarbit(player,varbitPoints, 0) + + // Forces the player to hold a bowl and animate accordingly. + replaceSlot(player, EquipmentSlot.WEAPON.ordinal, Item(Items.STONE_BOWL_4704), null, Container.EQUIPMENT) + // Change the player's SET ANIMATIONS to the bowl holding set. Found using ::ranim + player.appearance.setAnimations(Animation(357)) // THIS WAS TRIAL AND ERROR AND WAS FUCKING HARD TO FIND + player.appearance.sync() + + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + val distance = player.location.getDistance(Location(3251, 9516, 2)).toInt() + 1// Per tick? + forceMove(player, player.location, Location(3251, 9516, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 1 -> { + face(player, Location(3252, 9516, 2)) + val junaScenery = getScenery(Location(3252, 9516, 2)) + if (junaScenery != null) { + animateScenery(junaScenery, 2055) + } + return@queueScript delayScript(player, 2) + } + 2 -> { + val distance = player.location.getDistance(Location(3253, 9516, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3253, 9516, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 3 -> { + face(player, Location(3253, 9517, 2)) + return@queueScript delayScript(player, 2) + } + 4 -> { + val distance = player.location.getDistance(Location(3253, 9517, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3253, 9517, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 5 -> { + face(player, Location(3257, 9517, 2)) + return@queueScript delayScript(player, 2) + } + 6 -> { + val distance = player.location.getDistance(Location(3257, 9517, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3257, 9517, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 7 -> { + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + fun endGame(player: Player) { + lock(player, 22) + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + sendMessage(player, "Your time in the cave is up.") + val distance = player.location.getDistance(Location(3253, 9517, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3253, 9517, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 1 -> { + face(player, Location(3253, 9516, 2)) + return@queueScript delayScript(player, 2) + } + 2 -> { + val distance = player.location.getDistance(Location(3253, 9516, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3253, 9516, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 3 -> { + face(player, Location(3251, 9516, 2)) + val junaScenery = getScenery(Location(3252, 9516, 2)) + if (junaScenery != null) { + animateScenery(junaScenery, 2055) + } + return@queueScript delayScript(player, 2) + } + 4 -> { + val distance = player.location.getDistance(Location(3251, 9516, 2)).toInt() + 1 // Per tick? + forceMove(player, player.location, Location(3251, 9516, 2), 0, distance * 15, null, 2041) + return@queueScript delayScript(player, distance) + } + 5 -> { + sendMessage(player, "You drink the liquid...") + animate(player, 2045) + return@queueScript delayScript(player, 3) + } + 6 -> { + rewardTears(player) + setAttribute(player, TearsOfGuthix.attributePreviousDate, System.currentTimeMillis()) + setAttribute(player, TearsOfGuthix.attributePreviousXPAmount, player.skills.totalXp) + setAttribute(player, TearsOfGuthix.attributePreviousQuestPoints, getQuestPoints(player)) + removeAttribute(player, attributeTearsCollected) + if (player.interfaceManager.singleTab?.id == 4) { + player.interfaceManager.closeSingleTab() + } + player.interfaceManager.restoreTabs() + removeItem(player, Items.STONE_BOWL_4704, Container.EQUIPMENT) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + } + + override fun defineListeners() { + + on(Scenery.WEEPING_WALL_6660, SCENERY, "collect-from") { player, node -> + animate(player, 2043) + val index = TearsOfGuthixGlobalTick.allWalls.indexOf(node.location) + setAttribute(player, attributeIsCollecting, index) + return@on true + } + + } + + // Timer step per tick while you are in the minigame. + override fun process(entity: Entity, event: TickEvent) { + if (entity is Player) { + if (getAttribute(entity, attributeTicksRemaining, -1) > 0) { + setAttribute(entity, attributeTicksRemaining, getAttribute(entity, attributeTicksRemaining, 0) - 1) + setVarbit(entity, varbitTimeBar, (getAttribute(entity, attributeTicksRemaining, 0) * 10 / getQuestPoints(entity)), false) + if (getAttribute(entity, attributeIsCollecting, 0) != 0) { + val currentArrayIndex = getAttribute(entity, attributeIsCollecting, 0) + val currentTearState = TearsOfGuthixGlobalTick.globalWallState[currentArrayIndex] + if (currentTearState == 1) { + setAttribute(entity, attributeTearsCollected, getAttribute(entity, attributeTearsCollected, 0) + 1) + } else if (currentTearState == 2 && getAttribute(entity, attributeTearsCollected, 0) > 0){ + setAttribute(entity, attributeTearsCollected, getAttribute(entity, attributeTearsCollected, 0) - 1) + } + setVarbit(entity, varbitPoints, getAttribute(entity, attributeTearsCollected, 0)) + } + } else if (getAttribute(entity, attributeTicksRemaining, -1) == 0) { + removeAttribute(entity, attributeTicksRemaining) + endGame(entity) + } + } + } + + + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders(3253, 9513, 3262, 9522, 2)) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + if (getAttribute(entity, attributeTicksRemaining, 0) <= 0) { + removeItem(entity, Items.STONE_BOWL_4704, Container.EQUIPMENT) + teleport(entity, Location(3251, 9516, 2)) + } else { + entity.hook(Event.Tick, this) + } + } + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + entity.unhook(this) + if (logout) { + removeItem(entity, Items.STONE_BOWL_4704, Container.EQUIPMENT) + removeAttribute(entity, attributeTearsCollected) + removeAttribute(entity, attributeTicksRemaining) + teleport(entity, Location(3251, 9516, 2)) + } + } + } + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + entity.hook(Event.Tick, this) + setAttribute(entity, attributeIsCollecting, 0) // If you move, you ain't collecting + } + } +} + +/** + * Global Tick class to randomize the walls consistently for everyone. + */ +class TearsOfGuthixGlobalTick : TickListener { + + companion object { + var ticks = 0 + var globalWallState = intArrayOf(0, 0, 2, 1, 2, 1, 0, 0, 2, 1) + val allWalls = arrayOf( + // Blank + Location(0, 0, 0), + // Left Walls + Location(3258, 9520, 2), + Location(3261, 9516, 2), + Location(3261, 9518, 2), + Location(3257, 9514, 2), + Location(3259, 9514, 2), + // Right Walls + Location(3257, 9520, 2), + Location(3259, 9520, 2), + Location(3261, 9517, 2), + Location(3258, 9514, 2), + ) + } + + override fun tick() { + // Do this every 10 ticks. + if (ticks++ > 10) { ticks = 0 } else { return } + // Shuffle the walls + val wallStates = intArrayOf(0, 0, 0, 1, 1, 1, 2, 2, 2) // 0 is absent, 1 is blue, 2 is green + wallStates.shuffle() + globalWallState = intArrayOf(0) + wallStates + + /* + * Explanation: The walls are layered sceneries, which makes it rabidly fucked to change them. + * What I did was to add the tears scenery first (essentially overriding the tears scenery), + * then add the WEEPING_WALL_6660 right after it so that the interactions are still there. + * this is how a layer is like: + * 1 - WEEPING_WALL_6660 - No model, but holds the option "collect-from" + * 2 - BLUE/GREEN/ABSENT - Model of the blue/green/absent waterfall. + * 3 - WEEPING_WALL_6664 - The actual model, but not interactive. + * 6661 - 6664 is left side, 6665 to 6668 is right side + */ + wallStates.forEachIndexed { index, state -> + val scenery = getScenery(allWalls[index + 1])!! + val newSceneryId = if (state == 2) { + if (index + 1 <= 5) { + Scenery.GREEN_TEARS_6662 + } else { + Scenery.GREEN_TEARS_6666 + } + } else if (state == 1) { + if (index + 1 <= 5) { + Scenery.BLUE_TEARS_6661 + } else { + Scenery.BLUE_TEARS_6665 + } + } else { + if (index + 1 <= 5) { + Scenery.ABSENCE_OF_TEARS_6663 + } else { + Scenery.ABSENCE_OF_TEARS_6667 + } + } + addScenery(core.game.node.scenery.Scenery( + newSceneryId, + scenery.location, + 4, + scenery.rotation + )) + addScenery(core.game.node.scenery.Scenery(Scenery.WEEPING_WALL_6660, scenery.location, 0, scenery.rotation)) + } + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/node/entity/npc/NPC.java b/Server/src/main/core/game/node/entity/npc/NPC.java index 053713888..38691b7c9 100644 --- a/Server/src/main/core/game/node/entity/npc/NPC.java +++ b/Server/src/main/core/game/node/entity/npc/NPC.java @@ -523,6 +523,9 @@ public class NPC extends Entity { return false; } + public int getNextWalk() { + return nextWalk; + } /** * Sets the next walk. */ diff --git a/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt b/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt index ada26eaca..2ac6a0957 100644 --- a/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt @@ -56,11 +56,23 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) { if (args.size < 2) { reject(player, "Syntax error: ::ranim ") } - try { - player.appearance.setAnimations(Animation.create(args[1].toInt())) - player.appearance.sync() - } catch (e: NumberFormatException) { - reject(player, "Syntax error: ::ranim ") + if (args.size > 2) { + GameWorld.Pulser.submit(object : Pulse(3, player) { + var id = args[1].toInt() + override fun pulse(): Boolean { + player.appearance.setAnimations(Animation.create(id)) + player.appearance.sync() + player.sendChat("Current: $id") + return ++id >= args[2].toInt() + } + }) + } else { + try { + player.appearance.setAnimations(Animation.create(args[1].toInt())) + player.appearance.sync() + } catch (e: NumberFormatException) { + reject(player, "Syntax error: ::ranim ") + } } } diff --git a/Server/src/main/core/game/world/map/zone/impl/DarkZone.java b/Server/src/main/core/game/world/map/zone/impl/DarkZone.java index 1340dcde2..5d955031a 100644 --- a/Server/src/main/core/game/world/map/zone/impl/DarkZone.java +++ b/Server/src/main/core/game/world/map/zone/impl/DarkZone.java @@ -85,6 +85,7 @@ public final class DarkZone extends MapZone implements EventHook{ public void configure() { register(new ZoneBorders(1728, 5120, 1791, 5247)); registerRegion(12693); + registerRegion(12948); registerRegion(12949); register(new ZoneBorders(3306,9661,3222,9600)); register(new ZoneBorders(3717,9473,3841,9346)); From c03947e0b0d6ca27b1ed0f84a9bc0fd935e466bc Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 3 Feb 2025 00:48:51 +0000 Subject: [PATCH 195/306] Cleaned up legacy save code --- .../skill/construction/HouseManager.java | 53 -------- .../global/skill/construction/Servant.java | 36 +----- .../skill/gather/mining/MiningSkillPulse.kt | 3 +- .../core/cache/def/impl/ClothDefinition.java | 1 - .../core/cache/def/impl/ItemDefinition.java | 8 +- .../def/impl/RenderAnimationDefinition.java | 1 - .../cache/def/impl/SceneryDefinition.java | 1 - .../main/core/game/container/Container.java | 49 ------- .../game/container/impl/BankContainer.java | 20 --- .../core/game/node/entity/player/Player.java | 120 +++++++----------- .../player/info/login/PlayerSaveParser.kt | 17 --- .../entity/player/info/login/PlayerSaver.kt | 14 -- .../node/entity/player/link/QuestData.java | 14 -- .../node/entity/player/link/SavedData.java | 50 -------- .../node/entity/player/link/Settings.java | 60 +-------- .../core/game/node/entity/skill/Skills.java | 25 ---- .../game/node/entity/state/PlayerState.kt | 3 - .../main/core/game/node/entity/state/State.kt | 42 ------ .../game/node/entity/state/StatePulse.java | 89 ------------- .../game/node/entity/state/StateRepository.kt | 41 ------ .../entity/state/impl/FireResistantPulse.java | 77 ----------- .../communication/CommunicationInfo.java | 24 ---- .../game/system/config/GroundSpawnLoader.kt | 13 -- 23 files changed, 53 insertions(+), 708 deletions(-) delete mode 100644 Server/src/main/core/game/node/entity/state/PlayerState.kt delete mode 100644 Server/src/main/core/game/node/entity/state/State.kt delete mode 100644 Server/src/main/core/game/node/entity/state/StatePulse.java delete mode 100644 Server/src/main/core/game/node/entity/state/StateRepository.kt delete mode 100644 Server/src/main/core/game/node/entity/state/impl/FireResistantPulse.java diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index fd4968171..372b976d2 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -20,7 +20,6 @@ import core.game.world.GameWorld; import org.rs09.consts.Sounds; import java.awt.*; -import java.nio.ByteBuffer; import static core.api.ContentAPIKt.*; import static core.api.regionspec.RegionSpecificationKt.fillWith; @@ -99,36 +98,6 @@ public final class HouseManager { } - public void save(ByteBuffer buffer) { - buffer.put((byte) location.ordinal()); - buffer.put((byte) style.ordinal()); - if (hasServant()) { - servant.save(buffer); - } else { - buffer.put((byte) -1); - } - for (int z = 0; z < 4; z++) { - for (int x = 0; x < 8; x++) { - for (int y = 0; y < 8; y++) { - Room room = rooms[z][x][y]; - if (room != null) { - buffer.put((byte) z).put((byte) x).put((byte) y); - buffer.put((byte) room.getProperties().ordinal()); - buffer.put((byte) room.getRotation().toInteger()); - for (int i = 0; i < room.getHotspots().length; i++) { - if (room.getHotspots()[i].getDecorationIndex() > -1) { - buffer.put((byte) i); - buffer.put((byte) room.getHotspots()[i].getDecorationIndex()); - } - } - buffer.put((byte) -1); - } - } - } - } - buffer.put((byte) -1);//Eof - } - public void parse(JSONObject data){ location = HouseLocation.values()[Integer.parseInt( data.get("location").toString())]; style = HousingStyle.values()[Integer.parseInt( data.get("style").toString())]; @@ -155,28 +124,6 @@ public final class HouseManager { } } - - public void parse(ByteBuffer buffer) { - location = HouseLocation.values()[buffer.get() & 0xFF]; - style = HousingStyle.values()[buffer.get() & 0xFF]; - servant = Servant.parse(buffer); - int z = 0; - while ((z = buffer.get()) != -1) { - if (z == 3) { - hasDungeon = true; - } - int x = buffer.get(); - int y = buffer.get(); - Room room = rooms[z][x][y] = new Room(RoomProperties.values()[buffer.get() & 0xFF]); - room.configure(style); - room.setRotation(Direction.get(buffer.get() & 0xFF)); - int spot = 0; - while ((spot = buffer.get()) != -1) { - room.getHotspots()[spot].setDecorationIndex(buffer.get() & 0xFF); - } - } - } - /** * Prepares for entering the player's house. * @param player diff --git a/Server/src/main/content/global/skill/construction/Servant.java b/Server/src/main/content/global/skill/construction/Servant.java index 63275330d..a3527bdad 100644 --- a/Server/src/main/content/global/skill/construction/Servant.java +++ b/Server/src/main/content/global/skill/construction/Servant.java @@ -5,8 +5,6 @@ import core.game.node.entity.npc.NPC; import core.game.node.item.Item; import org.json.simple.JSONObject; -import java.nio.ByteBuffer; - /** * Represents a player's servant. * @author Emperor @@ -44,26 +42,9 @@ public final class Servant extends NPC { } /** - * Saves the servant details. - * @param buffer The buffer to write on. - */ - public void save(ByteBuffer buffer) { - buffer.put((byte) type.ordinal()); - buffer.putShort((byte) uses); - if (item == null) { - buffer.putShort((short) -1); - } else { - buffer.putShort((short) item.getId()); - buffer.putInt(item.getAmount()); - } - buffer.put((byte) (greet ? 1 : 0)); - } - - /** - * Parses the servant from the buffer. + * Parses the servant from the save file. * @return The servant. */ - public static Servant parse(JSONObject data){ int type = Integer.parseInt( data.get("type").toString()); Servant servant = new Servant(ServantType.values()[type]); @@ -77,21 +58,6 @@ public final class Servant extends NPC { return servant; } - public static Servant parse(ByteBuffer buffer) { - int type = buffer.get(); - if (type == -1) { - return null; - } - Servant servant = new Servant(ServantType.values()[type]); - servant.uses = buffer.getShort() & 0xFFFF; - int itemId = buffer.getShort() & 0xFFFF; - if ((short) itemId != -1) { - servant.item = new Item(itemId, buffer.getInt()); - } - servant.greet = buffer.get() == 1; - return servant; - } - /** * Gets the item value. * @return The item. diff --git a/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt b/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt index 31a47cc4b..58464672e 100644 --- a/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt +++ b/Server/src/main/content/global/skill/gather/mining/MiningSkillPulse.kt @@ -11,6 +11,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills import content.data.skill.SkillingTool +import content.global.activity.shootingstar.StarBonus import content.global.skill.skillcapeperks.SkillcapePerks import core.game.node.item.ChanceItem import core.game.node.scenery.Scenery @@ -224,7 +225,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul } // If player has mining boost from Shooting Star, roll chance at extra ore - if (player.hasActiveState("shooting-star")) { + if (hasTimerActive(player)) { if (RandomFunction.getRandom(5) == 3) { sendMessage(player, "...you manage to mine a second ore thanks to the Star Sprite.") amount += 1 diff --git a/Server/src/main/core/cache/def/impl/ClothDefinition.java b/Server/src/main/core/cache/def/impl/ClothDefinition.java index 27c63cc53..c100c16ef 100644 --- a/Server/src/main/core/cache/def/impl/ClothDefinition.java +++ b/Server/src/main/core/cache/def/impl/ClothDefinition.java @@ -1,7 +1,6 @@ package core.cache.def.impl; import java.nio.ByteBuffer; -import java.util.Arrays; import core.ServerConstants; import core.cache.Cache; diff --git a/Server/src/main/core/cache/def/impl/ItemDefinition.java b/Server/src/main/core/cache/def/impl/ItemDefinition.java index 60baf51ea..88ba3712d 100644 --- a/Server/src/main/core/cache/def/impl/ItemDefinition.java +++ b/Server/src/main/core/cache/def/impl/ItemDefinition.java @@ -1,6 +1,6 @@ package core.cache.def.impl; -import core.ServerConstants; +import content.global.skill.summoning.familiar.BurdenBeast; import core.api.EquipmentSlot; import core.cache.Cache; import core.cache.def.Definition; @@ -12,17 +12,12 @@ import core.game.node.entity.skill.Skills; import core.game.node.item.Item; import core.game.node.item.ItemPlugin; import core.game.world.GameWorld; -import core.net.packet.PacketRepository; -import core.net.packet.out.WeightUpdate; -import core.plugin.Plugin; import core.tools.Log; import core.tools.StringUtils; -import core.tools.SystemLogger; import core.game.system.config.ItemConfigParser; import org.rs09.consts.Items; import java.nio.ByteBuffer; -import java.text.DecimalFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -33,7 +28,6 @@ import static core.api.ContentAPIKt.log; /** * Represents an item's definitions. - * @author Jagex * @author Emperor */ public class ItemDefinition extends Definition { diff --git a/Server/src/main/core/cache/def/impl/RenderAnimationDefinition.java b/Server/src/main/core/cache/def/impl/RenderAnimationDefinition.java index f68060e46..881e4040d 100644 --- a/Server/src/main/core/cache/def/impl/RenderAnimationDefinition.java +++ b/Server/src/main/core/cache/def/impl/RenderAnimationDefinition.java @@ -2,7 +2,6 @@ package core.cache.def.impl; import core.cache.Cache; import core.tools.Log; -import core.tools.SystemLogger; import core.game.world.GameWorld; import java.lang.reflect.Array; diff --git a/Server/src/main/core/cache/def/impl/SceneryDefinition.java b/Server/src/main/core/cache/def/impl/SceneryDefinition.java index 60ba83f99..6172d7828 100644 --- a/Server/src/main/core/cache/def/impl/SceneryDefinition.java +++ b/Server/src/main/core/cache/def/impl/SceneryDefinition.java @@ -7,7 +7,6 @@ import core.game.interaction.OptionHandler; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; import core.tools.Log; -import core.tools.SystemLogger; import core.game.world.GameWorld; import java.nio.ByteBuffer; diff --git a/Server/src/main/core/game/container/Container.java b/Server/src/main/core/game/container/Container.java index 431151cd0..5cecb6905 100644 --- a/Server/src/main/core/game/container/Container.java +++ b/Server/src/main/core/game/container/Container.java @@ -8,7 +8,6 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.rs09.consts.Items; -import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -560,30 +559,6 @@ public class Container { return -1; } - /** - * Parses the container data from the byte buffer. - * - * @param buffer The byte buffer. - * @return The total value of all items (G.E price > Store price > High - * alchemy price). - */ - public int parse(ByteBuffer buffer) { - int slot; - int total = 0; - while ((slot = buffer.getShort()) != -1) { - int id = buffer.getShort() & 0xFFFF; - int amount = buffer.getInt(); - int charge = buffer.getInt(); - if (id >= ItemDefinition.getDefinitions().size() || slot >= items.length || slot < 0) { - continue; - } - Item item = items[slot] = new Item(id, amount, charge); - item.setIndex(slot); - total += item.getValue(); - } - return total; - } - public void parse(JSONArray itemArray){ AtomicInteger total = new AtomicInteger(0); itemArray.forEach(item -> { @@ -601,30 +576,6 @@ public class Container { }); } - /** - * Saves the item data on the byte buffer. - * - * @param buffer The byte buffer. - * @return The total value of all items (G.E price > Store price > High - * alchemy price). - */ - public long save(ByteBuffer buffer) { - long totalValue = 0; - for (int i = 0; i < items.length; i++) { - Item item = items[i]; - if (item == null) { - continue; - } - buffer.putShort((short) i); - buffer.putShort((short) item.getId()); - buffer.putInt(item.getAmount()); - buffer.putInt(item.getCharge()); - totalValue += item.getValue(); - } - buffer.putShort((short) -1); - return totalValue; - } - /** * Copies the container to this container. * diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index f8f994d4d..5fb95791b 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -165,26 +165,6 @@ public final class BankContainer extends Container { open = true; } - - @Override - public long save(ByteBuffer buffer) { - buffer.putInt(lastAmountX); - buffer.put((byte) tabStartSlot.length); - for (int j : tabStartSlot) { - buffer.putShort((short) j); - } - return super.save(buffer); - } - - @Override - public int parse(ByteBuffer buffer) { - lastAmountX = buffer.getInt(); - int length = buffer.get() & 0xFF; - for (int i = 0; i < length; i++) { - tabStartSlot[i] = buffer.getShort(); - } - return super.parse(buffer); - } /** * Closes the bank. diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 13e6e7d31..70f944c39 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -71,8 +71,6 @@ import core.game.node.entity.combat.CombatSwingHandler; import content.global.handlers.item.equipment.EquipmentDegrader; import core.game.node.entity.combat.graves.Grave; import core.game.node.entity.combat.graves.GraveController; -import core.game.node.entity.state.State; -import core.game.node.entity.state.StateRepository; import core.game.world.GameWorld; import core.game.world.repository.Repository; import core.game.world.update.MapChunkRenderer; @@ -123,10 +121,9 @@ public class Player extends Entity { public VarpManager varpManager = new VarpManager(this); - public HashMap varpMap = new HashMap<>(); - public HashMap saveVarp = new HashMap<>(); + public HashMap varpMap = new HashMap<>(); - public HashMap states = new HashMap<>(); + public HashMap saveVarp = new HashMap<>(); public HashMap> logoutListeners = new HashMap<>(); @@ -500,21 +497,21 @@ public class Player extends Entity { if (i == null) break; totalWealth += (long) i.getDefinition().getValue() * i.getAmount(); } - GrandExchangeRecords ge = GrandExchangeRecords.getInstance(this); - for (int i=0; i<6; i++) { - GrandExchangeOffer offer = ge.getOffer(i); - if (offer != null) { - totalWealth += offer.cacheValue(); - } - } + GrandExchangeRecords ge = GrandExchangeRecords.getInstance(this); + for (int i=0; i<6; i++) { + GrandExchangeOffer offer = ge.getOffer(i); + if (offer != null) { + totalWealth += offer.cacheValue(); + } + } - // This can lead to a false positive of up to 3 * 187.5k, but only for 3 ticks while a cannon is being constructed - if (this.getAttribute("dmc", null) != null) { - totalWealth += ItemDefinition.forId(Items.CANNON_BASE_6).getValue(); - totalWealth += ItemDefinition.forId(Items.CANNON_STAND_8).getValue(); - totalWealth += ItemDefinition.forId(Items.CANNON_BARRELS_10).getValue(); - totalWealth += ItemDefinition.forId(Items.CANNON_FURNACE_12).getValue(); - } + // This can lead to a false positive of up to 3 * 187.5k, but only for 3 ticks while a cannon is being constructed + if (this.getAttribute("dmc", null) != null) { + totalWealth += ItemDefinition.forId(Items.CANNON_BASE_6).getValue(); + totalWealth += ItemDefinition.forId(Items.CANNON_STAND_8).getValue(); + totalWealth += ItemDefinition.forId(Items.CANNON_BARRELS_10).getValue(); + totalWealth += ItemDefinition.forId(Items.CANNON_FURNACE_12).getValue(); + } long diff = previousWealth == -1 ? 0L : totalWealth - previousWealth; setAttribute("/save:last-wealth", totalWealth); @@ -557,15 +554,15 @@ public class Player extends Entity { return this.getIndex() | 0x8000; } - @Override - public void onAttack (Entity e) { - if (e instanceof Player) { - Player p = (Player) e; - if (skullManager.isWildernessDisabled()) { - return; - } - } - } + @Override + public void onAttack (Entity e) { + if (e instanceof Player) { + Player p = (Player) e; + if (skullManager.isWildernessDisabled()) { + return; + } + } + } @Override public CombatSwingHandler getSwingHandler(boolean swing) { @@ -594,7 +591,7 @@ public class Player extends Entity { @Override public void commenceDeath(Entity killer) { - if (!isPlaying()) return; + if (!isPlaying()) return; super.commenceDeath(killer); if (prayer.get(PrayerType.RETRIBUTION)) { prayer.startRetribution(killer); @@ -747,18 +744,18 @@ public class Player extends Entity { if (entity instanceof NPC && !((NPC) entity).getDefinition().hasAction("attack") && !((NPC) entity).isIgnoreAttackRestrictions(this)) { return false; } - if (entity instanceof Player) { - Player p = (Player) entity; - if (p.getSkullManager().isWilderness() && skullManager.isWilderness()) { - if (!GameWorld.getSettings().getWild_pvp_enabled()) - return false; - if (p.getSkullManager().hasWildernessProtection()) - return false; - if (skullManager.hasWildernessProtection()) - return false; - return true; - } else return false; - } + if (entity instanceof Player) { + Player p = (Player) entity; + if (p.getSkullManager().isWilderness() && skullManager.isWilderness()) { + if (!GameWorld.getSettings().getWild_pvp_enabled()) + return false; + if (p.getSkullManager().hasWildernessProtection()) + return false; + if (skullManager.hasWildernessProtection()) + return false; + return true; + } else return false; + } return super.isAttackable(entity, style, message); } @@ -1346,7 +1343,6 @@ public class Player extends Entity { return "Player [name=" + name + ", getRights()=" + getRights() + "]"; } - public String getCustomState() { return customState; } @@ -1372,37 +1368,15 @@ public class Player extends Entity { this.archeryTotal = archeryTotal; } - public boolean hasActiveState(String key){ - State state = states.get(key); - if(state != null && state.getPulse() != null){ - return true; + public void updateAppearance() { + getUpdateMasks().register(EntityFlag.Appearance, this); + } + + public void incrementInvalidPacketCount() { + invalidPacketCount++; + if (invalidPacketCount >= 5) { + clear(); + log(this.getClass(), Log.ERR, "Disconnecting " + getName() + " for having a high rate of invalid packets. Potential packet bot misbehaving, or simply really bad connection."); } - return false; } - - public State registerState(String key){ - return StateRepository.forKey(key, this); - } - - public void clearState(String key){ - State state = states.get(key); - if(state == null) return; - Pulse pulse = state.getPulse(); - if(pulse != null) { - pulse.stop(); - } - states.remove(key); - } - - public void updateAppearance() { - getUpdateMasks().register(EntityFlag.Appearance, this); - } - - public void incrementInvalidPacketCount() { - invalidPacketCount++; - if (invalidPacketCount >= 5) { - clear(); - log(this.getClass(), Log.ERR, "Disconnecting " + getName() + " for having a high rate of invalid packets. Potential packet bot misbehaving, or simply really bad connection."); - } - } } diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index b48f72e63..03fc75d67 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -59,7 +59,6 @@ class PlayerSaveParser(val player: Player) { parseAppearance() parseGrave() parseVarps() - parseStates() parseSpellbook() parseSavedData() parseAutocastSpell() @@ -174,22 +173,6 @@ class PlayerSaveParser(val player: Player) { player.bankPinManager.parse(bpData) } - fun parseStates() { - player.states.clear() - if (saveFile!!.containsKey("states")) { - val states: JSONArray = saveFile!!["states"] as JSONArray - for (state in states) { - val s = state as JSONObject - val stateId = s["stateKey"].toString() - if(player.states[stateId] != null) continue - val stateClass = player.registerState(stateId) - stateClass?.parse(s) - stateClass?.init() - player.states.put(stateId,stateClass) - } - } - } - fun parseFamiliars() { val familiarData = saveFile!!["familiarManager"] as JSONObject player.familiarManager.parse(familiarData) diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 8b34bebb4..11c15b4d8 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -47,7 +47,6 @@ class PlayerSaver (val player: Player){ savePlayerMonitor(saveFile) saveMusicPlayer(saveFile) saveFamiliarManager(saveFile) - saveStateManager(saveFile) saveBankPinData(saveFile) saveHouseData(saveFile) saveAchievementData(saveFile) @@ -262,19 +261,6 @@ class PlayerSaver (val player: Player){ root.put("bankPinManager",bankPinManager) } - fun saveStateManager(root: JSONObject){ - val states = JSONArray() - player.states.forEach{key,clazz -> - if(clazz != null && clazz.pulse != null) { - val stateObj = JSONObject() - stateObj.put("stateKey", key) - clazz.save(stateObj) - states.add(stateObj) - } - } - root.put("states",states) - } - fun saveFamiliarManager(root: JSONObject){ val familiarManager = JSONObject() val petDetails = JSONObject() diff --git a/Server/src/main/core/game/node/entity/player/link/QuestData.java b/Server/src/main/core/game/node/entity/player/link/QuestData.java index aa58c395f..110c89e01 100644 --- a/Server/src/main/core/game/node/entity/player/link/QuestData.java +++ b/Server/src/main/core/game/node/entity/player/link/QuestData.java @@ -5,7 +5,6 @@ import core.game.node.item.Item; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import java.nio.ByteBuffer; import java.util.Arrays; /** @@ -97,19 +96,6 @@ public final class QuestData { witchsExperimentStage = Integer.parseInt( data.get("witchsExperimentStage").toString()); } - /** - * Saves the desert treasure node. - * @param buffer The buffer. - */ - private final void saveDesertTreasureNode(ByteBuffer buffer) { - buffer.put((byte) 8); - for (int i = 0; i < desertTreasure.length; i++) { - Item item = desertTreasure[i]; - buffer.putShort((short) item.getId()); - buffer.put((byte) item.getAmount()); - } - } - /** * Gets the draynorLever. * @return The draynorLever. diff --git a/Server/src/main/core/game/node/entity/player/link/SavedData.java b/Server/src/main/core/game/node/entity/player/link/SavedData.java index fc62f3a72..a0e005592 100644 --- a/Server/src/main/core/game/node/entity/player/link/SavedData.java +++ b/Server/src/main/core/game/node/entity/player/link/SavedData.java @@ -2,8 +2,6 @@ package core.game.node.entity.player.link; import core.game.node.entity.player.Player; -import java.nio.ByteBuffer; - /** * Represents a managing class of saved data related to ingame interactions, * such as questing data, npc talking data, etc. @@ -39,45 +37,6 @@ public class SavedData { this.player = player; } - /** - * Method used to save an activity var that isn't valued at default. - * @param buffer the buffer. - * @param var the variable to save. - */ - public static final void save(final ByteBuffer buffer, final Object var, final int index) { - if (var instanceof Integer ? (int) var != 0 : var instanceof Double ? (double) var != 0.0 : var instanceof Byte ? (byte) var != 0 : var instanceof Short ? (short) var != 0 : var instanceof Long ? (long) var != 0L : var instanceof Boolean ? (boolean) var != false : var != null) { - buffer.put((byte) index); - if (var instanceof Integer) { - buffer.putInt((int) var); - } else if (var instanceof Byte) { - buffer.put((byte) var); - } else if (var instanceof Short) { - buffer.putShort((short) var); - } else if (var instanceof Long) { - buffer.putLong((long) var); - } else if (var instanceof Boolean) { - buffer.put((byte) 1); - } else if (var instanceof Double) { - buffer.putDouble((double) var); - } else if (var instanceof double[]) { - double[] doubleArray = ((double[]) var); - for (int i = 0; i < doubleArray.length; i++) { - buffer.putDouble(doubleArray[i]); - } - } else if (var instanceof boolean[]) { - boolean[] booleanArray = ((boolean[]) var); - for (int i = 0; i < booleanArray.length; i++) { - buffer.put((byte) (booleanArray[i] ? 1 : 0)); - } - } else if (var instanceof int[]) { - int[] intArray = ((int[]) var); - for (int i = 0; i < intArray.length; i++) { - buffer.putInt(intArray[i]); - } - } - } - } - /** * Gets the boolean value. * @param value the value. @@ -87,15 +46,6 @@ public class SavedData { return value == 1; } - /** - * Gets the boolean value. - * @param buffer the buffer. - * @return the value. - */ - public static boolean getBoolean(ByteBuffer buffer) { - return getBoolean(buffer.get()); - } - /** * Gets the activityData. * @return The activityData. diff --git a/Server/src/main/core/game/node/entity/player/link/Settings.java b/Server/src/main/core/game/node/entity/player/link/Settings.java index 640e44723..920a65629 100644 --- a/Server/src/main/core/game/node/entity/player/link/Settings.java +++ b/Server/src/main/core/game/node/entity/player/link/Settings.java @@ -4,12 +4,8 @@ import core.game.system.config.ItemConfigParser; import org.json.simple.JSONObject; import core.game.node.entity.player.Player; import core.game.node.item.Item; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; import core.net.packet.IoBuffer; -import java.nio.ByteBuffer; - import static core.api.ContentAPIKt.*; @@ -199,61 +195,9 @@ public final class Settings { } /** - * Writes the settings on the byte buffer. - * @param buffer The byte buffer. + * Parses the settings from the save file. + * @param settingsData The JSON object. */ - public void save(ByteBuffer buffer) { - buffer.put((byte) 1).put((byte) brightness).put((byte) musicVolume).put((byte) soundEffectVolume).put((byte) areaSoundVolume).put((byte) (singleMouseButton ? 1 : 0)).put((byte) (disableChatEffects ? 1 : 0)).put((byte) (splitPrivateChat ? 1 : 0)).put((byte) (acceptAid ? 1 : 0)).put((byte) (runToggled ? 1 : 0)).put((byte) publicChatSetting).put((byte) privateChatSetting).put((byte) clanChatSetting).put((byte) tradeSetting).put((byte) assistSetting).put(((byte) runEnergy)); - if (!player.getProperties().isRetaliating()) { - buffer.put((byte) 2); - } - if (specialEnergy != 100) { - buffer.put((byte) 3).put((byte) specialEnergy); - } - if (attackStyleIndex != 0) { - buffer.put((byte) 4).put((byte) attackStyleIndex); - } - buffer.put((byte) 0); - } - - /** - * Parses the settings from the byte buffer. - * @param buffer The byte buffer. - */ - public void parse(ByteBuffer buffer) { - int opcode; - while ((opcode = buffer.get() & 0xFF) != 0) { - switch (opcode) { - case 1: - brightness = buffer.get(); - musicVolume = buffer.get(); - soundEffectVolume = buffer.get(); - areaSoundVolume = buffer.get(); - singleMouseButton = buffer.get() == 1; - disableChatEffects = buffer.get() == 1; - splitPrivateChat = buffer.get() == 1; - acceptAid = buffer.get() == 1; - runToggled = buffer.get() == 1; - publicChatSetting = buffer.get(); - privateChatSetting = buffer.get(); - clanChatSetting = buffer.get(); - tradeSetting = buffer.get(); - assistSetting = buffer.get(); - runEnergy = buffer.get(); - break; - case 2: - player.getProperties().setRetaliating(false); - break; - case 3: - specialEnergy = buffer.get() & 0xFF; - break; - case 4: - attackStyleIndex = buffer.get(); - break; - } - } - } - public void parse(JSONObject settingsData){ brightness = Integer.parseInt( settingsData.get("brightness").toString()); musicVolume = Integer.parseInt( settingsData.get("musicVolume").toString()); diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index 9f550245a..19debcc0e 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -25,7 +25,6 @@ import core.plugin.CorePluginTypes.XPGainPlugins; import org.rs09.consts.Items; import org.rs09.consts.Sounds; -import java.nio.ByteBuffer; import java.util.ArrayList; import static core.api.ContentAPIKt.getWorldTicks; @@ -413,30 +412,6 @@ public final class Skills { updateCombatLevel(); } - public void parseExpRate(ByteBuffer buffer) { - experienceMultiplier = buffer.getDouble(); - if(GameWorld.getSettings().getDefault_xp_rate() != experienceMultiplier){ - experienceMultiplier = GameWorld.getSettings().getDefault_xp_rate(); - } - } - - /** - * Saves the skill data on the buffer. - * @param buffer The byte buffer. - */ - public void save(ByteBuffer buffer) { - for (int i = 0; i < 24; i++) { - buffer.putInt((int) (experience[i] * 10)); - buffer.put((byte) dynamicLevels[i]); - buffer.put((byte) staticLevels[i]); - } - buffer.putInt((int) experienceGained); - } - - public void saveExpRate(ByteBuffer buffer) { - buffer.putDouble(experienceMultiplier); - } - /** * Refreshes all the skill levels. */ diff --git a/Server/src/main/core/game/node/entity/state/PlayerState.kt b/Server/src/main/core/game/node/entity/state/PlayerState.kt deleted file mode 100644 index bfc15b2c4..000000000 --- a/Server/src/main/core/game/node/entity/state/PlayerState.kt +++ /dev/null @@ -1,3 +0,0 @@ -package core.game.node.entity.state - -annotation class PlayerState(val key: String) diff --git a/Server/src/main/core/game/node/entity/state/State.kt b/Server/src/main/core/game/node/entity/state/State.kt deleted file mode 100644 index 20dcd9385..000000000 --- a/Server/src/main/core/game/node/entity/state/State.kt +++ /dev/null @@ -1,42 +0,0 @@ -package core.game.node.entity.state - -import core.game.node.entity.player.Player -import core.game.system.task.Pulse -import org.json.simple.JSONObject -import core.game.world.GameWorld.Pulser - -/** - * A class representing a state that the player or some associated thing can be in. - * @param player The player the state is for - * @author Ceikry - */ -abstract class State(val player: Player? = null) { - var pulse: Pulse? = null - - /** - * Saves any additional data the state might need to the player's save. - */ - abstract fun save(root: JSONObject) - - /** - * Parses any additional saved data the state might have. - */ - abstract fun parse(_data: JSONObject) - - /** - * Returns a new instance of the class constructed for the player. - */ - abstract fun newInstance(player: Player? = null) : State - - /** - * Method used to define the pulse the state uses. - * Called during the init method of the state, which is done during save parsing and done - * manually when first creating a state. - */ - abstract fun createPulse() - fun init() { - createPulse() - pulse ?: return - Pulser.submit(pulse!!) - } -} \ No newline at end of file diff --git a/Server/src/main/core/game/node/entity/state/StatePulse.java b/Server/src/main/core/game/node/entity/state/StatePulse.java deleted file mode 100644 index c4f006be0..000000000 --- a/Server/src/main/core/game/node/entity/state/StatePulse.java +++ /dev/null @@ -1,89 +0,0 @@ -package core.game.node.entity.state; - -import core.game.node.entity.Entity; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; - -import java.nio.ByteBuffer; - -/** - * Represents a state pulse. - * @author Emperor - */ -public abstract class StatePulse extends Pulse { - - /** - * The entity. - */ - protected final Entity entity; - - /** - * Constructs a new {@code StatePulse} {@code Object}. - * @param entity The entity. - * @param ticks The amount of ticks. - */ - public StatePulse(Entity entity, int ticks) { - super(ticks, entity); - super.stop(); - this.entity = entity; - } - - /** - * Checks if data has to be saved. - * @return {@code True} if so. - */ - public abstract boolean isSaveRequired(); - - /** - * Saves the state data. - * @param buffer The buffer. - */ - public abstract void save(ByteBuffer buffer); - - /** - * Parses the state data. - * @param entity The entity. - * @param buffer The buffer. - * @return The state pulse created. - */ - public abstract StatePulse parse(Entity entity, ByteBuffer buffer); - - /** - * Creates a new instance of this state pulse. - * @param entity The entity. - * @param args The arguments. - * @return The state pulse. - */ - public abstract StatePulse create(Entity entity, Object... args); - - /** - * Checks if this pulse can be ran for the given entity. - * @param entity The entity. - * @return {@code True} if so. - */ - public boolean canRun(Entity entity) { - return true; - } - - /** - * Called when the pulse gets manually removed. - */ - public void remove() { - /* - * empty. - */ - } - - /** - * Runs the pulse. - */ - public void run() { - if (isRunning()) { - return; - } - restart(); - start(); - GameWorld.getPulser().submit(this); - } - -} \ No newline at end of file diff --git a/Server/src/main/core/game/node/entity/state/StateRepository.kt b/Server/src/main/core/game/node/entity/state/StateRepository.kt deleted file mode 100644 index 8e437e6f4..000000000 --- a/Server/src/main/core/game/node/entity/state/StateRepository.kt +++ /dev/null @@ -1,41 +0,0 @@ -package core.game.node.entity.state - -import core.api.StartupListener -import core.game.node.entity.player.Player -import io.github.classgraph.ClassGraph - -class StateRepository : StartupListener{ - override fun startup() { - loadStateClasses() - } - - companion object { - val states = HashMap() - - fun loadStateClasses() - { - val result = ClassGraph().enableClassInfo().enableAnnotationInfo().acceptPackages("content").scan() - result.getClassesWithAnnotation("core.game.node.entity.state.PlayerState").forEach{ - val key = it.getAnnotationInfo("core.game.node.entity.state.PlayerState").parameterValues[0].value as String - val clazz = it.loadClass().newInstance() - if(clazz is State) { - states.put(key, clazz) - } - } - } - - @JvmStatic - fun forKey(key: String, player: Player): State?{ - val state = states[key] - if(player.hasActiveState(key)){ - return states[key] - } - if(state != null){ - val clazz = state.newInstance(player) - player.states[key] = clazz - return clazz - } - return null - } - } -} diff --git a/Server/src/main/core/game/node/entity/state/impl/FireResistantPulse.java b/Server/src/main/core/game/node/entity/state/impl/FireResistantPulse.java deleted file mode 100644 index b00e4cbbd..000000000 --- a/Server/src/main/core/game/node/entity/state/impl/FireResistantPulse.java +++ /dev/null @@ -1,77 +0,0 @@ -package core.game.node.entity.state.impl; - -import core.game.node.entity.Entity; -import core.game.node.entity.player.Player; -import core.game.node.entity.state.StatePulse; -import core.game.world.GameWorld; - -import java.nio.ByteBuffer; - -/** - * The pulse used for fire resistant. - * @author Vexia - */ -public class FireResistantPulse extends StatePulse { - - /** - * The time to finish. - */ - private static int END_TIME = GameWorld.getSettings().isDevMode() ? 30 : 600; - - /** - * The current tick. - */ - private int currentTick; - - /** - * If the potion is an extended antifire. - */ - private boolean extended; - - /** - * Constructs a new {@Code FireResistantPulse} {@Code Object} - * @param entity the entity. - * @param ticks the ticks. - */ - public FireResistantPulse(Entity entity, int ticks, int currentTick, boolean extended) { - super(entity, ticks); - this.extended = extended; - this.currentTick = currentTick; - } - - @Override - public boolean isSaveRequired() { - return true; - } - - @Override - public void save(ByteBuffer buffer) { - buffer.putInt(currentTick); - } - - @Override - public StatePulse parse(Entity entity, ByteBuffer buffer) { - return new FireResistantPulse(entity, 1, buffer.getInt(), extended); - } - - @Override - public StatePulse create(Entity entity, Object... args) { - return new FireResistantPulse(entity, 1, 0, (boolean) args[0]); - } - - @Override - public boolean pulse() { - if(extended && currentTick == 0 && END_TIME < 1200){ - END_TIME += 600; - } - if (entity instanceof Player) { - if (currentTick == (END_TIME - 25)) { - entity.asPlayer().getPacketDispatch().sendMessage("Your resistance to dragonfire is about to run out."); - } else if (currentTick == (END_TIME - 1)) { - entity.asPlayer().getPacketDispatch().sendMessage("Your resistance to dragonfire has run out."); - } - } - return ++currentTick >= END_TIME; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/game/system/communication/CommunicationInfo.java b/Server/src/main/core/game/system/communication/CommunicationInfo.java index 895d45865..8135e7315 100644 --- a/Server/src/main/core/game/system/communication/CommunicationInfo.java +++ b/Server/src/main/core/game/system/communication/CommunicationInfo.java @@ -1,12 +1,10 @@ package core.game.system.communication; -import core.cache.misc.buffer.ByteBufferUtils; import core.game.node.entity.player.Player; import core.tools.Log; import org.jetbrains.annotations.NotNull; import proto.management.PrivateMessage; import core.auth.UserAccountInfo; -import core.tools.SystemLogger; import core.game.system.mysql.SQLTable; import core.game.system.task.Pulse; import core.game.world.GameWorld; @@ -19,7 +17,6 @@ import core.net.packet.out.ContactPackets; import core.tools.StringUtils; import core.worker.ManagementEvents; -import java.nio.ByteBuffer; import java.util.*; import java.util.Map.Entry; @@ -215,27 +212,6 @@ public final class CommunicationInfo { } } - /** - * Roar temp - * @param buffer - */ - public void parsePrevious(ByteBuffer buffer) { - int size = buffer.get() & 0xFF; - for (int i = 0; i < size; i++) { - String name = ByteBufferUtils.getString(buffer); - Contact contact = new Contact(name); - contact.setRank(ClanRank.FRIEND); - contacts.put(name, contact); - } - size = buffer.get() & 0xFF; - for (int i = 0; i < size; i++) { - blocked.add(ByteBufferUtils.getString(buffer)); - } - if (buffer.get() == 1) { - ByteBufferUtils.getString(buffer); - } - } - /** * Sends a message to the target. * @param player The player sending the message. diff --git a/Server/src/main/core/game/system/config/GroundSpawnLoader.kt b/Server/src/main/core/game/system/config/GroundSpawnLoader.kt index baf00ce02..cbf5dabc9 100644 --- a/Server/src/main/core/game/system/config/GroundSpawnLoader.kt +++ b/Server/src/main/core/game/system/config/GroundSpawnLoader.kt @@ -10,12 +10,10 @@ import org.json.simple.JSONObject import org.json.simple.parser.JSONParser import core.ServerConstants import core.api.log -import core.tools.SystemLogger import core.game.world.GameWorld import core.game.world.repository.Repository import core.tools.Log import java.io.* -import java.nio.ByteBuffer class GroundSpawnLoader { val parser = JSONParser() @@ -65,17 +63,6 @@ class GroundSpawnLoader { return "GroundSpawn [name=" + getName() + ", respawnRate=" + respawnRate + ", loc=" + getLocation() + "]" } - /** - * Method used to save this ground item to a byte buffer. - * @param buffer the buffer. - */ - fun save(buffer: ByteBuffer) { - buffer.putInt(respawnRate) - buffer.putShort(id.toShort()) - buffer.putInt(amount) - buffer.putShort((getLocation().x and 0xFFFF).toShort()).putShort((getLocation().y and 0xFFFF).toShort()).put(getLocation().z.toByte()) - } - /** * Method used to initialize this spawn. */ From dd35e479c14de167805f1ee8e704c98fc298b937 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Feb 2025 21:32:27 -0700 Subject: [PATCH 196/306] Cracking safes the the Rogue's Den now repeats The repetition will stop if you move away, get low health, or run out of inventory space. --- .../handlers/scenery/ThievingGuidePlugin.java | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java b/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java index 71efac4a5..4d306fc5e 100644 --- a/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java +++ b/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java @@ -81,24 +81,33 @@ public class ThievingGuidePlugin extends OptionHandler { player.getDialogueInterpreter().sendDialogues(2266, null, "And where do you think you're going? A little too eager", "I think. Come and talk to me before you go wandering", "around in there."); break; case "crack": - if (player.getSkills().getLevel(Skills.THIEVING) < 50) { - player.getPacketDispatch().sendMessage("You need to be level " + level + " thief to crack this safe."); - return true; - } - if (player.getInventory().freeSlots() == 0) { - player.getPacketDispatch().sendMessage("Not enough inventory space."); - return true; - } - final boolean success = success(player, Skills.THIEVING); - player.lock(4); - player.getPacketDispatch().sendMessage("You start cracking the safe."); - player.animate(animations[success ? 1 : 0]); + GameWorld.getPulser().submit(new Pulse(3, player) { @Override public boolean pulse() { + if (player.getSkills().getLevel(Skills.THIEVING) < 50) { + player.getPacketDispatch().sendMessage("You need to be level " + level + " thief to crack this safe."); + return true; + } + if (player.getInventory().freeSlots() == 0) { + player.getPacketDispatch().sendMessage("Not enough inventory space."); + return true; + } + if (player.getSkills().getLifepoints() <= 6) { + player.getPacketDispatch().sendMessage("You're too injured to be dealing with traps right now."); + return true; + } + if (player.getLocation().getDistance(node.getLocation()) >= 1) { + return true; + } + + final boolean success = success(player, Skills.THIEVING); + //player.lock(4); + player.getPacketDispatch().sendMessage("You start cracking the safe."); + player.animate(animations[success ? 1 : 0]); if (success) { handleSuccess(player, (Scenery) node); - return true; + return false; } final boolean trapped = RandomFunction.random(3) == 1; if (trapped) { @@ -109,11 +118,12 @@ public class ThievingGuidePlugin extends OptionHandler { @Override public boolean pulse() { player.animate(new Animation(-1, Priority.HIGH)); - return true; + return false; } }); } - return true; + + return false; } }); break; From 7b5ac708dc515f9fd39967c798555d203efaff47 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 7 Feb 2025 16:40:10 -0700 Subject: [PATCH 197/306] Implemented shared banks aka clan banks Players can talk to a banker to enable clan banks. When enabled, any banking function will use the primary bank of the owner of the clan chat the player is in. This only works while the bank owner is online; if they are offline the player will fallback to their own bank. --- .../content/global/dialogue/BankerDialogue.kt | 60 +++++++++++++++---- .../game/container/impl/BankContainer.java | 20 +++++++ .../core/game/node/entity/player/Player.java | 11 +++- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/Server/src/main/content/global/dialogue/BankerDialogue.kt b/Server/src/main/content/global/dialogue/BankerDialogue.kt index e913ce4f0..7b857da7d 100644 --- a/Server/src/main/content/global/dialogue/BankerDialogue.kt +++ b/Server/src/main/content/global/dialogue/BankerDialogue.kt @@ -45,18 +45,7 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin 2 -> showTopics( Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to access my bank account, please.", 10), - IfTopic( - core.game.dialogue.FacialExpression.FRIENDLY, - "I'd like to switch to my ${getBankAccountName(player, true)} bank account.", - 13, - hasActivatedSecondaryBankAccount(player) - ), - IfTopic( - core.game.dialogue.FacialExpression.FRIENDLY, - "I'd like to open a secondary bank account.", - 20, - !hasActivatedSecondaryBankAccount(player) - ), + Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to switch my default bank account.", 7), Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to check my PIN settings.", 11), Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to collect items.", 12), Topic(core.game.dialogue.FacialExpression.ASKING, "What is this place?", 3), @@ -78,6 +67,53 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin "Leave your valuables with us if you want to keep them safe." ).also { stage = END_DIALOGUE } + 7 -> showTopics( + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to turn on the Clan bank, please.", + 8, + !(player.getAttribute("clanbank:enabled",false)) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to turn off the Clan bank, please.", + 9, + player.getAttribute("clanbank:enabled",false) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to switch to my ${getBankAccountName(player, true)} bank account.", + 13, + hasActivatedSecondaryBankAccount(player) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to open a secondary bank account.", + 20, + !hasActivatedSecondaryBankAccount(player) + ), + ) + + 8 -> { + player.setAttribute("/save:clanbank:enabled", true) + + npcl( + core.game.dialogue.FacialExpression.FRIENDLY, + "The Clan bank has been enabled. " + + "If the Clan owner is online, you will access their primary bank account instead of your own." + ).also { stage = 2 } + } + + 9 -> { + player.removeAttribute("clanbank:enabled") + + npcl( + core.game.dialogue.FacialExpression.FRIENDLY, + "The Clan bank has been disabled. " + + "You will now always open your personal bank account." + ).also { stage = 2 } + } + 10 -> { openBankAccount(player) end() diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index f8f994d4d..42421e0eb 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -43,6 +43,11 @@ public final class BankContainer extends Container { */ private Player player; + /** + * Snowscape. The player reference. + */ + private Player owner; + /** * The bank listener. */ @@ -76,6 +81,7 @@ public final class BankContainer extends Container { super(SIZE, ContainerType.ALWAYS_STACK, SortType.HASH); super.register(listener = new BankListener(player)); this.player = player; + this.owner = player; } /** @@ -110,6 +116,18 @@ public final class BankContainer extends Container { ); } + /** + * Snowscape custom. Sets the current player. Used for clan banks. + * @param newplayer The new player assigned to the bank. + */ + public void setPlayer(Player newPlayer) { + // Only modify if the bank is not open, otherwise the player who is accessing it will suddenly be unable to deposit/withdraw + if (!isOpen()) { + this.player = newPlayer; + this.listener.player = newPlayer; + } + } + /** * Open the bank. */ @@ -195,6 +213,8 @@ public final class BankContainer extends Container { player.getInterfaceManager().closeSingleTab(); player.removeAttribute("search"); player.getPacketDispatch().sendRunScript(571, ""); + //Snowscape. Set the player back to the owner of the account. + setPlayer(this.owner); } /** diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index a23d472c7..8a09b46ac 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -1048,11 +1048,20 @@ public class Player extends Entity { return equipment; } - /** + /** Snowscape modifications: Added check for clan bank * Gets the current active bank. * @return Current active bank. */ public BankContainer getBank() { + if (getAttribute("clanbank:enabled",false)) { + Player target = Repository.getPlayerByName(this.getCommunication().getCurrentClan()); + if (target != null) { + target.getBankPrimary().setPlayer(this); + return target.getBankPrimary(); + } + } + //The primary bank.player is changed back to the owner when a player closes it, but if something else, like dialogue, runs a getbank() function then it's never changed back. So this manually changes it when checking our own bank. + bank.setPlayer(this); return useSecondaryBank ? bankSecondary : bank; } From d91f77c29482826cd7586b52e1f7f3da42672ebf Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 9 Feb 2025 02:37:14 +0000 Subject: [PATCH 198/306] Refactored how quests are referred to internally Fixed numerous requirement checks for Rag and Bone Man II, The Lost Tribe, The Tourist Trap, Waterfall Quest and The Fremennik Trials --- Server/data/configs/door_configs.json | 6 +- Server/src/main/content/data/GodBook.java | 2 +- Server/src/main/content/data/Quests.kt | 158 +++++++++ .../activity/shootingstar/ShootingStar.kt | 2 +- .../shootingstar/ShootingStarPlugin.kt | 24 +- .../content/global/bots/CannonballSmelter.kt | 5 +- .../handlers/iface/ExperienceInterface.kt | 7 +- .../handlers/iface/FairyRingInterface.kt | 10 +- .../handlers/iface/PrayerTabInterface.java | 3 +- .../global/handlers/iface/QuestTabUtils.kt | 317 +++++++++--------- .../global/handlers/item/EctophialListener.kt | 3 +- .../item/ItemQuestRequirementListener.kt | 55 +-- .../handlers/item/SilverSicklePlugin.java | 3 +- .../global/handlers/item/TeleTabsListener.kt | 3 +- .../handlers/item/TeleportCrystalPlugin.java | 3 +- .../handlers/item/withnpc/GCItemOnCat.kt | 12 +- .../item/withnpc/GertrudeCatUsePlugin.java | 3 +- .../handlers/item/withnpc/RopeOnLadyKeli.kt | 9 +- .../item/withobject/AmmoMouldOnFurnace.kt | 6 +- .../item/withobject/SmithingPlugin.java | 3 +- .../content/global/handlers/npc/RatNPC.java | 3 +- .../global/handlers/npc/SheepBehavior.kt | 3 +- .../agility/shortcuts/BarSqueezeShortcut.java | 3 +- .../agility/shortcuts/TunnelShortcut.java | 3 +- .../global/skill/construction/CrestType.java | 9 +- .../skill/cooking/StandardCookingPulse.java | 3 +- .../skill/farming/UseWithPatchHandler.kt | 3 +- .../skill/fletching/FletchingPulse.java | 3 +- .../fletching/items/darts/DartPulse.java | 3 +- .../skill/herblore/HerbCleanListener.kt | 3 +- .../global/skill/herblore/HerbTarPulse.java | 3 +- .../global/skill/herblore/HerblorePulse.java | 3 +- .../global/skill/magic/MagicAltarListener.kt | 3 +- .../skill/magic/modern/ModernListeners.kt | 9 +- .../skill/prayer/PrayerAltarListener.kt | 7 +- .../global/skill/runecrafting/Altar.java | 9 +- .../runecrafting/MysteriousRuinListener.kt | 11 +- .../skill/runecrafting/RuneCraftPulse.java | 7 +- .../runecrafting/RunecraftingPlugin.java | 5 +- .../abyss/ZamorakMageDialogue.java | 3 +- .../skill/skillcapeperks/SkillcapePerks.kt | 11 +- .../skill/slayer/SlayerMasterDialogue.java | 3 +- .../global/skill/slayer/SlayerPlugin.java | 3 +- .../skill/slayer/SlayerRewardPlugin.java | 3 +- .../content/global/skill/slayer/Tasks.java | 49 +-- .../skill/smithing/FurnaceOptionPlugin.java | 3 +- .../global/skill/smithing/SmithingPulse.java | 5 +- .../smithing/smelting/SmeltingPulse.java | 4 +- .../summoning/SummoningTrainingRoom.java | 5 +- .../familiar/SummonFamiliarPlugin.java | 3 +- .../skill/thieving/StallThiefPulse.java | 7 +- .../travel/glider/CaptainDalburDialogue.java | 4 +- .../global/travel/glider/GliderPlugin.java | 4 +- .../travel/ship/SeamanDialoguePlugin.java | 3 +- .../global/travel/ship/ShipCharter.java | 13 +- .../travel/trees/GnomeSpiritTreeListener.kt | 4 +- .../minigame/allfiredup/AFUBeaconHandler.kt | 11 +- .../allfiredup/AFURepairClimbHandler.kt | 3 +- .../minigame/pyramidplunder/PharaohSceptre.kt | 3 +- .../minigame/sorceress/GardenObjectsPlugin.kt | 3 +- .../SorceressApprenticeDialogue.java | 3 +- .../burthorpe/dialogue/BernaldDialogue.kt | 4 +- .../burthorpe/dialogue/BreocaDialogue.kt | 3 +- .../burthorpe/dialogue/CeolburgDialogue.kt | 3 +- .../burthorpe/dialogue/DenulthDialogue.kt | 11 +- .../burthorpe/dialogue/DunstanDialogue.kt | 11 +- .../burthorpe/dialogue/EohricDialogue.kt | 4 +- .../burthorpe/dialogue/HaroldDialogue.kt | 6 +- .../burthorpe/dialogue/HildDialogue.kt | 3 +- .../burthorpe/dialogue/HygdDialogue.kt | 3 +- .../burthorpe/dialogue/OcgaDialogue.kt | 3 +- .../burthorpe/dialogue/PendaDialogue.kt | 3 +- .../burthorpe/dialogue/UnferthDialogue.kt | 5 +- .../burthorpe/handlers/HeroGuildPlugin.java | 9 +- .../quest/deathplateau/DeathPlateau.kt | 9 +- .../DeathPlateauDoorDialogueFile.kt | 5 +- .../DeathPlateauInteractionListener.kt | 7 +- .../quest/deathplateau/DenulthDialogueFile.kt | 11 +- .../quest/deathplateau/DunstanDialogueFile.kt | 9 +- .../quest/deathplateau/EohricDialogueFile.kt | 9 +- .../quest/deathplateau/HaroldDialogueFile.kt | 15 +- .../quest/deathplateau/IOUNoteDialogueFile.kt | 5 +- .../quest/deathplateau/SabaDialogueFile.kt | 5 +- .../quest/deathplateau/SecretWayLocation.kt | 5 +- .../quest/deathplateau/TenzingDialogueFile.kt | 7 +- .../quest/heroesquest/AchiettiesDialogue.kt | 19 +- .../heroesquest/AlfonseTheWaiterDialogue.kt | 11 +- .../heroesquest/CharlieTheCookDialogue.kt | 14 +- .../quest/heroesquest/GarvDialogue.kt | 10 +- .../quest/heroesquest/GerrantDialogue.kt | 3 +- .../quest/heroesquest/GripBehavior.kt | 5 +- .../quest/heroesquest/GruborDialogue.kt | 7 +- .../quest/heroesquest/HeroesQuest.kt | 32 +- .../quest/heroesquest/HeroesQuestListener.kt | 13 +- .../quest/heroesquest/KatrineDialogueFile.kt | 17 +- .../quest/heroesquest/StravenDialogueFile.kt | 17 +- .../quest/heroesquest/TrobertDialogue.kt | 13 +- .../quest/trollstronghold/BerryNpc.kt | 4 +- .../quest/trollstronghold/DadDialogue.kt | 5 +- .../quest/trollstronghold/DadDialogueFile.kt | 7 +- .../burthorpe/quest/trollstronghold/DadNpc.kt | 12 +- .../trollstronghold/DenulthDialogueFile.kt | 3 +- .../trollstronghold/DunstanDialogueFile.kt | 5 +- .../quest/trollstronghold/TrollGeneralsNpc.kt | 7 +- .../quest/trollstronghold/TrollStronghold.kt | 24 +- .../TrollStrongholdListener.kt | 35 +- .../quest/trollstronghold/TwigNpc.kt | 6 +- .../asgarnia/dialogue/OracleDialogue.java | 3 +- .../asgarnia/dialogue/ThuroDialogue.java | 3 +- .../falador/dialogue/DoricDialogue.kt | 3 +- .../dialogue/FaladorSquireDialogue.java | 3 +- .../dialogue/SirTiffyCashienDialogue.kt | 6 +- .../falador/quest/TheKnightsSword.java | 3 +- .../blackknightsfortress/BKCabbagePlugin.java | 3 +- .../BKListenDialogue.java | 5 +- .../BlackKnightsFortress.java | 3 +- .../SirAmikVarzeDialogue.java | 3 +- .../doricsquest/DoricDoricsQuestDialogue.kt | 7 +- .../falador/quest/doricsquest/DoricsQuest.kt | 3 +- .../recruitmentdrive/RecruitmentDrive.kt | 10 +- .../RecruitmentDriveListeners.kt | 8 +- .../SirAmikVarzeDialogueFile.kt | 13 +- .../SirTiffyCashienDialogueFile.kt | 13 +- .../goblindiplomacy/GDiplomacyCutscene.java | 11 +- .../goblindiplomacy/GoblinDiplomacy.java | 9 +- .../goblindiplomacy/GrubfootDialogue.java | 3 +- .../portsarim/dialogue/AhabDialogue.java | 3 +- .../portsarim/dialogue/KlarenseDialogue.java | 3 +- .../dialogue/RedbeardFrankDialogue.java | 3 +- .../portsarim/handlers/PortSarimPlugin.java | 3 +- .../portsarim/handlers/PortsObjectPlugin.java | 3 +- .../piratestreasure/PiratesTreasure.java | 3 +- .../PiratesTreasurePlugin.java | 3 +- .../rimmington/dialogue/HettyDialogue.kt | 4 +- .../witchpotion/HettyWitchsPotionDialogue.kt | 7 +- .../quest/witchpotion/WitchsPotion.kt | 6 +- .../witchpotion/WitchsPotionListeners.kt | 5 +- .../taverley/dialogue/KaqemeexDialogue.java | 13 +- .../taverley/dialogue/PikkupstixDialogue.java | 3 +- .../taverley/dialogue/SanfewDialogue.java | 9 +- .../asgarnia/taverley/quest/DruidicRitual.kt | 10 +- .../asgarnia/taverley/quest/WolfWhistle.java | 3 +- .../quest/witchshouse/BoyDialoguePlugin.java | 5 +- .../quest/witchshouse/WitchsHouse.java | 3 +- .../quest/witchshouse/WitchsHousePlugin.java | 3 +- .../trollheim/dialogue/SabaDialogue.kt | 4 +- .../trollheim/dialogue/TenzingDialogue.kt | 4 +- .../handlers/gwd/GodwarsEntranceHandler.java | 3 +- .../alkharid/dialogue/AliMorrisaneDialogue.kt | 5 +- .../dialogue/BorderGuardDialogue.java | 3 +- .../alkharid/dialogue/GemTraderDialogue.kt | 19 +- .../alkharid/dialogue/HassanDialogue.java | 3 +- .../princealirescue/LadyKeliDialogue.java | 3 +- .../princealirescue/PrinceAliRescue.java | 3 +- .../PrinceAliRescuePlugin.java | 3 +- .../desert/dialogue/RugMerchantDialogue.java | 7 +- .../desert/handlers/TollGateOptionPlugin.java | 3 +- .../deserttreasure/ArchaeologistDialogue.kt | 19 +- .../shadowofthestorm/DarklightListener.kt | 3 +- .../desert/quest/thegolem/TheGolemDialogue.kt | 33 +- .../desert/quest/thegolem/TheGolemQuest.kt | 17 +- .../quest/thetouristrap/AlShabimDialogue.java | 3 +- .../quest/thetouristrap/AnaDialogue.java | 7 +- .../thetouristrap/BedabinNomadDialogue.java | 3 +- .../thetouristrap/CaptainSiadDialogue.java | 3 +- .../thetouristrap/DesertGuardDialogue.java | 3 +- .../quest/thetouristrap/IrenaDialogue.java | 3 +- .../thetouristrap/MaleSlaveDialogue.java | 3 +- .../MercenaryCaptainDialogue.java | 5 +- .../thetouristrap/MercenaryDialogue.java | 3 +- .../thetouristrap/MinecartDriverDialogue.java | 3 +- .../quest/thetouristrap/MiningCampZone.java | 3 +- .../quest/thetouristrap/TouristTrap.java | 9 +- .../thetouristrap/TouristTrapPlugin.java | 19 +- .../sophanem/handlers/SophanemPlugin.java | 19 +- .../dialogue/LokarSearunnerDialogue.java | 3 +- .../diary/FremennikAchievementDiary.kt | 3 +- .../jatizso/dialogue/MordGunnarsDialogue.kt | 3 +- .../dialogue/BjornAndEldgrimDialogues.kt | 5 +- .../rellekka/dialogue/BlaninDialogue.kt | 3 +- .../dialogue/CouncilWorkerDialogue.kt | 3 +- .../rellekka/dialogue/DronDialogue.kt | 3 +- .../dialogue/FishmongerRellekkaDialogue.kt | 3 +- .../rellekka/dialogue/FurTraderDialogue.kt | 3 +- .../dialogue/IngridHradsonDialogue.kt | 7 +- .../rellekka/dialogue/JarvaldDialogue.kt | 7 +- .../dialogue/LonghallBouncerDialogue.kt | 3 +- .../dialogue/MariaGunnarsDialogue.java | 3 +- .../rellekka/dialogue/ReesoDialogue.kt | 3 +- .../rellekka/dialogue/TalkToChiefDialogue.kt | 5 +- .../rellekka/dialogue/VolfOlasfsonDialogue.kt | 7 +- .../rellekka/handlers/RellekkaListeners.kt | 5 +- .../thefremenniktrials/AskeladdenDialogue.kt | 5 +- .../ChieftanBrundtDialogue.kt | 11 +- .../CouncilWorkerFTDialogue.kt | 3 +- .../thefremenniktrials/FishermanDialogue.kt | 5 +- .../thefremenniktrials/FremennikTrials.kt | 8 +- .../quest/thefremenniktrials/LalliDialogue.kt | 7 +- .../quest/thefremenniktrials/ManniDialogue.kt | 5 +- .../quest/thefremenniktrials/OlafTheBard.kt | 5 +- .../thefremenniktrials/PeerTheSeerDialogue.kt | 9 +- .../thefremenniktrials/PoisonSalesman.kt | 9 +- .../thefremenniktrials/SigliTheHuntsman.kt | 6 +- .../thefremenniktrials/SigmundDialogue.kt | 5 +- .../thefremenniktrials/SkulgrimenDialogue.kt | 3 +- .../thefremenniktrials/SwensenTheNavigator.kt | 6 +- .../TFTInteractionListeners.kt | 7 +- .../quest/thefremenniktrials/ThoraDialogue.kt | 3 +- .../thefremenniktrials/ThorvaldDialogue.kt | 9 +- .../quest/thefremenniktrials/YrsaDialogue.kt | 3 +- .../plaguecity/dialogue/KilronDialogue.kt | 3 +- .../plaguecity/quest/elena/AlrenaDialogue.kt | 7 +- .../plaguecity/quest/elena/BravekDialogue.kt | 15 +- .../plaguecity/quest/elena/ClerkDialogue.kt | 5 +- .../plaguecity/quest/elena/EdmondDialogue.kt | 13 +- .../plaguecity/quest/elena/ElenaDialogue.kt | 5 +- .../quest/elena/HeadMournerDialogue.kt | 5 +- .../plaguecity/quest/elena/JethickDialogue.kt | 7 +- .../quest/elena/MarthaRehnisonDialogue.kt | 5 +- .../quest/elena/MilliRehnisonDialogue.kt | 7 +- .../plaguecity/quest/elena/MournerDialogue.kt | 5 +- .../plaguecity/quest/elena/PlagueCity.kt | 5 +- .../quest/elena/PlagueCityListeners.kt | 39 +-- .../quest/elena/TedRehnisonDialogue.kt | 7 +- .../quest/elena/UndergroundCutscene.kt | 3 +- .../ardougne/quest/arena/FightArena.kt | 5 +- .../quest/arena/FightArenaListeners.kt | 13 +- .../arena/dialogue/ALazyGuardDialogue.kt | 8 +- .../arena/dialogue/GeneralKhazardDialogue.kt | 6 +- .../quest/arena/dialogue/GuardsDialogue.kt | 9 +- .../quest/arena/dialogue/HengradDialogue.kt | 6 +- .../arena/dialogue/JeremyServilADialogue.kt | 6 +- .../arena/dialogue/JeremyServilBDialogue.kt | 8 +- .../arena/dialogue/JustinServilDialogue.kt | 4 +- .../arena/dialogue/KhazardBarmanDialogue.kt | 6 +- .../arena/dialogue/LadyServilDialogue.kt | 14 +- .../quest/arena/dialogue/LocalDialogue.kt | 7 +- .../ardougne/quest/arena/npc/BouncerNPC.kt | 7 +- .../ardougne/quest/arena/npc/GeneralNPC.kt | 7 +- .../ardougne/quest/arena/npc/OgreNPC.kt | 7 +- .../ardougne/quest/arena/npc/ScorpionNPC.kt | 7 +- .../clocktower/BrotherKojoDialogueFile.kt | 7 +- .../ardougne/quest/clocktower/ClockTower.kt | 4 +- .../quest/clocktower/ClockTowerListeners.kt | 33 +- .../quest/monksfriend/BrotherCedricNPC.kt | 12 +- .../quest/monksfriend/BrotherOmadNPC.kt | 17 +- .../quest/monksfriend/MonasteryMonkNPC.kt | 3 +- .../ardougne/quest/monksfriend/MonksFriend.kt | 3 +- .../quest/sheepherder/HalgriveDialogue.java | 7 +- .../quest/sheepherder/OrbonDialogue.java | 3 +- .../quest/sheepherder/SheepHerder.java | 3 +- .../catherby/dialogue/ArheinDialogue.kt | 3 +- .../kandarin/dialogue/ThormacDialogue.kt | 5 +- .../feldip/ooglog/dialogue/BalneaDialogue.kt | 4 +- .../feldip/quest/chompybird/BloatedToadNPC.kt | 3 +- .../feldip/quest/chompybird/ChompyBird.kt | 3 +- .../quest/chompybird/ChompyBirdDialogues.kt | 7 +- .../feldip/quest/chompybird/RantzNPC.kt | 3 +- .../kandarin/guilds/WizardGuildPlugin.java | 5 +- .../pisc/handlers/SeaweedNetHandler.kt | 3 +- .../dwarfcannon/CaptainLawgofDialogue.java | 3 +- .../quest/dwarfcannon/DwarfCannon.java | 11 +- .../quest/dwarfcannon/DwarfCannonPlugin.java | 10 +- .../quest/dwarfcannon/LollkDialogue.java | 3 +- .../quest/dwarfcannon/NulodionDialogue.java | 3 +- .../dmc/DwarfMultiCannonPlugin.java | 3 +- .../quest/fishingcontest/BonzoDialogue.java | 3 +- .../quest/fishingcontest/DwarfDialogue.java | 11 +- .../quest/fishingcontest/FishingContest.java | 3 +- .../fishingcontest/GarlicPipeInteraction.java | 3 +- .../quest/fishingcontest/GateInteraction.java | 5 +- .../fishingcontest/StairInteraction.java | 3 +- .../quest/fishingcontest/VineInteraction.java | 3 +- .../kandarin/quest/grandtree/AnitaDialogue.kt | 3 +- .../kandarin/quest/grandtree/BlackDemonNPC.kt | 6 +- .../quest/grandtree/CaptainErrdoDialogue.kt | 3 +- .../quest/grandtree/CharlieDialogue.kt | 10 +- .../kandarin/quest/grandtree/ForemanNPC.kt | 3 +- .../quest/grandtree/GloughDialogue.kt | 8 +- .../quest/grandtree/GrandTreeListeners.kt | 19 +- .../quest/grandtree/HazelmereDialogue.kt | 6 +- .../quest/grandtree/KingNarnodeDialogue.kt | 18 +- .../quest/grandtree/ShipyardWorkerDialogue.kt | 3 +- .../kandarin/quest/grandtree/TheGrandTree.kt | 7 +- .../quest/scorpioncatcher/SCPeksaDialogue.kt | 3 +- .../quest/scorpioncatcher/SCSeerDialogue.kt | 5 +- .../scorpioncatcher/SCThormacDialogue.kt | 7 +- .../quest/scorpioncatcher/SCWallListener.kt | 3 +- .../quest/scorpioncatcher/ScorpionCatcher.kt | 3 +- .../templeofikov/FireWarriorOfLesarkusNPC.kt | 6 +- .../templeofikov/GuardianOfArmadylBehavior.kt | 3 +- .../templeofikov/GuardianOfArmadylDialogue.kt | 5 +- .../quest/templeofikov/LucienDialogue.kt | 11 +- .../templeofikov/LucienEndingDialogue.kt | 9 +- .../quest/templeofikov/LucienEndingNPC.kt | 5 +- .../quest/templeofikov/TempleOfIkov.kt | 6 +- .../templeofikov/TempleOfIkovListeners.kt | 28 +- .../quest/templeofikov/WineldaDialogue.kt | 7 +- .../kandarin/quest/tree/BallistaDialogue.kt | 5 +- .../quest/tree/CommanderMontaiDialogue.kt | 9 +- .../kandarin/quest/tree/ElkoyDialogue.kt | 4 +- .../quest/tree/KhazardWarlordDialogue.kt | 3 +- .../kandarin/quest/tree/KhazardWarlordNPC.kt | 3 +- .../kandarin/quest/tree/KingBolrenDialogue.kt | 14 +- .../kandarin/quest/tree/RemsaiDialogue.kt | 3 +- .../quest/tree/TrackerGnomeOneDialogue.kt | 3 +- .../quest/tree/TrackerGnomeThreeDialogue.kt | 3 +- .../quest/tree/TrackerGnomeTwoDialogue.kt | 3 +- .../kandarin/quest/tree/TreeGnomeVillage.kt | 4 +- .../quest/tree/TreeGnomeVillageListeners.kt | 3 +- .../quest/waterfall/AlmeraDialogue.java | 7 +- .../kandarin/quest/waterfall/BaxtorianBook.kt | 5 +- .../quest/waterfall/HudonDialogue.java | 7 +- .../kandarin/quest/waterfall/WaterFall.java | 9 +- .../quest/waterfall/WaterfallPlugin.java | 7 +- .../whileguthixsleeps/WhileGuthixSleeps.kt | 61 ++-- .../kandarin/seers/dialogue/SeerDialogue.kt | 6 +- .../elementalworkshop/BatteredBookHandler.kt | 4 +- .../quest/elementalworkshop/EWListeners.kt | 13 +- .../seers/quest/elementalworkshop/EWUtils.kt | 4 +- .../ElementalWorkshopQuest.kt | 3 +- .../quest/merlinsquest/ArheinMCDialogue.kt | 3 +- .../quest/merlinsquest/BeggarDialogue.java | 3 +- .../merlinsquest/CandleMakerDialogue.java | 5 +- .../merlinsquest/KingArthurDialogue.java | 5 +- .../quest/merlinsquest/MerlinCrystal.java | 4 +- .../MerlinCrystalOptionPlugin.java | 3 +- .../merlinsquest/MerlinCrystalPlugin.java | 16 +- .../quest/merlinsquest/MerlinListeners.kt | 3 +- .../quest/merlinsquest/SirGawainDialogue.java | 3 +- .../quest/merlinsquest/SirKayDialogue.java | 3 +- .../merlinsquest/SirLancelotDialogue.java | 3 +- .../seers/quest/merlinsquest/SirLucan.java | 3 +- .../quest/merlinsquest/SirMordredNPC.java | 3 +- .../quest/merlinsquest/SirPalomedes.java | 3 +- .../quest/merlinsquest/TheLadyOfTheLake.kt | 3 +- .../quest/merlinsquest/ThrantaxDialogue.java | 3 +- .../seers/quest/merlinsquest/ThrantaxNPC.java | 3 +- .../quest/seaslug/BaileyDialogueFile.kt | 19 +- .../quest/seaslug/CarolineDialogueFile.kt | 15 +- .../quest/seaslug/HolgartDialogueFile.kt | 29 +- .../seaslug/HolgartIslandDialogueFile.kt | 13 +- .../seaslug/HolgartPlatformDialogueFile.kt | 8 +- .../quest/seaslug/KennithDialogueFile.kt | 34 +- .../quest/seaslug/KentDialogueFile.kt | 16 +- .../witchhaven/quest/seaslug/SeaSlug.kt | 11 +- .../quest/seaslug/SeaSlugListeners.kt | 15 +- .../dialogue/CustomsOfficerDialogue.java | 3 +- .../handlers/CustomsOfficerPlugin.java | 3 +- .../quest/junglepotion/JunglePotion.java | 8 +- .../junglepotion/JunglePotionPlugin.java | 3 +- .../quest/junglepotion/TrufitusDialogue.java | 3 +- .../quest/tribaltotem/CrompertyDialogue.kt | 9 +- .../quest/tribaltotem/HoracioDialogue.kt | 3 +- .../quest/tribaltotem/KangaiMauDialogue.kt | 15 +- .../quest/tribaltotem/RPDTEmployeeDialogue.kt | 5 +- .../quest/tribaltotem/TribalTotemListeners.kt | 9 +- .../quest/tribaltotem/TribalTotemQuest.kt | 6 +- .../shilo/handlers/BrokenCartBypass.java | 3 +- .../karamja/shilo/handlers/ShiloCart.kt | 7 +- .../misc/entrana/dialogue/CaveMonk.java | 3 +- .../misc/keldagrim/dialogue/KjutDialogue.kt | 3 +- .../handlers/KeldagrimCartMethods.kt | 5 +- .../dialogue/FishmongerMiscDialogue.kt | 3 +- .../dialogue/FlowerGirlDialogue.kt | 4 +- .../tutisland/handlers/RatTutorialNPC.java | 3 +- .../zanaris/dialogue/FairyQueenDialogue.kt | 3 +- .../handlers/EvilChickenLairListener.kt | 3 +- .../misc/zanaris/handlers/FairyRingPlugin.kt | 3 +- .../barbvillage/dialogue/PeksaDialogue.kt | 5 +- .../digsite/dialogue/ExaminerDialogue.kt | 35 +- .../digsite/dialogue/ResearcherDialogue.kt | 4 +- .../ArchaeologicalExpertListener.kt | 11 +- .../thedigsite/DigsiteWorkmanDialogue.kt | 5 +- .../quest/thedigsite/StudentsDialogue.kt | 37 +- .../digsite/quest/thedigsite/TheDigSite.kt | 7 +- .../quest/thedigsite/TheDigSiteListeners.kt | 39 +-- .../dorgeshuun/dialogue/MistagDialogue.kt | 3 +- .../thelosttribe/DukeHoracioTLTDialogue.kt | 11 +- .../thelosttribe/HistoryOfTheGoblinRace.kt | 5 +- .../quest/thelosttribe/LostTribe.kt | 7 +- .../quest/thelosttribe/LostTribeCutscene.kt | 3 +- .../thelosttribe/LostTribeOptionHandler.kt | 8 +- .../quest/thelosttribe/MistagLTDialogue.kt | 6 +- .../quest/thelosttribe/PickaxeOnRubble.kt | 3 +- .../quest/thelosttribe/PickpocketSigmund.kt | 3 +- .../quest/thelosttribe/SigmundChestHandler.kt | 5 +- .../draynor/dialogue/AggieDialogue.java | 3 +- .../draynor/dialogue/JoeGuardDialogue.java | 3 +- .../draynor/dialogue/LeelaDialogue.java | 3 +- .../draynor/dialogue/MissSchismDialogue.java | 5 +- .../draynor/dialogue/MorganDialogue.java | 5 +- .../draynor/dialogue/PrinceAliDialogue.java | 3 +- .../dialogue/ProfessorOddensteinPlugin.java | 5 +- .../draynor/dialogue/VeronicaDialogue.java | 5 +- .../draynor/quest/anma/AliceDialogue.java | 3 +- .../quest/anma/AliceHusbandDialogue.java | 3 +- .../draynor/quest/anma/AnimalMagnetism.java | 15 +- .../quest/anma/AnimalMagnetismPlugin.java | 13 +- .../draynor/quest/anma/AnmaCutscene.kt | 3 +- .../draynor/quest/anma/AvaDialogue.java | 3 +- .../draynor/quest/anma/AvasDevice.kt | 3 +- .../draynor/quest/anma/OldCronDialogue.java | 3 +- .../draynor/quest/anma/WitchDialogue.java | 3 +- .../draynor/quest/ernest/ErnestDialogue.java | 5 +- .../quest/ernest/ErnestTheChicken.java | 7 +- .../draynor/quest/vampire/VampireSlayer.java | 3 +- .../quest/vampire/VampireSlayerNPC.java | 3 +- .../quest/vampire/VampireSlayerPlugin.java | 3 +- .../lumbridge/dialogue/DukeHoracioDialogue.kt | 13 +- .../dialogue/FredTheFarmerDialogue.kt | 9 +- .../dialogue/LumbridgeGuideDialogue.kt | 5 +- .../lumbridge/dialogue/SigmundDialogue.java | 9 +- .../diary/LumbridgeAchivementDiary.kt | 3 +- .../handlers/LumbridgeBasementPlugin.java | 1 + .../quest/cooksassistant/CooksAssistant.kt | 5 +- .../cooksassistant/LumbridgeCookDialogue.kt | 17 +- .../quest/lostcity/DramenTreeListener.kt | 3 +- .../lumbridge/quest/lostcity/LostCity.kt | 3 +- .../quest/lostcity/LostCityListeners.kt | 14 +- .../quest/lostcity/ShamusDialogue.kt | 8 +- .../lumbridge/quest/lostcity/TreeSpiritNPC.kt | 7 +- .../quest/lostcity/WarriorDialogue.kt | 5 +- .../runemysteries/DukeHoracioRMDialogue.kt | 3 +- .../quest/runemysteries/RuneMysteries.java | 3 +- .../sheepshearer/SSFredTheFarmerDialogue.kt | 7 +- .../quest/sheepshearer/SheepShearer.kt | 3 +- .../quest/tearsofguthix/JunaDialogue.kt | 13 +- .../quest/tearsofguthix/TearsOfGuthix.kt | 7 +- .../tearsofguthix/TearsOfGuthixListeners.kt | 3 +- .../tearsofguthix/TearsOfGuthixMinigame.kt | 7 +- .../FatherAereckDialogue.java | 7 +- .../FatherUhrneyDialogue.java | 9 +- .../quest/therestlessghost/RestlessGhost.java | 11 +- .../RestlessGhostDialogue.java | 9 +- .../therestlessghost/RestlessGhostPlugin.java | 13 +- .../therestlessghost/RestlessGhostSkull.java | 3 +- .../quest/asoulsbane/ASoulsBane.java | 5 +- .../quest/asoulsbane/ASoulsBaneListeners.kt | 3 +- .../priestinperil/DoorPerilDialogue.java | 5 +- .../quest/priestinperil/DrezelDialogue.java | 7 +- .../priestinperil/DrezelMonumentDialogue.java | 7 +- .../priestinperil/KingRoaldPIPDialogue.kt | 5 +- .../quest/priestinperil/MonkOfZamorakNPC.java | 3 +- .../quest/priestinperil/PriestInPeril.java | 3 +- .../PriestInPerilOptionPlugin.java | 5 +- .../priestinperil/PriestInPerilUseListener.kt | 5 +- .../priestinperil/TempleGuardianNPC.java | 3 +- .../quest/ragandboneman/BatBehavior.kt | 3 +- .../quest/ragandboneman/BearBehavior.kt | 4 +- .../quest/ragandboneman/BigFrogBehavior.kt | 4 +- .../quest/ragandboneman/GiantBatBehavior.kt | 3 +- .../quest/ragandboneman/GiantRatBehavior.kt | 4 +- .../quest/ragandboneman/GoblinBehavior.kt | 5 +- .../quest/ragandboneman/MonkeyBehavior.kt | 4 +- .../ragandboneman/OddOldManDialogueFile.kt | 8 +- .../quest/ragandboneman/RagAndBoneMan.kt | 4 +- .../quest/ragandboneman/RamBehavior.kt | 4 +- .../quest/ragandboneman/UnicornBehavior.kt | 4 +- .../varrock/dialogue/ApothecaryDialogue.java | 11 +- .../varrock/dialogue/BaraekDialogue.java | 3 +- .../varrock/dialogue/DrHarlowDialogue.java | 11 +- .../dialogue/FatherLawrenceDialogue.java | 5 +- .../varrock/dialogue/GertrudeDialogue.java | 11 +- .../dialogue/GertrudesCatDialogue.java | 3 +- .../varrock/dialogue/KingRoaldDialogue.kt | 11 +- .../dialogue/MuseumGuardsDialoguePlugin.kt | 5 +- .../varrock/dialogue/ShilopDialogue.java | 5 +- .../varrock/dialogue/WiloughDialogue.java | 5 +- .../varrock/diary/VarrockAchivementDiary.kt | 3 +- .../handlers/LumberYardCratePlugin.java | 3 +- .../misthalin/varrock/handlers/ZaffPlugin.kt | 3 +- .../varrock/quest/allfiredup/AllFiredUp.kt | 5 +- .../quest/allfiredup/BlazeSharpeyeDialogue.kt | 11 +- .../quest/allfiredup/KingRoaldAFUDialogue.kt | 5 +- .../quest/allfiredup/SquireFyreDialogue.kt | 5 +- .../quest/demonslayer/DSCutsceneTrigger.kt | 3 +- .../quest/demonslayer/DSlayerDrainPlugin.java | 3 +- .../quest/demonslayer/DemonSlayer.java | 5 +- .../demonslayer/DemonSlayerCutscene.java | 5 +- .../quest/demonslayer/DemonSlayerPlugin.java | 6 +- .../quest/demonslayer/GypsyArisDialogue.java | 3 +- .../quest/demonslayer/SirPyrsinDialogue.java | 6 +- .../quest/demonslayer/TraibornDialogue.java | 3 +- .../demonslayer/WallyCutscenePlugin.java | 3 +- .../quest/dragonslayer/CabinBoyJenkins.java | 14 +- .../quest/dragonslayer/DSMagicDoorPlugin.java | 3 +- .../varrock/quest/dragonslayer/DSNedNPC.java | 3 +- .../quest/dragonslayer/DragonSlayer.kt | 5 +- .../dragonslayer/DragonSlayerCutscene.java | 5 +- .../dragonslayer/DragonSlayerPlugin.java | 15 +- .../varrock/quest/dragonslayer/ElvargNPC.java | 6 +- .../dragonslayer/GuildmasterDialogue.java | 3 +- .../quest/dragonslayer/NedDSDialogue.kt | 4 +- .../varrock/quest/dragonslayer/NedDialogue.kt | 5 +- .../quest/dragonslayer/OziachDialogue.java | 5 +- .../quest/dragonslayer/WormbrainDialogue.java | 3 +- .../quest/dragonslayer/WormbrainNPC.java | 5 +- .../quest/dragonslayer/ZombieRatNPC.java | 9 +- .../varrock/quest/familycrest/AvanDialogue.kt | 7 +- .../varrock/quest/familycrest/BootDialogue.kt | 5 +- .../quest/familycrest/CalebDialogue.kt | 7 +- .../quest/familycrest/ChronozonCaveZone.kt | 3 +- .../varrock/quest/familycrest/ChronozonNPC.kt | 5 +- .../quest/familycrest/DimintheisDialogue.kt | 11 +- .../varrock/quest/familycrest/FamilyCrest.kt | 4 +- .../JohnathonAntiPoisonInteraction.kt | 5 +- .../quest/familycrest/JohnathonDialogue.kt | 7 +- .../familycrest/WitchavenLeverInteraction.kt | 5 +- .../varrock/quest/gertrude/FluffNPC.java | 3 +- .../varrock/quest/gertrude/GertrudesCat.java | 3 +- .../quest/gertrude/LumberKittenNPC.java | 3 +- .../varrock/quest/romeo/JulietDialogue.java | 5 +- .../varrock/quest/romeo/JulietNPC.java | 3 +- .../varrock/quest/romeo/RJCutscenePlugin.java | 7 +- .../varrock/quest/romeo/RomeoJuliet.java | 5 +- .../varrock/quest/romeo/RomeoNPC.java | 2 +- .../shieldofarrav/CharlieTheTrampDialogue.kt | 11 +- .../shieldofarrav/CuratorHaigHalenDialogue.kt | 15 +- .../quest/shieldofarrav/JohnnyBeardNPC.java | 3 +- .../quest/shieldofarrav/KatrineDialogue.java | 5 +- .../shieldofarrav/KingRoaldArravDialogue.kt | 4 +- .../quest/shieldofarrav/ReldoDialogue.java | 9 +- .../shieldofarrav/ShieldArravPlugin.java | 3 +- .../quest/shieldofarrav/ShieldofArrav.java | 3 +- .../quest/shieldofarrav/ShieldofArravBook.kt | 10 +- .../quest/shieldofarrav/StravenDialogue.java | 5 +- .../shieldofarrav/WeaponsMasterDialogue.java | 3 +- .../whatliesbelow/AnnaJonesDialogue.java | 3 +- .../quest/whatliesbelow/OutlawNPC.java | 3 +- .../whatliesbelow/RatBurgissDialogue.java | 3 +- .../whatliesbelow/SurokMagisDialogue.java | 3 +- .../quest/whatliesbelow/WLBelowPlugin.java | 3 +- .../quest/whatliesbelow/WhatLiesBelow.java | 15 +- .../wiztower/dialogue/TraibornDialogue.java | 3 +- .../wiztower/handlers/WizardTowerPlugin.java | 16 +- .../misthalin/wiztower/quest/ImpCatcher.java | 3 +- .../canifis/dialogue/RoavarDialogue.kt | 5 +- .../morytania/handlers/MorytaniaArea.kt | 3 +- .../morytania/handlers/MorytaniaListeners.kt | 3 +- .../BookcaseDialogueFile.kt | 3 +- .../CreatureOfFenkenstrain.kt | 20 +- .../CreatureOfFenkenstrainListeners.kt | 33 +- .../DrFenkenstrainDialogue.kt | 35 +- .../GardenerGhostDialogue.kt | 21 +- .../LordRologarthDialogue.kt | 12 +- .../quest/naturespirit/NSDrezelDialogue.kt | 11 +- .../quest/naturespirit/NSListeners.kt | 14 +- .../quest/naturespirit/NSTarlockDialogue.kt | 6 +- .../naturespirit/NatureSpiritDialogue.kt | 9 +- .../quest/naturespirit/NatureSpiritQuest.kt | 11 +- .../dialogue/QuarterMasterDialogue.java | 3 +- .../quest/rovingelves/ElunedDialogue.java | 5 +- .../quest/rovingelves/IslwynDialogue.java | 7 +- .../rovingelves/MossGiantGuardianNPC.java | 3 +- .../quest/rovingelves/RovingElves.java | 3 +- .../rovingelves/RovingElvesObstacles.java | 3 +- .../quest/rovingelves/RovingElvesPlugin.java | 3 +- .../wilderness/handlers/ChaosTunnelZone.java | 3 +- .../CorporealBeastWarningInterface.kt | 3 +- .../wilderness/handlers/WildernessPlugin.java | 3 +- Server/src/main/core/api/ContentAPI.kt | 37 +- Server/src/main/core/game/bots/Script.java | 5 +- .../core/game/dialogue/DialogueBuilder.kt | 3 +- .../game/global/action/DoorActionHandler.java | 5 +- .../combat/graves/GravePurchaseInterface.kt | 2 +- .../node/entity/combat/graves/GraveType.kt | 9 +- .../player/info/login/LoginConfiguration.java | 7 +- .../player/info/login/SaveVersionHooks.kt | 3 +- .../node/entity/player/link/emote/Emotes.java | 3 +- .../node/entity/player/link/quest/Quest.java | 27 +- .../player/link/quest/QuestRepository.java | 55 ++- .../main/core/game/requirement/Requirement.kt | 283 ++++++++-------- Server/src/main/core/game/shops/Shops.kt | 5 +- .../system/command/sets/QuestCommandSet.kt | 6 +- .../game/system/config/DoorConfigLoader.kt | 2 - Server/src/test/kotlin/QuestTests.kt | 11 +- 577 files changed, 2634 insertions(+), 2138 deletions(-) create mode 100644 Server/src/main/content/data/Quests.kt diff --git a/Server/data/configs/door_configs.json b/Server/data/configs/door_configs.json index 8da3736ee..9608881e7 100644 --- a/Server/data/configs/door_configs.json +++ b/Server/data/configs/door_configs.json @@ -1984,16 +1984,14 @@ "replaceId": "28518", "fence": "false", "metal": "true", - "autowalk": "true", - "questRequirement": "Icthlarin's Little Helper" + "autowalk": "true" }, { "id": "28514", "replaceId": "28518", "fence": "false", "metal": "true", - "autowalk": "true", - "questRequirement": "Icthlarin's Little Helper" + "autowalk": "true" }, { "id": "21065", diff --git a/Server/src/main/content/data/GodBook.java b/Server/src/main/content/data/GodBook.java index 314e61773..92029b479 100644 --- a/Server/src/main/content/data/GodBook.java +++ b/Server/src/main/content/data/GodBook.java @@ -100,7 +100,7 @@ public enum GodBook { * @param page the page. */ public void insertPage(Player player, Item book, Item page) { - if (!hasRequirement(player, "Horror from the Deep")) + if (!hasRequirement(player, Quests.HORROR_FROM_THE_DEEP)) return; if (hasPage(player, book, page)) { player.sendMessage("The book already has that page."); diff --git a/Server/src/main/content/data/Quests.kt b/Server/src/main/content/data/Quests.kt new file mode 100644 index 000000000..190cf2093 --- /dev/null +++ b/Server/src/main/content/data/Quests.kt @@ -0,0 +1,158 @@ +package content.data + +enum class Quests(val questName: String) { + MYTHS_OF_THE_WHITE_LANDS("Myths of the White Lands"), + BLACK_KNIGHTS_FORTRESS("Black Knights' Fortress"), + COOKS_ASSISTANT("Cook's Assistant"), + DEMON_SLAYER("Demon Slayer"), + DORICS_QUEST("Doric's Quest"), + DRAGON_SLAYER("Dragon Slayer"), + ERNEST_THE_CHICKEN("Ernest the Chicken"), + GOBLIN_DIPLOMACY("Goblin Diplomacy"), + IMP_CATCHER("Imp Catcher"), + THE_KNIGHTS_SWORD("The Knight's Sword"), + PIRATES_TREASURE("Pirate's Treasure"), + PRINCE_ALI_RESCUE("Prince Ali Rescue"), + THE_RESTLESS_GHOST("The Restless Ghost"), + ROMEO_JULIET("Romeo & Juliet"), + RUNE_MYSTERIES("Rune Mysteries"), + SHEEP_SHEARER("Sheep Shearer"), + SHIELD_OF_ARRAV("Shield of Arrav"), + VAMPIRE_SLAYER("Vampire Slayer"), + WITCHS_POTION("Witch's Potion"), + ANIMAL_MAGNETISM("Animal Magnetism"), + BETWEEN_A_ROCK("Between a Rock..."), + BIG_CHOMPY_BIRD_HUNTING("Big Chompy Bird Hunting"), + BIOHAZARD("Biohazard"), + CABIN_FEVER("Cabin Fever"), + CLOCK_TOWER("Clock Tower"), + CONTACT("Contact!"), + ZOGRE_FLESH_EATERS("Zogre Flesh Eaters"), + CREATURE_OF_FENKENSTRAIN("Creature of Fenkenstrain"), + DARKNESS_OF_HALLOWVALE("Darkness of Hallowvale"), + DEATH_TO_THE_DORGESHUUN("Death to the Dorgeshuun"), + DEATH_PLATEAU("Death Plateau"), + DESERT_TREASURE("Desert Treasure"), + DEVIOUS_MINDS("Devious Minds"), + THE_DIG_SITE("The Dig Site"), + DRUIDIC_RITUAL("Druidic Ritual"), + DWARF_CANNON("Dwarf Cannon"), + EADGARS_RUSE("Eadgar's Ruse"), + EAGLES_PEAK("Eagles' Peak"), + ELEMENTAL_WORKSHOP_I("Elemental Workshop I"), + ELEMENTAL_WORKSHOP_II("Elemental Workshop II"), + ENAKHRAS_LAMENT("Enakhra's Lament"), + ENLIGHTENED_JOURNEY("Enlightened Journey"), + THE_EYES_OF_GLOUPHRIE("The Eyes of Glouphrie"), + FAIRYTALE_I_GROWING_PAINS("Fairytale I - Growing Pains"), + FAIRYTALE_II_CURE_A_QUEEN("Fairytale II - Cure a Queen"), + FAMILY_CREST("Family Crest"), + THE_FEUD("The Feud"), + FIGHT_ARENA("Fight Arena"), + FISHING_CONTEST("Fishing Contest"), + FORGETTABLE_TALE("Forgettable Tale..."), + THE_FREMENNIK_TRIALS("The Fremennik Trials"), + WATERFALL_QUEST("Waterfall Quest"), + GARDEN_OF_TRANQUILITY("Garden of Tranquility"), + GERTRUDES_CAT("Gertrude's Cat"), + GHOSTS_AHOY("Ghosts Ahoy"), + THE_GIANT_DWARF("The Giant Dwarf"), + THE_GOLEM("The Golem"), + THE_GRAND_TREE("The Grand Tree"), + THE_HAND_IN_THE_SAND("The Hand in the Sand"), + HAUNTED_MINE("Haunted Mine"), + HAZEEL_CULT("Hazeel Cult"), + HEROES_QUEST("Heroes' Quest"), + HOLY_GRAIL("Holy Grail"), + HORROR_FROM_THE_DEEP("Horror from the Deep"), + ICTHLARINS_LITTLE_HELPER("Icthlarin's Little Helper"), + IN_AID_OF_THE_MYREQUE("In Aid of the Myreque"), + IN_SEARCH_OF_THE_MYREQUE("In Search of the Myreque"), + JUNGLE_POTION("Jungle Potion"), + LEGENDS_QUEST("Legend's Quest"), + LOST_CITY("Lost City"), + THE_LOST_TRIBE("The Lost Tribe"), + LUNAR_DIPLOMACY("Lunar Diplomacy"), + MAKING_HISTORY("Making History"), + MERLINS_CRYSTAL("Merlin's Crystal"), + MONKEY_MADNESS("Monkey Madness"), + MONKS_FRIEND("Monk's Friend"), + MOUNTAIN_DAUGHTER("Mountain Daughter"), + MOURNINGS_END_PART_I("Mourning's End Part I"), + MOURNINGS_END_PART_II("Mourning's End Part II"), + MURDER_MYSTERY("Murder Mystery"), + MY_ARMS_BIG_ADVENTURE("My Arm's Big Adventure"), + NATURE_SPIRIT("Nature Spirit"), + OBSERVATORY_QUEST("Observatory Quest"), + ONE_SMALL_FAVOUR("One Small Favour"), + PLAGUE_CITY("Plague City"), + PRIEST_IN_PERIL("Priest in Peril"), + RAG_AND_BONE_MAN("Rag and Bone Man"), + RATCATCHERS("Ratcatchers"), + RECIPE_FOR_DISASTER("Recipe for Disaster"), + RECRUITMENT_DRIVE("Recruitment Drive"), + REGICIDE("Regicide"), + ROVING_ELVES("Roving Elves"), + ROYAL_TROUBLE("Royal Trouble"), + RUM_DEAL("Rum Deal"), + SCORPION_CATCHER("Scorpion Catcher"), + SEA_SLUG("Sea Slug"), + THE_SLUG_MENACE("The Slug Menace"), + SHADES_OF_MORTTON("Shades of Mort'ton"), + SHADOW_OF_THE_STORM("Shadow of the Storm"), + SHEEP_HERDER("Sheep Herder"), + SHILO_VILLAGE("Shilo Village"), + A_SOULS_BANE("A Soul's Bane"), + SPIRITS_OF_THE_ELID("Spirits of the Elid"), + SWAN_SONG("Swan Song"), + TAI_BWO_WANNAI_TRIO("Tai Bwo Wannai Trio"), + A_TAIL_OF_TWO_CATS("A Tail of Two Cats"), + TEARS_OF_GUTHIX("Tears of Guthix"), + TEMPLE_OF_IKOV("Temple of Ikov"), + THRONE_OF_MISCELLANIA("Throne of Miscellania"), + THE_TOURIST_TRAP("The Tourist Trap"), + WITCHS_HOUSE("Witch's House"), + TREE_GNOME_VILLAGE("Tree Gnome Village"), + TRIBAL_TOTEM("Tribal Totem"), + TROLL_ROMANCE("Troll Romance"), + TROLL_STRONGHOLD("Troll Stronghold"), + UNDERGROUND_PASS("Underground Pass"), + WANTED("Wanted!"), + WATCHTOWER("Watchtower"), + COLD_WAR("Cold War"), + THE_FREMENNIK_ISLES("The Fremennik Isles"), + TOWER_OF_LIFE("Tower of Life"), + THE_GREAT_BRAIN_ROBBERY("The Great Brain Robbery"), + WHAT_LIES_BELOW("What Lies Below"), + OLAFS_QUEST("Olaf's Quest"), + ANOTHER_SLICE_OF_HAM("Another Slice of H.A.M"), + DREAM_MENTOR("Dream Mentor"), + GRIM_TALES("Grim Tales"), + KINGS_RANSOM("King's Ransom"), + THE_PATH_OF_GLOUPHRIE("The Path of Glouphrie"), + BACK_TO_MY_ROOTS("Back to my Roots"), + LAND_OF_THE_GOBLINS("Land of the Goblins"), + DEALING_WITH_SCABARAS("Dealing with Scabaras"), + WOLF_WHISTLE("Wolf Whistle"), + AS_A_FIRST_RESORT("As a First Resort..."), + CATAPULT_CONSTRUCTION("Catapult Construction"), + KENNITHS_CONCERNS("Kennith's Concerns"), + LEGACY_OF_SEERGAZE("Legacy of Seergaze"), + PERILS_OF_ICE_MOUNTAIN("Perils of Ice Mountain"), + TOKTZ_KET_DILL("TokTz-Ket-Dill"), + SMOKING_KILLS("Smoking Kills"), + ROCKING_OUT("Rocking Out"), + SPIRIT_OF_SUMMER("Spirit of Summer"), + MEETING_HISTORY("Meeting History"), + ALL_FIRED_UP("All Fired Up"), + SUMMERS_END("Summer's End"), + DEFENDER_OF_VARROCK("Defender of Varrock"), + SWEPT_AWAY("Swept Away"), + WHILE_GUTHIX_SLEEPS("While Guthix Sleeps"), + IN_PYRE_NEED("In Pyre Need"), + TEST_QUEST("Test Quest"); + + override fun toString(): String { + return questName + } +} diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt index dcb48e84a..0dd2e005a 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt @@ -30,7 +30,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando "Relleka mining site" to Location.create(2682, 3700, 0), // Rellekka mining site "Jatizso mine" to Location.create(2393, 3815, 0), //Jatiszo mining site (requires Fremennik Isles prereqs) "Lunar Isle mine" to Location.create(2140, 3939, 0), // Lunar Isle mine (requires Lunar Diplomacy prereqs) - "Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires Fremennik Trials) + "Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires The Fremennik Trials) //"Neitiznot runite mine" to Location.create(2376, 3835, 0), // Near the Neitiznot runite mine (requires Fremennik Isles prereqs) currently inaccessible as bridge does not work "Ardougne mining site" to Location.create(2600, 3232, 0), // Ardougne mining site (Monastery) "Ardougne eastern mine" to Location.create(2706, 3334, 0), // Ardougne mining site (Legends Guild) diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt index 274a414a6..680d2d6da 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt @@ -12,11 +12,11 @@ import core.ServerStore.Companion.getBoolean import core.game.dialogue.DialogueFile import core.game.interaction.InteractionListener import core.game.interaction.IntType -import core.tools.SystemLogger import core.game.system.command.Privilege import core.game.world.GameWorld import core.tools.Log import core.tools.secondsToTicks +import content.data.Quests class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Commands, StartupListener { override fun login(player: Player) { @@ -80,17 +80,17 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com override fun handle(componentID: Int, buttonID: Int) { fun teleportToStar(player: Player) { val condition: (p: Player) -> Boolean = when (star.location.toLowerCase()) { - "canifis bank" -> {p -> requireQuest(p, "Priest in Peril", "to access this.") } - //"burgh de rott bank" -> {p -> hasRequirement(p, "In Aid of the Myreque") } //disabled: crash - "crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40) } - "lletya bank" -> {p -> hasRequirement(p, "Mourning's End Part I") } - "jatizso mine" -> {p -> hasRequirement(p, "The Fremennik Isles") } - "south crandor mining site" -> {p -> hasRequirement(p, "Dragon Slayer") } - "shilo village mining site" -> {p -> hasRequirement(p, "Shilo Village") } - "mos le'harmless bank" -> {p -> hasRequirement(p, "Cabin Fever") } //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025 - "lunar isle mine" -> {p -> hasRequirement(p, "Lunar Diplomacy") } - "miscellania coal mine" -> {p -> requireQuest(p, "The Fremennik Trials", "to access this.") } - //"neitiznot runite mine" -> {p -> hasRequirement(p, "The Fremennik Isles") } //disabled: currently not reachable + "canifis bank" -> {p -> requireQuest(p, Quests.PRIEST_IN_PERIL, "to access this.")} + //"burgh de rott bank" -> {p -> hasRequirement(p, Quests.IN_AID_OF_THE_MYREQUE)} //disabled: crash + "crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40)} + "lletya bank" -> {p -> hasRequirement(p, Quests.MOURNINGS_END_PART_I)} + "jatizso mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)} + "south crandor mining site" -> {p -> hasRequirement(p, Quests.DRAGON_SLAYER)} + "shilo village mining site" -> {p -> hasRequirement(p, Quests.SHILO_VILLAGE)} + "mos le'harmless bank" -> {p -> hasRequirement(p, Quests.CABIN_FEVER)} //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025 + "lunar isle mine" -> {p -> hasRequirement(p, Quests.LUNAR_DIPLOMACY)} + "miscellania coal mine" -> {p -> requireQuest(p, Quests.THE_FREMENNIK_TRIALS, "to access this.")} + //"neitiznot runite mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)} //disabled: currently not reachable else -> {_ -> true} } if (!condition.invoke(player)) { diff --git a/Server/src/main/content/global/bots/CannonballSmelter.kt b/Server/src/main/content/global/bots/CannonballSmelter.kt index ca6406937..8ac77f7e1 100644 --- a/Server/src/main/content/global/bots/CannonballSmelter.kt +++ b/Server/src/main/content/global/bots/CannonballSmelter.kt @@ -7,8 +7,6 @@ import core.api.* import core.game.bots.* import core.game.ge.GrandExchange import core.game.interaction.DestinationFlag -import core.game.interaction.IntType -import core.game.interaction.InteractionListeners import core.game.interaction.MovementPulse import core.game.node.Node import core.game.node.entity.skill.Skills @@ -16,6 +14,7 @@ import core.game.node.item.Item import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import org.rs09.consts.Items +import content.data.Quests @PlayerCompatible @ScriptName("Falador Cannonball Smelter") @@ -273,6 +272,6 @@ class CannonballSmelter : Script() { skills.put(Skills.HITPOINTS,99) skills.put(Skills.DEFENCE,99) skills.put(Skills.SMITHING,35) - quests.add("Dwarf Cannon") + quests.add(Quests.DWARF_CANNON) } } diff --git a/Server/src/main/content/global/handlers/iface/ExperienceInterface.kt b/Server/src/main/content/global/handlers/iface/ExperienceInterface.kt index be4d2599e..c7003ea83 100644 --- a/Server/src/main/content/global/handlers/iface/ExperienceInterface.kt +++ b/Server/src/main/content/global/handlers/iface/ExperienceInterface.kt @@ -10,6 +10,7 @@ import core.plugin.Initializable import core.plugin.Plugin import core.tools.Log import org.rs09.consts.Sounds +import content.data.Quests /** * Represents the experience interface. @@ -78,15 +79,15 @@ class ExperienceInterface() : ComponentPlugin() { } private fun checkHerblore(player: Player): Boolean{ - return (player.questRepository.isComplete("Druidic Ritual")) + return (player.questRepository.isComplete(Quests.DRUIDIC_RITUAL)) } private fun checkSummoning(player: Player): Boolean{ - return player.questRepository.isComplete("Wolf Whistle") + return player.questRepository.isComplete(Quests.WOLF_WHISTLE) } private fun checkRunecrafting(player: Player): Boolean{ - return player.questRepository.isComplete("Rune Mysteries") + return player.questRepository.isComplete(Quests.RUNE_MYSTERIES) } companion object { diff --git a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt index f73ec61c4..69bba13d7 100644 --- a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt +++ b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt @@ -10,7 +10,7 @@ import core.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.RegionManager import core.tools.RandomFunction - +import content.data.Quests /** * Handles the fairy ring interface @@ -179,7 +179,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int AKS(Location.create(2571, 2956, 0), "Feldip Hills: Jungle Hunter area", 25), ALQ(Location.create(3597, 3495, 0), "Morytania: Haunted Woods east of Canifis", 27) { override fun checkAccess(player: Player) : Boolean { - return requireQuest(player, "Priest in Peril", "to use this ring.") + return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.") } }, ALS(Location.create(2644, 3495, 0), "Kandarin: McGrubor's Wood", 29), @@ -191,7 +191,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int BKQ(Location.create(3041, 4532, 0), "Other realms: Enchanted Valley", 39), BKR(Location.create(3469, 3431, 0), "Morytania: Mort Myre, south of Canifis", 40) { override fun checkAccess(player: Player) : Boolean { - return requireQuest(player, "Priest in Peril", "to use this ring.") + return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.") } }, BLP(Location.create(2437, 5126, 0), "Dungeons: TzHaar area", 42), @@ -199,7 +199,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int BLR(Location.create(2740, 3351, 0), "Kandarin: Legends' Guild", 44), CIP(Location.create(2513, 3884, 0), "Islands: Miscellania", 46) { override fun checkAccess(player: Player): Boolean { - return requireQuest(player, "Fremennik Trials", "to use this ring.") + return requireQuest(player, Quests.THE_FREMENNIK_TRIALS, "to use this ring.") } }, CIQ(Location.create(2528, 3127, 0), "Kandarin: North-west of Yanille", 47), @@ -208,7 +208,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int CKR(Location.create(2801, 3003, 0), "Karamja: South of Tai Bwo Wannai Village", 56), CKS(Location.create(3447, 3470, 0), "Morytania: Canifis", 57) { override fun checkAccess(player: Player) : Boolean { - return requireQuest(player, "Priest in Peril", "to use this ring.") + return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.") } }, CLP(Location.create(3082, 3206, 0), "Islands: South of Draynor Village", 58), diff --git a/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java b/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java index 2d0932e89..2c31b11ce 100644 --- a/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java +++ b/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java @@ -9,6 +9,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Represents the prayer interface. @@ -27,7 +28,7 @@ public final class PrayerTabInterface extends ComponentPlugin { public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { final PrayerType type = PrayerType.get(button); if (type == PrayerType.CHIVALRY || type == PrayerType.PIETY) - if (!hasRequirement(player, "King's Ransom")) + if (!hasRequirement(player, Quests.KINGS_RANSOM)) return true; if (type == null) { return true; diff --git a/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt b/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt index d7482c089..3af184404 100644 --- a/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt +++ b/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt @@ -10,12 +10,13 @@ import kotlin.math.* import java.util.* import org.rs09.consts.* +import content.data.Quests 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 + fun showRequirementsInterface(player: Player, button: Int) { + val questName = getNameForButton(button) + val questReq = QuestRequirements.values().filter { it.quest.questName == questName }.firstOrNull() ?: return var (isMet, unmetReqs) = QuestReq(questReq).evaluate(player) var messageList = ArrayList() @@ -27,7 +28,7 @@ object QuestTabUtils { closeInterface(player) for (req in unmetReqs) { if (req is QuestReq) - questList.add(req.questReq.questName) + questList.add(req.questReq.quest.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 @@ -82,163 +83,163 @@ object QuestTabUtils { 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" + private fun getNameForButton(button: Int) : String { + val quest = when (button) { + 10 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName + 11 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName 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" + 13 -> Quests.BLACK_KNIGHTS_FORTRESS.questName + 14 -> Quests.COOKS_ASSISTANT.questName + 15 -> Quests.DEMON_SLAYER.questName + 16 -> Quests.DORICS_QUEST.questName + 17 -> Quests.DRAGON_SLAYER.questName + 18 -> Quests.ERNEST_THE_CHICKEN.questName + 19 -> Quests.GOBLIN_DIPLOMACY.questName + 20 -> Quests.IMP_CATCHER.questName + 21 -> Quests.THE_KNIGHTS_SWORD.questName + 22 -> Quests.PIRATES_TREASURE.questName + 23 -> Quests.PRINCE_ALI_RESCUE.questName + 24 -> Quests.THE_RESTLESS_GHOST.questName + 25 -> Quests.ROMEO_JULIET.questName + 26 -> Quests.RUNE_MYSTERIES.questName + 27 -> Quests.SHEEP_SHEARER.questName + 28 -> Quests.SHIELD_OF_ARRAV.questName + 29 -> Quests.VAMPIRE_SLAYER.questName + 30 -> Quests.WITCHS_POTION.questName 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" + 32 -> Quests.ANIMAL_MAGNETISM.questName + 33 -> Quests.BETWEEN_A_ROCK.questName + 34 -> Quests.BIG_CHOMPY_BIRD_HUNTING.questName + 35 -> Quests.BIOHAZARD.questName + 36 -> Quests.CABIN_FEVER.questName + 37 -> Quests.CLOCK_TOWER.questName + 38 -> Quests.CONTACT.questName + 39 -> Quests.ZOGRE_FLESH_EATERS.questName + 40 -> Quests.CREATURE_OF_FENKENSTRAIN.questName + 41 -> Quests.DARKNESS_OF_HALLOWVALE.questName + 42 -> Quests.DEATH_TO_THE_DORGESHUUN.questName + 43 -> Quests.DEATH_PLATEAU.questName + 44 -> Quests.DESERT_TREASURE.questName + 45 -> Quests.DEVIOUS_MINDS.questName + 46 -> Quests.THE_DIG_SITE.questName + 47 -> Quests.DRUIDIC_RITUAL.questName + 48 -> Quests.DWARF_CANNON.questName + 49 -> Quests.EADGARS_RUSE.questName + 50 -> Quests.EAGLES_PEAK.questName + 51 -> Quests.ELEMENTAL_WORKSHOP_I.questName + 52 -> Quests.ELEMENTAL_WORKSHOP_II.questName + 53 -> Quests.ENAKHRAS_LAMENT.questName + 54 -> Quests.ENLIGHTENED_JOURNEY.questName + 55 -> Quests.THE_EYES_OF_GLOUPHRIE.questName + 56 -> Quests.FAIRYTALE_I_GROWING_PAINS.questName + 57 -> Quests.FAIRYTALE_II_CURE_A_QUEEN.questName + 58 -> Quests.FAMILY_CREST.questName + 59 -> Quests.THE_FEUD.questName + 60 -> Quests.FIGHT_ARENA.questName + 61 -> Quests.FISHING_CONTEST.questName + 62 -> Quests.FORGETTABLE_TALE.questName + 63 -> Quests.THE_FREMENNIK_TRIALS.questName + 64 -> Quests.WATERFALL_QUEST.questName + 65 -> Quests.GARDEN_OF_TRANQUILITY.questName + 66 -> Quests.GERTRUDES_CAT.questName + 67 -> Quests.GHOSTS_AHOY.questName + 68 -> Quests.THE_GIANT_DWARF.questName + 69 -> Quests.THE_GOLEM.questName + 70 -> Quests.THE_GRAND_TREE.questName + 71 -> Quests.THE_HAND_IN_THE_SAND.questName + 72 -> Quests.HAUNTED_MINE.questName + 73 -> Quests.HAZEEL_CULT.questName + 74 -> Quests.HEROES_QUEST.questName + 75 -> Quests.HOLY_GRAIL.questName + 76 -> Quests.HORROR_FROM_THE_DEEP.questName + 77 -> Quests.ICTHLARINS_LITTLE_HELPER.questName + 78 -> Quests.IN_AID_OF_THE_MYREQUE.questName + 79 -> Quests.IN_SEARCH_OF_THE_MYREQUE.questName + 80 -> Quests.JUNGLE_POTION.questName + 81 -> Quests.LEGENDS_QUEST.questName + 82 -> Quests.LOST_CITY.questName + 83 -> Quests.THE_LOST_TRIBE.questName + 84 -> Quests.LUNAR_DIPLOMACY.questName + 85 -> Quests.MAKING_HISTORY.questName + 86 -> Quests.MERLINS_CRYSTAL.questName + 87 -> Quests.MONKEY_MADNESS.questName + 88 -> Quests.MONKS_FRIEND.questName + 89 -> Quests.MOUNTAIN_DAUGHTER.questName + 90 -> Quests.MOURNINGS_END_PART_I.questName + 91 -> Quests.MOURNINGS_END_PART_II.questName + 92 -> Quests.MURDER_MYSTERY.questName + 93 -> Quests.MY_ARMS_BIG_ADVENTURE.questName + 94 -> Quests.NATURE_SPIRIT.questName + 95 -> Quests.OBSERVATORY_QUEST.questName + 96 -> Quests.ONE_SMALL_FAVOUR.questName + 97 -> Quests.PLAGUE_CITY.questName + 98 -> Quests.PRIEST_IN_PERIL.questName + 99 -> Quests.RAG_AND_BONE_MAN.questName + 100 -> Quests.RATCATCHERS.questName + 101 -> Quests.RECIPE_FOR_DISASTER.questName + 102 -> Quests.RECRUITMENT_DRIVE.questName + 103 -> Quests.REGICIDE.questName + 104 -> Quests.ROVING_ELVES.questName + 105 -> Quests.ROYAL_TROUBLE.questName + 106 -> Quests.RUM_DEAL.questName + 107 -> Quests.SCORPION_CATCHER.questName + 108 -> Quests.SEA_SLUG.questName + 109 -> Quests.THE_SLUG_MENACE.questName + 110 -> Quests.SHADES_OF_MORTTON.questName + 111 -> Quests.SHADOW_OF_THE_STORM.questName + 112 -> Quests.SHEEP_HERDER.questName + 113 -> Quests.SHILO_VILLAGE.questName + 114 -> Quests.A_SOULS_BANE.questName + 115 -> Quests.SPIRITS_OF_THE_ELID.questName + 116 -> Quests.SWAN_SONG.questName + 117 -> Quests.TAI_BWO_WANNAI_TRIO.questName + 118 -> Quests.A_TAIL_OF_TWO_CATS.questName + 119 -> Quests.TEARS_OF_GUTHIX.questName + 120 -> Quests.TEMPLE_OF_IKOV.questName + 121 -> Quests.THRONE_OF_MISCELLANIA.questName + 122 -> Quests.THE_TOURIST_TRAP.questName + 123 -> Quests.WITCHS_HOUSE.questName + 124 -> Quests.TREE_GNOME_VILLAGE.questName + 125 -> Quests.TRIBAL_TOTEM.questName + 126 -> Quests.TROLL_ROMANCE.questName + 127 -> Quests.TROLL_STRONGHOLD.questName + 128 -> Quests.UNDERGROUND_PASS.questName + 129 -> Quests.WANTED.questName + 130 -> Quests.WATCHTOWER.questName + 131 -> Quests.COLD_WAR.questName + 132 -> Quests.THE_FREMENNIK_ISLES.questName + 133 -> Quests.TOWER_OF_LIFE.questName + 134 -> Quests.THE_GREAT_BRAIN_ROBBERY.questName + 135 -> Quests.WHAT_LIES_BELOW.questName + 136 -> Quests.OLAFS_QUEST.questName + 137 -> Quests.ANOTHER_SLICE_OF_HAM.questName + 138 -> Quests.DREAM_MENTOR.questName + 139 -> Quests.GRIM_TALES.questName + 140 -> Quests.KINGS_RANSOM.questName + 141 -> Quests.THE_PATH_OF_GLOUPHRIE.questName + 142 -> Quests.BACK_TO_MY_ROOTS.questName + 143 -> Quests.LAND_OF_THE_GOBLINS.questName + 144 -> Quests.DEALING_WITH_SCABARAS.questName + 145 -> Quests.WOLF_WHISTLE.questName + 146 -> Quests.AS_A_FIRST_RESORT.questName + 147 -> Quests.CATAPULT_CONSTRUCTION.questName + 148 -> Quests.KENNITHS_CONCERNS.questName + 149 -> Quests.LEGACY_OF_SEERGAZE.questName + 150 -> Quests.PERILS_OF_ICE_MOUNTAIN.questName + 151 -> Quests.TOKTZ_KET_DILL.questName + 152 -> Quests.SMOKING_KILLS.questName + 153 -> Quests.ROCKING_OUT.questName + 154 -> Quests.SPIRIT_OF_SUMMER.questName + 155 -> Quests.MEETING_HISTORY.questName + 156 -> Quests.ALL_FIRED_UP.questName + 157 -> Quests.SUMMERS_END.questName + 158 -> Quests.DEFENDER_OF_VARROCK.questName + 159 -> Quests.SWEPT_AWAY.questName + 160 -> Quests.WHILE_GUTHIX_SLEEPS.questName + 161 -> Quests.IN_PYRE_NEED.questName + 162 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName else -> "" } - return name + return quest as String } } diff --git a/Server/src/main/content/global/handlers/item/EctophialListener.kt b/Server/src/main/content/global/handlers/item/EctophialListener.kt index 6370c9c22..111db96c5 100644 --- a/Server/src/main/content/global/handlers/item/EctophialListener.kt +++ b/Server/src/main/content/global/handlers/item/EctophialListener.kt @@ -13,6 +13,7 @@ import core.game.world.update.flag.context.Graphics import org.rs09.consts.Items import org.rs09.consts.Scenery import org.rs09.consts.Sounds +import content.data.Quests @Suppress("unused") class EctophialListener : InteractionListener { @@ -37,7 +38,7 @@ class EctophialListener : InteractionListener { } on(Items.ECTOPHIAL_4251, IntType.ITEM, "empty") { player, node -> - if (!hasRequirement(player, "Ghosts Ahoy")) + if (!hasRequirement(player, Quests.GHOSTS_AHOY)) return@on true if (player.isTeleBlocked) { diff --git a/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt b/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt index 4dd960bad..8acaa698a 100644 --- a/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt +++ b/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt @@ -4,6 +4,7 @@ import core.api.* import core.game.node.entity.player.link.quest.QuestRepository import org.rs09.consts.Items import core.game.interaction.InteractionListener +import content.data.Quests class ItemQuestRequirementListener : InteractionListener { @@ -106,7 +107,7 @@ class ItemQuestRequirementListener : InteractionListener { /* onEquip(fremennikIslesEquipment) { player, _ -> - if (!isQuestComplete(player, "Fremennik Isles")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_ISLES)) { sendMessage(player, "You must have completed The Fremennik Isles to equip this.") return@onEquip false } @@ -114,7 +115,7 @@ class ItemQuestRequirementListener : InteractionListener { } onEquip(fremennikIslesDuringQuestEquipment){ player, _ -> - if (questStage(player, "Fremennik Isles") > 0) { + if (questStage(player, Quests.THE_FREMENNIK_ISLES) > 0) { sendMessage(player, "You must have started The Fremennik Isles to equip this.") return@onEquip false } @@ -123,23 +124,23 @@ class ItemQuestRequirementListener : InteractionListener { */ onEquip(fremennikTrialsEquipment) { player, _ -> - return@onEquip hasRequirement(player, "Fremennik Trials") + return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_TRIALS) } onEquip(fremennikIslesEquipment) {player, _ -> - return@onEquip hasRequirement(player, "The Fremennik Isles") + return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_ISLES) } onEquip(avasBackpacks){ player, _ -> - return@onEquip hasRequirement(player, "Animal Magnetism") + return@onEquip hasRequirement(player, Quests.ANIMAL_MAGNETISM) } onEquip(lostCityWeapons){ player, _ -> - return@onEquip hasRequirement(player, "Lost City") + return@onEquip hasRequirement(player, Quests.LOST_CITY) } onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ -> - return@onEquip hasRequirement(player, "Legend's Quest") + return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST) } onEquip(questCapes) { player, _ -> @@ -152,84 +153,84 @@ class ItemQuestRequirementListener : InteractionListener { } onEquip(Items.WOLFBANE_2952){ player, _ -> - return@onEquip hasRequirement(player, "Priest in Peril") + return@onEquip hasRequirement(player, Quests.PRIEST_IN_PERIL) } onEquip(Items.ANCIENT_MACE_11061){ player, _ -> - return@onEquip hasRequirement(player, "Another Slice of H.A.M") + return@onEquip hasRequirement(player, Quests.ANOTHER_SLICE_OF_HAM) } onEquip(Items.ANCIENT_STAFF_4675){ player, _ -> - return@onEquip hasRequirement(player, "Desert Treasure") + return@onEquip hasRequirement(player, Quests.DESERT_TREASURE) } onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ -> - return@onEquip hasRequirement(player, "Elemental Workshop I") + return@onEquip hasRequirement(player, Quests.ELEMENTAL_WORKSHOP_I) } onEquip(crystalEquipment){ player, _ -> - return@onEquip hasRequirement(player, "Roving Elves") + return@onEquip hasRequirement(player, Quests.ROVING_ELVES) } onEquip(dragonSlayerEquipment) {player, _ -> - return@onEquip hasRequirement(player, "Dragon Slayer") + return@onEquip hasRequirement(player, Quests.DRAGON_SLAYER) } onEquip(Items.DRAGON_SCIMITAR_4587) {player, _ -> - return@onEquip hasRequirement(player, "Monkey Madness") + return@onEquip hasRequirement(player, Quests.MONKEY_MADNESS) } onEquip(Items.GLOVES_7462) {player, _ -> - return@onEquip hasRequirement(player, "Recipe for Disaster") + return@onEquip hasRequirement(player, Quests.RECIPE_FOR_DISASTER) } onEquip(Items.SLAYER_HELMET_13263) {player, _ -> - return@onEquip hasRequirement(player, "Smoking Kills") + return@onEquip hasRequirement(player, Quests.SMOKING_KILLS) } onEquip (Items.DRAGON_HALBERD_3204) {player, _ -> - return@onEquip hasRequirement(player, "Regicide") + return@onEquip hasRequirement(player, Quests.REGICIDE) } onEquip (Items.CLIMBING_BOOTS_3105) {player, _ -> - return@onEquip hasRequirement(player, "Death Plateau") + return@onEquip hasRequirement(player, Quests.DEATH_PLATEAU) } onEquip (godBooks) {player, _ -> - return@onEquip hasRequirement(player, "Horror from the Deep") + return@onEquip hasRequirement(player, Quests.HORROR_FROM_THE_DEEP) } onEquip (pharaohScepters) {player, _ -> - return@onEquip hasRequirement(player, "Icthlarin's Little Helper") + return@onEquip hasRequirement(player, Quests.ICTHLARINS_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") + return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST) } onEquip (initiateArmour) {player, _ -> - return@onEquip hasRequirement(player, "Recruitment Drive") + return@onEquip hasRequirement(player, Quests.RECRUITMENT_DRIVE) } onEquip (proselyteArmour) {player, _ -> - return@onEquip hasRequirement(player, "The Slug Menace") + return@onEquip hasRequirement(player, Quests.THE_SLUG_MENACE) } onEquip (spiritShields) {player, _ -> - return@onEquip hasRequirement(player, "Summer's End") + return@onEquip hasRequirement(player, Quests.SUMMERS_END) } onEquip (Items.DRAGON_MACE_1434) {player, _ -> - return@onEquip hasRequirement(player, "Heroes' Quest") + return@onEquip hasRequirement(player, Quests.HEROES_QUEST) } onEquip (Items.DRAGON_BATTLEAXE_1377) {player, _ -> - return@onEquip hasRequirement(player, "Heroes' Quest") + return@onEquip hasRequirement(player, Quests.HEROES_QUEST) } onEquip (Items.DARKLIGHT_6746) {player, _ -> - return@onEquip hasRequirement(player, "Shadow of the Storm") + return@onEquip hasRequirement(player, Quests.SHADOW_OF_THE_STORM) } } } diff --git a/Server/src/main/content/global/handlers/item/SilverSicklePlugin.java b/Server/src/main/content/global/handlers/item/SilverSicklePlugin.java index eb403f33b..e7529d646 100644 --- a/Server/src/main/content/global/handlers/item/SilverSicklePlugin.java +++ b/Server/src/main/content/global/handlers/item/SilverSicklePlugin.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.plugin.Plugin; import content.region.morytania.quest.naturespirit.NSUtils; +import content.data.Quests; /** * Handles the Silver Sickle (b) to collect Mort Myre Fungus. @@ -28,7 +29,7 @@ public final class SilverSicklePlugin extends OptionHandler { switch (option) { case "operate": case "cast bloom": - if(player.getQuestRepository().getQuest("Nature Spirit").getStage(player) >= 75) { + if(player.getQuestRepository().getQuest(Quests.NATURE_SPIRIT).getStage(player) >= 75) { player.getPacketDispatch().sendAnimation(9021); NSUtils.castBloom(player); } else { diff --git a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt index 21a291360..6b0b7c0d3 100644 --- a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt +++ b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt @@ -10,12 +10,13 @@ import core.game.node.entity.player.link.TeleportManager import core.game.node.item.Item import core.game.world.map.Location import core.api.hasRequirement; +import content.data.Quests class TeleTabsListener : InteractionListener { enum class TeleTabs(val item: Int, val location: Location, val exp: Double, val requirementCheck: (Player) -> Boolean = { true }) { ADDOUGNE_TELEPORT(8011, Location.create(2662, 3307, 0), 61.0, { - player -> hasRequirement(player, "Plague City"); + player -> hasRequirement(player, Quests.PLAGUE_CITY); }), AIR_ALTAR_TELEPORT(13599, Location.create(2978, 3296, 0), 0.0), ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0), diff --git a/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java b/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java index 94c3b4eb7..5bbda0ffc 100644 --- a/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java +++ b/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java @@ -14,6 +14,7 @@ import core.game.world.map.zone.impl.WildernessZone; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Represents the rotten potato plugin. @@ -34,7 +35,7 @@ public final class TeleportCrystalPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - if (!hasRequirement(player, "Mourning's End Part I")) + if (!hasRequirement(player, Quests.MOURNINGS_END_PART_I)) return true; if (!WildernessZone.checkTeleport(player, 20)) { player.getPacketDispatch().sendMessage("The crystal is unresponsive."); diff --git a/Server/src/main/content/global/handlers/item/withnpc/GCItemOnCat.kt b/Server/src/main/content/global/handlers/item/withnpc/GCItemOnCat.kt index 3209b4f45..0b54ccf55 100644 --- a/Server/src/main/content/global/handlers/item/withnpc/GCItemOnCat.kt +++ b/Server/src/main/content/global/handlers/item/withnpc/GCItemOnCat.kt @@ -10,27 +10,27 @@ import org.rs09.consts.NPCs import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.world.GameWorld.Pulser +import content.data.Quests class GCItemOnCat : InteractionListener { override fun defineListeners() { - val GERTCAT = "Gertrude's Cat" val BEND_DOWN = 827 onUseWith(IntType.NPC, Items.BUCKET_OF_MILK_1927, NPCs.GERTRUDES_CAT_2997) { player, used, with -> - if(getQuestStage(player, GERTCAT) == 20 && removeItem(player, used.asItem())){ + if(getQuestStage(player, Quests.GERTRUDES_CAT) == 20 && removeItem(player, used.asItem())){ addItem(player, Items.BUCKET_1925) animate(player, BEND_DOWN) //bend down sendChat(with.asNpc(), "Mew!") - setQuestStage(player, GERTCAT, 30) + setQuestStage(player, Quests.GERTRUDES_CAT, 30) } return@onUseWith true } onUseWith(IntType.NPC, Items.DOOGLE_SARDINE_1552, NPCs.GERTRUDES_CAT_2997){ player, used, with -> - if(getQuestStage(player, GERTCAT) == 30 && removeItem(player, used.asItem())){ + if(getQuestStage(player, Quests.GERTRUDES_CAT) == 30 && removeItem(player, used.asItem())){ animate(player, BEND_DOWN) sendChat(with.asNpc(), "Mew!") - setQuestStage(player, GERTCAT, 40) + setQuestStage(player, Quests.GERTRUDES_CAT, 40) } return@onUseWith true } @@ -42,7 +42,7 @@ class GCItemOnCat : InteractionListener { onUseWith(IntType.NPC, Items.THREE_LITTLE_KITTENS_13236, NPCs.GERTRUDES_CAT_2997){ player, used, with -> if(removeItem(player, used.asItem())){ - setQuestStage(player, GERTCAT, 60) + setQuestStage(player, Quests.GERTRUDES_CAT, 60) //below copied verbatim from original, I don't like it. Pulser.submit(object : Pulse(1) { var count = 0 diff --git a/Server/src/main/content/global/handlers/item/withnpc/GertrudeCatUsePlugin.java b/Server/src/main/content/global/handlers/item/withnpc/GertrudeCatUsePlugin.java index b939f3735..efddb3bed 100644 --- a/Server/src/main/content/global/handlers/item/withnpc/GertrudeCatUsePlugin.java +++ b/Server/src/main/content/global/handlers/item/withnpc/GertrudeCatUsePlugin.java @@ -14,6 +14,7 @@ import core.game.world.map.path.Pathfinder; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the plugin used to handle the use with interactions. @@ -50,7 +51,7 @@ public final class GertrudeCatUsePlugin extends UseWithHandler { public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); final NPC npc = ((NPC) event.getUsedWith()); - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); if (event.getUsedItem().getId() == 1927 && quest.getStage(player) == 20) { if (player.getInventory().remove(event.getUsedItem())) { player.getInventory().add(EMPTY_BUCKET); diff --git a/Server/src/main/content/global/handlers/item/withnpc/RopeOnLadyKeli.kt b/Server/src/main/content/global/handlers/item/withnpc/RopeOnLadyKeli.kt index dab9e0c12..3dbd34a6d 100644 --- a/Server/src/main/content/global/handlers/item/withnpc/RopeOnLadyKeli.kt +++ b/Server/src/main/content/global/handlers/item/withnpc/RopeOnLadyKeli.kt @@ -5,20 +5,19 @@ import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests class RopeOnLadyKeli : InteractionListener { override fun defineListeners() { - val PAR = "Prince Ali Rescue" - onUseWith(IntType.NPC, Items.ROPE_954, NPCs.LADY_KELI_919) { player, used, with -> - if(getQuestStage(player, PAR) in 40..50 && getAttribute(player, "guard-drunk", false)){ + if(getQuestStage(player, Quests.PRINCE_ALI_RESCUE) in 40..50 && getAttribute(player, "guard-drunk", false)){ if(removeItem(player, used.asItem())){ sendDialogue(player, "You overpower Keli, tie her up, and put her in a cupboard.") - setQuestStage(player, PAR, 50) + setQuestStage(player, Quests.PRINCE_ALI_RESCUE, 50) setAttribute(player, "keli-gone", getWorldTicks() + 350) } } else { - if (getQuestStage(player, PAR) == 40){ + if (getQuestStage(player, Quests.PRINCE_ALI_RESCUE) == 40){ sendMessage(player, "You need to do something about the guard first.") } } diff --git a/Server/src/main/content/global/handlers/item/withobject/AmmoMouldOnFurnace.kt b/Server/src/main/content/global/handlers/item/withobject/AmmoMouldOnFurnace.kt index 5b78dd96b..0d5929d0a 100644 --- a/Server/src/main/content/global/handlers/item/withobject/AmmoMouldOnFurnace.kt +++ b/Server/src/main/content/global/handlers/item/withobject/AmmoMouldOnFurnace.kt @@ -1,7 +1,7 @@ package content.global.handlers.item.withobject +import content.data.Quests import core.api.* -import content.region.kandarin.quest.dwarfcannon.DwarfCannon import core.game.node.Node import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills @@ -19,8 +19,8 @@ class AmmoMouldOnFurnace : InteractionListener { private fun cannonBallOnUseWithHandler(player: Player, used: Node, with: Node): Boolean { face(player, with.centerLocation) - if(!isQuestComplete(player, DwarfCannon.NAME)) { - sendDialogue(player, "You need to complete the ${DwarfCannon.NAME} quest in order to do this.") + if(!isQuestComplete(player, Quests.DWARF_CANNON)) { + sendDialogue(player, "You need to complete the ${Quests.DWARF_CANNON} quest in order to do this.") return true } if (getDynLevel(player, Skills.SMITHING) < levelRequirement) { diff --git a/Server/src/main/content/global/handlers/item/withobject/SmithingPlugin.java b/Server/src/main/content/global/handlers/item/withobject/SmithingPlugin.java index 95d10cb2c..e9ef946b3 100644 --- a/Server/src/main/content/global/handlers/item/withobject/SmithingPlugin.java +++ b/Server/src/main/content/global/handlers/item/withobject/SmithingPlugin.java @@ -15,6 +15,7 @@ import core.game.node.scenery.Scenery; import core.plugin.Plugin; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the option handler used for smithing. @@ -68,7 +69,7 @@ public final class SmithingPlugin extends UseWithHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - if (((Scenery) event.getUsedWith()).getId() == 2782 && !player.getQuestRepository().isComplete("Doric's Quest")) { + if (((Scenery) event.getUsedWith()).getId() == 2782 && !player.getQuestRepository().isComplete(Quests.DORICS_QUEST)) { player.getDialogueInterpreter().sendDialogue("Property of Doric the Dwarf."); return true; } diff --git a/Server/src/main/content/global/handlers/npc/RatNPC.java b/Server/src/main/content/global/handlers/npc/RatNPC.java index 11f4fce94..f8a380db4 100644 --- a/Server/src/main/content/global/handlers/npc/RatNPC.java +++ b/Server/src/main/content/global/handlers/npc/RatNPC.java @@ -7,6 +7,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.world.map.Location; +import content.data.Quests; /** * Represents a rat npc. @@ -51,7 +52,7 @@ public class RatNPC extends AbstractNPC { super.finalizeDeath(killer); if (killer instanceof Player) { final Player p = ((Player) killer); - if (p.getQuestRepository().getQuest("Witch's Potion").isStarted(p)) { + if (p.getQuestRepository().getQuest(Quests.WITCHS_POTION).isStarted(p)) { GroundItemManager.create(RAT_TAIL, getLocation(), p); } } diff --git a/Server/src/main/content/global/handlers/npc/SheepBehavior.kt b/Server/src/main/content/global/handlers/npc/SheepBehavior.kt index d9767f8a4..b329d4622 100644 --- a/Server/src/main/content/global/handlers/npc/SheepBehavior.kt +++ b/Server/src/main/content/global/handlers/npc/SheepBehavior.kt @@ -17,6 +17,7 @@ import org.rs09.consts.NPCs import org.rs09.consts.Sounds import core.game.world.map.Location import core.game.world.map.Direction +import content.data.Quests private val sheepIds = intArrayOf( NPCs.SHEEP_42, @@ -74,7 +75,7 @@ class SheepBehavior : NPCBehavior(*sheepIds), InteractionListener { val sheep = node as NPC sheep.faceTemporary(player, 1) if (sheep.id == NPCs.SHEEP_3579) { - if (player.questRepository.getQuest("Sheep Shearer").isStarted(player)) { + if (player.questRepository.getQuest(Quests.SHEEP_SHEARER).isStarted(player)) { setAttribute(player, ATTR_IS_PENGUIN_SHEEP_SHEARED, true) } animate(player, Animation(893)) diff --git a/Server/src/main/content/global/skill/agility/shortcuts/BarSqueezeShortcut.java b/Server/src/main/content/global/skill/agility/shortcuts/BarSqueezeShortcut.java index 2321706b1..efe0f727f 100644 --- a/Server/src/main/content/global/skill/agility/shortcuts/BarSqueezeShortcut.java +++ b/Server/src/main/content/global/skill/agility/shortcuts/BarSqueezeShortcut.java @@ -9,6 +9,7 @@ import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Handles the bar squeezing shortcut. @@ -61,7 +62,7 @@ public class BarSqueezeShortcut extends AgilityShortcut { @Override public boolean checkRequirements(Player player) { - if (!player.getQuestRepository().isComplete("Priest in Peril") && !(player.getLocation().getY() >= 3159 && player.getLocation().getY() <= 3161)) { + if (!player.getQuestRepository().isComplete(Quests.PRIEST_IN_PERIL) && !(player.getLocation().getY() >= 3159 && player.getLocation().getY() <= 3161)) { player.getDialogueInterpreter().sendDialogue("You need to have completed Priest in Peril in order to do this."); return false; } diff --git a/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java b/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java index 7388fde01..42cf77e34 100644 --- a/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java +++ b/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java @@ -15,6 +15,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles a tunnel shortcut. @@ -73,7 +74,7 @@ public class TunnelShortcut extends AgilityShortcut { @Override public void run(final Player player, Scenery object, String option, boolean failed) { if (object.getId() == 14922) { - if (!hasRequirement(player, "Swan Song")) + if (!hasRequirement(player, Quests.SWAN_SONG)) return; } player.lock(6); diff --git a/Server/src/main/content/global/skill/construction/CrestType.java b/Server/src/main/content/global/skill/construction/CrestType.java index f54466772..277c77231 100644 --- a/Server/src/main/content/global/skill/construction/CrestType.java +++ b/Server/src/main/content/global/skill/construction/CrestType.java @@ -3,6 +3,7 @@ package content.global.skill.construction; import core.game.node.entity.player.Player; import org.rs09.consts.Items; import core.game.node.entity.skill.Skills; +import content.data.Quests; /** * Family crest types. @@ -16,7 +17,7 @@ public enum CrestType implements CrestRequirement { @Override public boolean eligible(Player player) { - return player.getQuestRepository().isComplete("Shield of Arrav"); + return player.getQuestRepository().isComplete(Quests.SHIELD_OF_ARRAV); } }, ASGARNIA("the symbol of Asgarnia"), // no requirements @@ -24,21 +25,21 @@ public enum CrestType implements CrestRequirement { @Override public boolean eligible(Player player) { - return player.getQuestRepository().isComplete("The Lost Tribe"); + return player.getQuestRepository().isComplete(Quests.THE_LOST_TRIBE); } }, DRAGON("a dragon") { // requires Dragon Slayer @Override public boolean eligible(Player player) { - return player.getQuestRepository().isComplete("Dragon Slayer"); + return player.getQuestRepository().isComplete(Quests.DRAGON_SLAYER); } }, FAIRY("a fairy") { // requries Lost City @Override public boolean eligible(Player player) { - return player.getQuestRepository().isComplete("Lost City"); + return player.getQuestRepository().isComplete(Quests.LOST_CITY); } }, GUTHIX("the symbol of Guthix") { // Requires 70+ Prayer diff --git a/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java b/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java index f081bed5a..c7998375a 100644 --- a/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java +++ b/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java @@ -16,6 +16,7 @@ import org.rs09.consts.Items; import org.rs09.consts.Sounds; import static core.api.ContentAPIKt.playAudio; +import content.data.Quests; public class StandardCookingPulse extends Pulse { //range animation @@ -72,7 +73,7 @@ public class StandardCookingPulse extends Pulse { this.experience = 0; if (properties != null) { // Handle Cook's Assistant range - if (object.getId() == LUMBRIDGE_RANGE && !player.getQuestRepository().isComplete("Cook's Assistant")) { + if (object.getId() == LUMBRIDGE_RANGE && !player.getQuestRepository().isComplete(Quests.COOKS_ASSISTANT)) { player.getPacketDispatch().sendMessage("You need to have completed the Cook's Assistant quest in order to use that range."); return false; } diff --git a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt index 497abcad9..6dac10dce 100644 --- a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt +++ b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt @@ -12,6 +12,7 @@ import core.game.interaction.QueueStrength import core.tools.StringUtils import core.tools.prependArticle import org.rs09.consts.Sounds +import content.data.Quests class UseWithPatchHandler : InteractionListener { val RAKE = Items.RAKE_5341 @@ -39,7 +40,7 @@ class UseWithPatchHandler : InteractionListener { val usedItem = used.asItem() if (patch == FarmingPatch.TROLL_STRONGHOLD_HERB) { - if (!hasRequirement(player, "My Arm's Big Adventure")) + if (!hasRequirement(player, Quests.MY_ARMS_BIG_ADVENTURE)) return@onUseWith true } diff --git a/Server/src/main/content/global/skill/fletching/FletchingPulse.java b/Server/src/main/content/global/skill/fletching/FletchingPulse.java index 9c7d0d638..218601b97 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingPulse.java +++ b/Server/src/main/content/global/skill/fletching/FletchingPulse.java @@ -9,6 +9,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import core.game.world.update.flag.context.Animation; import core.tools.StringUtils; +import content.data.Quests; /** * fletching skill pulse @@ -57,7 +58,7 @@ public final class FletchingPulse extends SkillPulse { amount = player.getInventory().getAmount(node); } if (fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT) { - if (player.getQuestRepository().getQuest("Big Chompy Bird Hunting").getStage(player) == 0) { + if (player.getQuestRepository().getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING).getStage(player) == 0) { player.getPacketDispatch().sendMessage("You must have started Big Chompy Bird Hunting to make those."); return false; } diff --git a/Server/src/main/content/global/skill/fletching/items/darts/DartPulse.java b/Server/src/main/content/global/skill/fletching/items/darts/DartPulse.java index 6f21ba8d7..d65fac185 100644 --- a/Server/src/main/content/global/skill/fletching/items/darts/DartPulse.java +++ b/Server/src/main/content/global/skill/fletching/items/darts/DartPulse.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the dart pulse. @@ -46,7 +47,7 @@ public final class DartPulse extends SkillPulse { player.getDialogueInterpreter().sendDialogue("You need a fletching level of " + dart.level + " to do this."); return false; } - if (!player.getQuestRepository().isComplete("The Tourist Trap")){ + if (!player.getQuestRepository().isComplete(Quests.THE_TOURIST_TRAP)){ player.getDialogueInterpreter().sendDialogue("You need to have completed Tourist Trap to fletch darts."); return false; } diff --git a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt index 7ba8cfe5a..6807e5d9e 100644 --- a/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt +++ b/Server/src/main/content/global/skill/herblore/HerbCleanListener.kt @@ -6,6 +6,7 @@ import core.game.interaction.InteractionListener import core.game.node.entity.skill.Skills import core.game.node.item.Item import java.util.* +import content.data.Quests /** * Dirty herb cleaning listener @@ -15,7 +16,7 @@ class HerbCleanListener : InteractionListener { override fun defineListeners() { on(IntType.ITEM, "clean") { player, node -> lock(player, 1) - if (!requireQuest(player, "Druidic Ritual", "before you can use Herblore.")) return@on true + if (!requireQuest(player, Quests.DRUIDIC_RITUAL, "before you can use Herblore.")) return@on true val herb: Herbs = Herbs.forItem(node as Item) ?: return@on true if (getDynLevel(player, Skills.HERBLORE) < herb.level) { diff --git a/Server/src/main/content/global/skill/herblore/HerbTarPulse.java b/Server/src/main/content/global/skill/herblore/HerbTarPulse.java index 45793be82..247f69f62 100644 --- a/Server/src/main/content/global/skill/herblore/HerbTarPulse.java +++ b/Server/src/main/content/global/skill/herblore/HerbTarPulse.java @@ -5,6 +5,7 @@ import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; import core.game.node.item.Item; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the pulse used to create herb tars. @@ -52,7 +53,7 @@ public final class HerbTarPulse extends SkillPulse { @Override public boolean checkRequirements() { - if (!player.getQuestRepository().isComplete("Druidic Ritual")) { + if (!player.getQuestRepository().isComplete(Quests.DRUIDIC_RITUAL)) { player.getPacketDispatch().sendMessage("You must complete the Druidic Ritual quest before you can use Herblore."); return false; } diff --git a/Server/src/main/content/global/skill/herblore/HerblorePulse.java b/Server/src/main/content/global/skill/herblore/HerblorePulse.java index fbf1a8c73..0f859ad23 100644 --- a/Server/src/main/content/global/skill/herblore/HerblorePulse.java +++ b/Server/src/main/content/global/skill/herblore/HerblorePulse.java @@ -12,6 +12,7 @@ import core.tools.RandomFunction; import org.rs09.consts.Sounds; import static core.api.ContentAPIKt.playAudio; +import content.data.Quests; /** @@ -69,7 +70,7 @@ public final class HerblorePulse extends SkillPulse { @Override public boolean checkRequirements() { - if (!player.getQuestRepository().isComplete("Druidic Ritual")) { + if (!player.getQuestRepository().isComplete(Quests.DRUIDIC_RITUAL)) { player.getPacketDispatch().sendMessage("You must complete the Druidic Ritual quest before you can use Herblore."); return false; } diff --git a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt index 554dcab4f..eb4e61fc5 100644 --- a/Server/src/main/content/global/skill/magic/MagicAltarListener.kt +++ b/Server/src/main/content/global/skill/magic/MagicAltarListener.kt @@ -9,6 +9,7 @@ import core.game.node.entity.player.link.SpellBookManager.SpellBook import core.game.node.entity.skill.Skills import org.rs09.consts.Scenery import org.rs09.consts.Sounds +import content.data.Quests class MagicAltarListener : InteractionListener { override fun defineListeners() { @@ -24,7 +25,7 @@ class MagicAltarListener : InteractionListener { private fun meetsRequirements(player: Player, altar: Node): Boolean { val level = if (altar.id == ANCIENT_ALTAR) 50 else 65 - if (!hasRequirement(player, if (altar.id == ANCIENT_ALTAR) "Desert Treasure" else "Lunar Diplomacy")) { + if (!hasRequirement(player, if (altar.id == ANCIENT_ALTAR) Quests.DESERT_TREASURE else Quests.LUNAR_DIPLOMACY)) { return false } diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 262824d2c..1ae76e091 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -29,6 +29,7 @@ import core.game.world.update.flag.context.Graphics import org.rs09.consts.Items import org.rs09.consts.Scenery import org.rs09.consts.Sounds +import content.data.Quests class ModernListeners : SpellListener("modern"){ override fun defineListeners() { @@ -65,28 +66,28 @@ class ModernListeners : SpellListener("modern"){ } onCast(Modern.ARDOUGNE_TELEPORT, NONE){ player, _ -> - if (!hasRequirement(player, "Plague City")) + if (!hasRequirement(player, Quests.PLAGUE_CITY)) return@onCast requires(player,51, arrayOf(Item(Items.WATER_RUNE_555,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,61.0, Location.create(2662, 3307, 0)) } onCast(Modern.WATCHTOWER_TELEPORT, NONE){ player, _ -> - if (!hasRequirement(player, "Watchtower")) + if (!hasRequirement(player, Quests.WATCHTOWER)) return@onCast requires(player,58, arrayOf(Item(Items.EARTH_RUNE_557,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,68.0, Location.create(2549, 3112, 0)) } onCast(Modern.TROLLHEIM_TELEPORT, NONE){ player, _ -> - if (!hasRequirement(player, "Eadgar's Ruse")) + if (!hasRequirement(player, Quests.EADGARS_RUSE)) return@onCast requires(player,61, arrayOf(Item(Items.FIRE_RUNE_554,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,68.0, Location.create(2891, 3678, 0)) } onCast(Modern.APE_ATOLL_TELEPORT, NONE){ player, _ -> - if (!hasRequirement(player, "Monkey Madness")) + if (!hasRequirement(player, Quests.MONKEY_MADNESS)) return@onCast requires(player,64, arrayOf(Item(Items.FIRE_RUNE_554,2),Item(Items.WATER_RUNE_555,2),Item(Items.LAW_RUNE_563,2),Item(Items.BANANA_1963))) sendTeleport(player,74.0, Location.create(2754, 2784, 0)) diff --git a/Server/src/main/content/global/skill/prayer/PrayerAltarListener.kt b/Server/src/main/content/global/skill/prayer/PrayerAltarListener.kt index 8ca2c7467..71982f578 100644 --- a/Server/src/main/content/global/skill/prayer/PrayerAltarListener.kt +++ b/Server/src/main/content/global/skill/prayer/PrayerAltarListener.kt @@ -12,11 +12,12 @@ import core.game.node.entity.skill.Skills import core.game.world.map.Location import org.rs09.consts.Scenery import org.rs09.consts.Sounds +import content.data.Quests class PrayerAltarListener : InteractionListener { override fun defineListeners() { on(altars, IntType.SCENERY, "pray", "pray-at") { player, node -> - if (node.id == Scenery.TRIBAL_STATUE_3863 && !hasRequirement(player, "Tai Bwo Wannai Trio")) { + if (node.id == Scenery.TRIBAL_STATUE_3863 && !hasRequirement(player, Quests.TAI_BWO_WANNAI_TRIO)) { // https://runescape.wiki/w/Tribal_Statue?oldid=1940922 return@on true } @@ -43,9 +44,9 @@ class PrayerAltarListener : InteractionListener { } on(Scenery.CHAOS_ALTAR_61, IntType.SCENERY, "check") { player, _ -> - if (getQuestStage(player, "Merlin's Crystal") == 70) { + if (getQuestStage(player, Quests.MERLINS_CRYSTAL) == 70) { sendDialogue(player, "You find a small inscription at the bottom of the altar. It reads: 'Snarthon Candtrick Termanto'.") - setQuestStage(player, "Merlin's Crystal", 80) + setQuestStage(player, Quests.MERLINS_CRYSTAL, 80) } else { sendMessage(player, "An altar of the evil god Zamorak.") } diff --git a/Server/src/main/content/global/skill/runecrafting/Altar.java b/Server/src/main/content/global/skill/runecrafting/Altar.java index 8be433efc..487d61e6f 100644 --- a/Server/src/main/content/global/skill/runecrafting/Altar.java +++ b/Server/src/main/content/global/skill/runecrafting/Altar.java @@ -5,6 +5,7 @@ import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Represents an altar an it's relative information(corresponding ruin, etc) @@ -72,15 +73,15 @@ public enum Altar { */ public void enterRift(Player player) { if (this == ASTRAL) { - if (!hasRequirement(player, "Lunar Diplomacy")) + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return; } if (this == DEATH) { - if (!hasRequirement(player, "Mourning's End Part II")) + if (!hasRequirement(player, Quests.MOURNINGS_END_PART_II)) return; } if (this == BLOOD) { - if (!hasRequirement(player, "Legacy of Seergaze")) + if (!hasRequirement(player, Quests.LEGACY_OF_SEERGAZE)) return; } if (this == LAW) { @@ -89,7 +90,7 @@ public enum Altar { return; } } - if (this == COSMIC && !player.getQuestRepository().isComplete("Lost City")) { + if (this == COSMIC && !player.getQuestRepository().isComplete(Quests.LOST_CITY)) { player.getPacketDispatch().sendMessage("You need to have completed the Lost City quest in order to do that."); return; } diff --git a/Server/src/main/content/global/skill/runecrafting/MysteriousRuinListener.kt b/Server/src/main/content/global/skill/runecrafting/MysteriousRuinListener.kt index 68fcf10c7..7bf55dd7f 100644 --- a/Server/src/main/content/global/skill/runecrafting/MysteriousRuinListener.kt +++ b/Server/src/main/content/global/skill/runecrafting/MysteriousRuinListener.kt @@ -1,5 +1,6 @@ package content.global.skill.runecrafting +import content.data.Quests import content.region.misthalin.varrock.diary.VarrockAchivementDiary.Companion.EasyTasks.ENTER_EARTH_ALTAR import core.api.* import core.game.container.impl.EquipmentContainer.SLOT_HAT @@ -19,7 +20,7 @@ class MysteriousRuinListener : InteractionListener { private val animation = Animation(827) private val allowedUsed = arrayOf(1438, 1448, 1444, 1440, 1442, 5516, 1446, 1454, 1452, 1462, 1458, 1456, 1450, 1460).toIntArray() private val allowedWith = allRuins() - private val nothingInteresting = "Nothing interesting happens" + private val nothingInteresting = "Nothing interesting happens." override fun defineListeners() { onUseWith(IntType.SCENERY, allowedUsed, *allowedWith) { player, used, with -> @@ -76,9 +77,9 @@ class MysteriousRuinListener : InteractionListener { private fun checkQuestCompletion(player: Player, ruin: MysteriousRuin): Boolean { return when (ruin) { - MysteriousRuin.DEATH -> hasRequirement(player, QuestReq(MEP_2), true) - MysteriousRuin.BLOOD -> hasRequirement(player, QuestReq(SEERGAZE), true) - else -> hasRequirement(player, QuestReq(RUNE_MYSTERIES), true) + MysteriousRuin.DEATH -> hasRequirement(player, Quests.MOURNINGS_END_PART_II, true) + MysteriousRuin.BLOOD -> hasRequirement(player, Quests.LEGACY_OF_SEERGAZE, true) + else -> hasRequirement(player, Quests.RUNE_MYSTERIES, true) } } @@ -102,4 +103,4 @@ class MysteriousRuinListener : InteractionListener { }) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 62c8b5efc..c9fa23ef5 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -24,6 +24,7 @@ import org.rs09.consts.Sounds; import java.util.ArrayList; import java.util.Arrays; +import content.data.Quests; /** * A class used to craft runes. @@ -102,15 +103,15 @@ public final class RuneCraftPulse extends SkillPulse { @Override public boolean checkRequirements() { if (altar == Altar.ASTRAL) { - if (!hasRequirement(player, "Lunar Diplomacy")) + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return false; } if (altar == Altar.DEATH) { - if (!hasRequirement(player, "Mourning's End Part II")) + if (!hasRequirement(player, Quests.MOURNINGS_END_PART_II)) return false; } if (altar == Altar.BLOOD) { - if (!hasRequirement(player, "Legacy of Seergaze")) + if (!hasRequirement(player, Quests.LEGACY_OF_SEERGAZE)) return false; } if (!altar.isOurania() && getDynLevel(player, Skills.RUNECRAFTING) < rune.getLevel()) { diff --git a/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java b/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java index 6bb69109f..954948eaf 100644 --- a/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java +++ b/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java @@ -24,6 +24,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles runecraftign related options. @@ -52,7 +53,7 @@ public class RunecraftingPlugin extends OptionHandler { @Override public boolean handle(final Player player, Node node, String option) { - if (!player.getQuestRepository().isComplete("Rune Mysteries") && player.getDetails().getRights() != Rights.ADMINISTRATOR) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES) && player.getDetails().getRights() != Rights.ADMINISTRATOR) { player.getPacketDispatch().sendMessage("You need to finish the Rune Mysteries Quest in order to do this."); return true; } @@ -97,7 +98,7 @@ public class RunecraftingPlugin extends OptionHandler { } Altar a = Altar.forObject(((Scenery) node)); if (a == Altar.ASTRAL) { - if (!hasRequirement(player, "Lunar Diplomacy")) + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return true; } player.getPulseManager().run(new RuneCraftPulse(player, null, a, false, null)); diff --git a/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java b/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java index dab5eee1d..ab06e4843 100644 --- a/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java +++ b/Server/src/main/content/global/skill/runecrafting/abyss/ZamorakMageDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -51,7 +52,7 @@ public final class ZamorakMageDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; varrockMage = npc.getId() == 2261 || npc.getId() == 2260; - if (!player.getQuestRepository().isComplete("Rune Mysteries")) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES)) { end(); player.sendMessage("The mage doesn't seem interested in talking to you."); return true; diff --git a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt index 7ee273098..5c5cb0bf3 100644 --- a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt @@ -16,6 +16,7 @@ import core.ServerStore.Companion.getInt import core.api.* import core.cache.def.impl.ItemDefinition import org.rs09.consts.Items +import content.data.Quests enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? = null) { BAREFISTED_SMITHING("cape_perks:barefisted-smithing"), @@ -195,11 +196,11 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? end() if(spellbook != null){ if (spellbook == SpellBookManager.SpellBook.ANCIENT) { - if (!hasRequirement(player, "Desert Treasure")) + if (!hasRequirement(player, Quests.DESERT_TREASURE)) return true } else if (spellbook == SpellBookManager.SpellBook.LUNAR) { - if (!hasRequirement(player, "Lunar Diplomacy")) + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return true } player.spellBookManager.setSpellBook(spellbook) @@ -260,9 +261,9 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? fun sendAltar(player: Player,altar: Altar){ end() - if (altar == Altar.DEATH && !hasRequirement(player, "Mourning's End Part II")) return - if (altar == Altar.ASTRAL && !hasRequirement(player, "Lunar Diplomacy")) return - if (altar == Altar.BLOOD && !hasRequirement(player, "Legacy of Seergaze")) return + if (altar == Altar.DEATH && !hasRequirement(player, Quests.MOURNINGS_END_PART_II)) return + if (altar == Altar.ASTRAL && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return + if (altar == Altar.BLOOD && !hasRequirement(player, Quests.LEGACY_OF_SEERGAZE)) return if (altar == Altar.LAW && !ItemDefinition.canEnterEntrana(player)) { sendItemDialogue(player, Items.SARADOMIN_SYMBOL_8055, "No weapons or armour are permitted on holy Entrana.") return diff --git a/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java b/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java index 128d6cc00..cb6aa6570 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java +++ b/Server/src/main/content/global/skill/slayer/SlayerMasterDialogue.java @@ -17,6 +17,7 @@ import core.plugin.Initializable; import static core.tools.DialogueConstKt.END_DIALOGUE; +import content.data.Quests; /** * Represents the dialogue plugin used for a slayer master. @@ -99,7 +100,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin { npc = (NPC) args[0]; } master = Master.forId(args[0] instanceof NPC ? ((NPC) args[0]).getId() : (int) args[0]); - quest = player.getQuestRepository().getQuest("Animal Magnetism"); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); if (master == Master.DURADEL) { if (Skillcape.isMaster(player, Skills.SLAYER)) { diff --git a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java index 35d6a4544..4e93e4fe0 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java +++ b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java @@ -12,6 +12,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles related slayer nodes. @@ -63,7 +64,7 @@ public class SlayerPlugin extends OptionHandler { player.teleport(new Location(2729, 3733, 0)); break; case 15767: - if (!hasRequirement(player, "Cabin Fever")) + if (!hasRequirement(player, Quests.CABIN_FEVER)) return true; player.teleport(new Location(3748, 9373, 0)); break; diff --git a/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java b/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java index 84d54b18d..247e87b82 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java +++ b/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java @@ -17,6 +17,7 @@ import core.plugin.Plugin; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the slayer reward interface plugin. @@ -309,7 +310,7 @@ public class SlayerRewardPlugin extends ComponentPlugin { @Override public boolean handle(Player player, Node node, String option) { - if (!hasRequirement(player, "Smoking Kills")) + if (!hasRequirement(player, Quests.SMOKING_KILLS)) return true; openTab(player, BUY); return true; diff --git a/Server/src/main/content/global/skill/slayer/Tasks.java b/Server/src/main/content/global/skill/slayer/Tasks.java index f2c459776..81a195f5a 100644 --- a/Server/src/main/content/global/skill/slayer/Tasks.java +++ b/Server/src/main/content/global/skill/slayer/Tasks.java @@ -8,6 +8,7 @@ import java.util.HashMap; import core.game.node.entity.player.Player; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * A non-garbage way of representing tasks @@ -30,34 +31,34 @@ public enum Tasks { BLACK_DRAGONS(80, new int[] {54, 4673, 4674, 4675, 4676, 3376, 50 }, new String[] { "Black dragons are the strongest dragons;", "watch out for their fiery breath." }, 1, false, true), BLOODVELDS(50, new int[] { 1618, 1619, 6215, 7643, 7642 }, new String[] { "Bloodvelds are strange demonic creatures, they use their", "long rasping tongue to feed on just about", "anything they can find." }, 50, false, false), BLUE_DRAGONS(65, new int[] { 55, 4681, 4682, 4683, 4684, 5178, 52, 4665, 4666, }, new String[] { "Blue dragons aren't as strong as other dragons but they're", "still very powerful, watch out for their fiery breath." }, 1, false, true), - BRINE_RATS(45, new int[] { 3707 }, new String[] { "Brine rats can be found in caves that are near the", "sea. They are hairless, bad-tempered and generally", "unfriendly." }, 47, "Olaf's Quest"), + BRINE_RATS(45, new int[] { 3707 }, new String[] { "Brine rats can be found in caves that are near the", "sea. They are hairless, bad-tempered and generally", "unfriendly." }, 47, Quests.OLAFS_QUEST), BRONZE_DRAGONS(75, new int[] { 1590 }, new String[] { "Bronze Dragons are the weakest of the metallic", "dragons, their bronze scales are far thicker than", "normal bronze armour." }, 1, false, true), CATABLEPONS(35, new int[] { 4397, 4398, 4399, }, new String[] { "Catablepon are mythical, cow like, magical creatures", "Beware their weakening glare." }, 1, false, false), CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "Cave Bugs are like Cave Crawlers, except smaller and", "easier to squish, though they still have a fondness", "for plants." }, 7, false, false), CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "Cave Crawlers are small and fast, often hiding in", "ambush. Avoid their barbed tongue or you'll", "get poisoned." }, 10, false, false), - CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "Cave Horrors can be found under Mos Le'Harmless. You", "will need a Witchwood Icon to fight them effectively." }, 58, "Cabin Fever"), + CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "Cave Horrors can be found under Mos Le'Harmless. You", "will need a Witchwood Icon to fight them effectively." }, 58, Quests.CABIN_FEVER), CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "Cave Slimes are the lesser cousins of Jellies, though", "don't be fooled they can still be dangerous as", "they're often poisonous." }, 17, false, false), COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "Cockatrice, like Basilisks, have a gaze which will", "paralyse and harm their prey. You'll need a Mirror", "Shield to protect you." }, 25, false, false), COWS(5, new int[] { 81, 1766, 1768, 2310, 397, 955, 1767, 3309 }, new String[] { "Cows are bigger than you, so they'll often hit fairly", "hard but are usually fairly slow to react." }, 1, false, false), CRAWLING_HAND(1,new int[] { 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 4226, 7640, 7641 }, new String[] { "Crawling Hands are undead severed hands, fast and", "dexterous they claw their victims." }, 5, true, false), CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles are large reptiles which live near water.", "You'll want to have a stabbing weapon handy for", "puncturing their thick scaly hides." }, 1, false, false), - DAGANNOTHS(75, new int[] { 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 2454, 2455, 2456, 2881, 2882, 2883, 2887, 2888, 3591, }, new String[] { "Dagannoth are large sea dwelling creatures which are", "very aggressive. You'll often find them in caves", "near sea water." }, 1, "Horror from the Deep"), - DARK_BEASTS(90, new int[] { 2783 }, new String[] { "Dark Beasts are large, dog-like predators.", "Their massively muscled bodies protect", "them from crushing weapons." }, 90, "Mourning's Ends Part II"), + DAGANNOTHS(75, new int[] { 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 2454, 2455, 2456, 2881, 2882, 2883, 2887, 2888, 3591, }, new String[] { "Dagannoth are large sea dwelling creatures which are", "very aggressive. You'll often find them in caves", "near sea water." }, 1, Quests.HORROR_FROM_THE_DEEP), + DARK_BEASTS(90, new int[] { 2783 }, new String[] { "Dark Beasts are large, dog-like predators.", "Their massively muscled bodies protect", "them from crushing weapons." }, 90, Quests.MOURNINGS_END_PART_II), DESERT_LIZARDS(15, new int[] { 2803, 2804, 2805, 2806, 2807, 2808 }, new String[] { "Lizards are large reptiles with tough skin. Those", "found in the desert will need you to douse them with", "freezing water to finish them off after a tough battle." }, 22, false, false), DOG(15, new int[] { 99, 3582, 1994, 1593, 1594, 3582 }, new String[] { "Dogs are much like Wolves, they are", "pack creatures which will hunt in groups." }, 1, false, false), DUST_DEVILS(70, new int[] { 1624 }, new String[] { "Dust Devils use clouds of dust, sand, ash and whatever", "else they can inhale to blind and disorientate", "their victims." }, 65, false, false), DWARF(6, new int[] { 118, 120, 121, 382, 3219, 3220, 3221, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3294, 3295, 4316, 5880, 5881, 5882, 5883, 5884, 5885, 2130, 2131, 2132, 2133, 3276, 3277, 3278, 3279, 119, 2423 }, new String[] { "Dwarves are a small but tough race of miners, often", "using pickaxes to pierce their opponents armour." }, 1, false, false), EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "Earth Warriors are a kind of earth elemental,", "grind them to dust with blunt weapons." }, 1, false, false), - ELVES(70, new int[] { 1183, 1184, 2359, 2360, 2361, 2362, 2373, 7438, 7439, 7440, 7441 }, new String[]{ "Elves are quick, agile, and vicious fighters which", "often favour bows and polearms."}, 1, "Regicide"), + ELVES(70, new int[] { 1183, 1184, 2359, 2360, 2361, 2362, 2373, 7438, 7439, 7440, 7441 }, new String[]{ "Elves are quick, agile, and vicious fighters which", "often favour bows and polearms."}, 1, Quests.REGICIDE), // Waiting for either Rum Deal or Pirate Pete and Fever Spiders before adding this assignment - FEVER_SPIDER(1, new int[] { 2850 }, new String[] { "Fever Spiders are giant spiders that carry the deadly", "Spider Fever. If you don't want to catch it I suggest", "you wear Slayer Gloves to fight them." }, 42, "Rum Deal"), + FEVER_SPIDER(1, new int[] { 2850 }, new String[] { "Fever Spiders are giant spiders that carry the deadly", "Spider Fever. If you don't want to catch it I suggest", "you wear Slayer Gloves to fight them." }, 42, Quests.RUM_DEAL), FIRE_GIANTS(65, new int[] { 110, 1582, 1583, 1584, 1585, 1586, 7003, 7004 }, new String[] { "Like other giants, Fire Giants often wield large weapons", "learn to recognise what kind of weapon it is,", "and act accordingly." }, 1, false, false), FLESH_CRAWLERS(15, new int[] { 4389, 4390, 4391 }, new String[] { "Flesh Crawlers are scavengers and will eat you - and", "anyone else, given the chance." }, 1, false, false), GARGOYLES(80, new int[] { 1610, 6389 }, new String[] { "Gargoyles are winged creatures of stone. You'll need", "to fight them to near death before breaking them apart", "with a rock hammer." }, 75, false, false), GHOSTS(13, new int[] { 103, 104, 491, 1541, 1549, 2716, 2931, 4387, 388, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 1698, 5349, 5350, 5351, 5352, 5369, 5370, 5371, 5372, 5373, 5374, 5572, 6094, 6095, 6096, 6097, 6098, 6504, 13645, 13466, 13467, 13468, 13469, 13470, 13471, 13472, 13473, 13474, 13475, 13476, 13477, 13478, 13479, 13480, 13481 }, new String[] { "Ghosts are undead so magic is your best bet against", "them, there is even a spell specially for fighting", "the undead." }, 1, true, false), GHOULS(25, new int[] { 1218, 3059 }, new String[] { "Ghouls aren't undead but they are stronger and", "tougher than they look. However they're also very", "cowardly and will run if they're losing a fight." }, 1, false, false), GOBLINS(1, new int[] { 100, 101, 102, 444, 445, 489, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2678, 2679, 2680, 2681, 3060, 3264, 3265, 3266, 3267, 3413, 3414, 3415, 3726, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4407, 4408, 4409, 4410, 4411, 4412, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4499, 4633, 4634, 4635, 4636, 4637, 5786, 5824, 5855, 5856, 6125, 6126, 6132, 6133, 6279, 6280, 6281, 6282, 6283, 6402, 6403, 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497 }, new String[] { "Goblins are mostly just annoying, but they can be vicious.", "Watch out for the spears they sometimes carry." }, 1, false, false), - GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks are extremely aggressive creatures. They have", "been imprisoned on an alternative plane, which is", "only accessible by using the fairyrings. Be extremely", "careful, their touch drains health as well as skills!" }, 1, "A Fairy Tale I - Growing Pains"), + GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks are extremely aggressive creatures. They have", "been imprisoned on an alternative plane, which is", "only accessible by using the fairyrings. Be extremely", "careful, their touch drains health as well as skills!" }, 1, Quests.FAIRYTALE_I_GROWING_PAINS), GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6204 }, new String[] { "Greater Demons are magic creatures so they are weak", "to magical attacks. Though not the strongest demon,", "they are still dangerous." }, 1, false, false), GREEN_DRAGONS(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362, 742 }, new String[] { "Green Dragons are the weakest dragon but still very", "powerful, watch out for their fiery breath." }, 1, false, true), HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are pesky critters that are hard to", "hit. You need a lit bug lantern to distract them with", "its hypnotic light." }, 33, false, false), @@ -70,21 +71,21 @@ public enum Tasks { INFERNAL_MAGES(40, new int[] { 1643, 1644, 1645, 1646, 1647 }, new String[] { "Infernal Mages are dangerous spell users, beware of", "their magic spells and go properly prepared" }, 45, false, false), IRON_DRAGONS(80, new int[] { 1591 }, new String[] { "Iron Dragons are some of the weaker metallic dragons,", "their iron scales are far thicker than normal", "iron armour." }, 1, false, true), JELLIES(57, new int[] { 1637, 1638, 1639, 1640, 1641, 1642 }, new String[] { "Jellies are nasty cube-like gelatinous creatures which", "absorb everything they come across into themselves." }, 52, false, false), - JUNGLE_HORRORS(65, new int[] { 4348, 4349, 4350, 4351, 4352 }, new String[] { "Jungle Horrors can be found all over Mos Le'Harmless.", "They are strong and aggressive, so watch out!" }, 1, "Cabin Fever"), + JUNGLE_HORRORS(65, new int[] { 4348, 4349, 4350, 4351, 4352 }, new String[] { "Jungle Horrors can be found all over Mos Le'Harmless.", "They are strong and aggressive, so watch out!" }, 1, Quests.CABIN_FEVER), KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1159, 1160, 1161 }, new String[] { "Kalphites are large insects which live in great hives", "under the desert sands." }, 1, false, false), // Waiting for the killer watt plane to be implemented before adding to assignments - KILLERWATTS(1, new int[] { 3201 }, new String[] { "Killerwatts store huge amounts of energy in their", "bodies, which is released if they are touched. You'll", "need to wear heavily insulated boots to counter this", "shocking effect." }, 37, "Ernest the Chicken"), + KILLERWATTS(1, new int[] { 3201 }, new String[] { "Killerwatts store huge amounts of energy in their", "bodies, which is released if they are touched. You'll", "need to wear heavily insulated boots to counter this", "shocking effect." }, 37, Quests.ERNEST_THE_CHICKEN), KURASKS(65, new int[] { 1608, 1609, 4229, 7805, 7797 }, new String[] { "Kurasks are large brutal creatures with very thick", "hides. You'll need a Leaf-Tipped Spear Sword or", "Battle-axe, Broad Arrows, or a Magic Dart to harm them." }, 70, false, false), LESSER_DEMONS(60, new int[] { 82, 6203, 3064, 4694, 4695, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to", "magical attacks. Though they're relatively weak they", "are still dangerous." }, 1, false, false), MINOTAURS(7, new int[] { 4404, 4405, 4406 }, new String[] { "Minotaurs are large manlike creatures but you'll", "want to be careful of their horns." }, 1, false, false), MITHRIL_DRAGONS(60, new int[] { 5363 }, new String[] { "Mithril dragons are more vulnerable to magic and to", "stab-based melee attacks than to anything else." }, 1, false, true), MOGRES(1, new int[] { 114 }, new String[] { "Mogres are a type of aquatic Ogre that is", "often mistaken for a giant mudskipper. You have to force", "them out of the water with a fishing explosive." }, 32, false, false), // Waiting for molanisks transform to be implemented before adding this to assignments - MOLANISKS(1, new int[] { 5751 }, new String[] { "Molanisks are subterranean creatures. You can find", "them in caves deep below the ground. I heard that the", "goblins have recently had trouble with some, but they", "use a bell of some sort to deal with them."}, 39, "Death to the Dorgeshuun"), + MOLANISKS(1, new int[] { 5751 }, new String[] { "Molanisks are subterranean creatures. You can find", "them in caves deep below the ground. I heard that the", "goblins have recently had trouble with some, but they", "use a bell of some sort to deal with them."}, 39, Quests.DEATH_TO_THE_DORGESHUUN), MONKEYS(1, new int[] { 132, 1463, 1464, 2301, 4344, 4363, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 1455, 1459, 1460, 1456, 1457, 1458 }, new String[] { "Monkeys are tricky creatures, they are agile and", "fairly fast. Learn to anticipate their movements." }, 1, false, false), MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "Like other giants, Moss Giants often wield large", "weapons, learn to recognise what kind of weapon it is", "and act accordingly." }, 1, false, false), // Waiting for zygomite transform to be implemented before adding this to assignments - MUTATED_ZYGOMITES(1, new int[] { 3346, 3347 }, new String[] { "Mutated Zygomites are hard to destroy. They regenerate", "quickly so you will need to finish them with fungicide." }, 57, "Lost City"), + MUTATED_ZYGOMITES(1, new int[] { 3346, 3347 }, new String[] { "Mutated Zygomites are hard to destroy. They regenerate", "quickly so you will need to finish them with fungicide." }, 57, Quests.LOST_CITY), NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small", "winged beings to help them fight their victims." }, 80, false, false), OGRES(40, new int[] { 115, 374, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2060, 2801, 3419, 7078, 7079, 7080, 7081, 7082 }, new String[] { "Ogres are brutal creatures, favouring large blunt", "maces and clubs they often attack without warning." }, 1, false, false), OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "Otherworldly Beings are ethereal beings making them", "weak to magical attack." }, 1, false, false), @@ -92,22 +93,22 @@ public enum Tasks { RED_DRAGONS(1, new int[] { 53, 1589, 3588, 4667, 4668, 4669, 4670, 4671, 4672 }, new String[] { "Red Dragons are very powerful, stronger than most", "dragons, watch out for their fiery breath." }, 1, false, false), ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "Rockslugs are strange stoney slugs. You'll need to", "fight them to near death before finishing them off", "with Salt." }, 20, false, false), // Seems to need Contact or the NPCs added to dungeons before adding this assignment as a task - SCABARITES(1, new int[] { 2001, 4500, 5251, 5252, 5255, 5256, 5250, 5254, 6777, 6778, 6774, 6780, 6781, 6773 }, new String[] {"Scabarites are insectoid creatures, found beyond the", "Kharidian deserts. They can be extremely dangerous."}, 1, "Contact!"), + SCABARITES(1, new int[] { 2001, 4500, 5251, 5252, 5255, 5256, 5250, 5254, 6777, 6778, 6774, 6780, 6781, 6773 }, new String[] {"Scabarites are insectoid creatures, found beyond the", "Kharidian deserts. They can be extremely dangerous."}, 1, Quests.CONTACT), SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "Scorpions are almost always poisonous, their hard", "carapace makes them resistant to crushing and", "stabbing attacks." }, 1, false, false), - SEA_SNAKES(1, new int[] { 3939, 3940 }, new String[] { "Sea Snakes are long and slithery with a venomous bite.", "The larger ones are more poisonous, so keep an eye on", "your health." }, 1, "Royal Trouble"), + SEA_SNAKES(1, new int[] { 3939, 3940 }, new String[] { "Sea Snakes are long and slithery with a venomous bite.", "The larger ones are more poisonous, so keep an eye on", "your health." }, 1, Quests.ROYAL_TROUBLE), SHADE(30, new int[] { 3617, 1250, 1241, 1246, 1248, 1250, 428, 1240 }, new String[] { "Shades are undead so magic is your best best against", "them, you can find Shades at Mort'ton." }, 1, true, false), // Dungeon needs to be connected to the Legend's Guild before adding this assignment as a task - SHADOW_WARRIORS(1, new int[] { 158 }, new String[] { "Shadow Warriors are dark and mysterious, they hide in", "the shadows so be wary of ambushes." }, 1, "Legends' Quest"), + SHADOW_WARRIORS(1, new int[] { 158 }, new String[] { "Shadow Warriors are dark and mysterious, they hide in", "the shadows so be wary of ambushes." }, 1, Quests.LEGENDS_QUEST), SKELETAL_WYVERN(70, new int[] { 3068, 3069, 3070, 3071 }, new String[] { "Skeletal Wyverns are extremely dangerous and they are", "hard to hit with arrows as they slip right through.", "To stand a good chance of surviving you'll need some", "elemental shielding from its icy breath." }, 72, false, false), SKELETONS(15, new int[] { 90, 91, 92, 93, 94, 459, 1471, 1575, 1973, 2036, 2037, 2715, 2717, 3065, 3151, 3291, 3581, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3844, 3850, 3851, 4384, 4385, 4386, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5359, 5365, 5366, 5367, 5368, 5381, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5411, 5412, 5422, 6091, 6092, 6093, 6103, 6104, 6105, 6106, 6107, 6764, 6765, 6766, 6767, 6768, 2050, 2056, 2057, 1539, 7640 }, new String[] { "Skeletons are undead so magic is your best bet against", "them, there is even a spell specially for fighting the undead." }, 1, true, false), SPIDERS(1, new int[] { 61, 1004, 1221, 1473, 1474, 63, 4401, 2034, 977, 7207, 134, 1009, 59, 60, 4400, 58, 62, 1478, 2491, 2492, 6376, 6377, }, new String[] { "Spiders are often poisonous, and many varieties are", "camouflaged too." }, 1, false, false), - SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "Spiritual mages can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 83, "Death Plateau"), - SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "Spiritual rangers can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 63, "Death Plateau"), - SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "Spiritual warriors can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 68, "Death Plateau"), + SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "Spiritual mages can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 83, Quests.DEATH_PLATEAU), + SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "Spiritual rangers can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 63, Quests.DEATH_PLATEAU), + SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "Spiritual warriors can be found in the icy caverns near", "Trollheim, supporting the cause of their chosen god." }, 68, Quests.DEATH_PLATEAU), STEEL_DRAGONS( 85,new int[] { 1592, 3590 }, new String[] { "Steel dragons are dangerous and metallic, with steel", "scales that are far thicker than normal steel armour. As", "you are an accomplished slayer, I am sure you'll be", "able to deal with them easily."}, 1, false, true), - SUQAHS (65, new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] { "Suqahs can only be found on the mystical Lunar Isle.", "They are capable of melee and magic attacks and often", "drop hide, teeth and herbs!" }, 1, "Lunar Diplomacy"), + SUQAHS (65, new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] { "Suqahs can only be found on the mystical Lunar Isle.", "They are capable of melee and magic attacks and often", "drop hide, teeth and herbs!" }, 1, Quests.LUNAR_DIPLOMACY), // No access to Lair of Tarn Razorlor but this should be added as a task when there is access - TERROR_DOGS(1, new int[] { 5417, 5418 }, new String[] { "Terror dogs are the personal pets of Tarn Razorlor.", "Wherever you find him, you will find them. They are", "bad-tempered and generally unfriendly." }, 40, "Haunted Mine"), + TERROR_DOGS(1, new int[] { 5417, 5418 }, new String[] { "Terror dogs are the personal pets of Tarn Razorlor.", "Wherever you find him, you will find them. They are", "bad-tempered and generally unfriendly." }, 40, Quests.HAUNTED_MINE), 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, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 391, 392, 393, 394, 395, 396}, new String[] { "Trolls regenerate damage quickly but are still", "vulnerable to poisons, they usually use crushing", "weapons." }, 1, false, false), TUROTHS(60, new int[] { 1622, 1611, 1623, 1626, 1627, 1628, 1629, 1630, 7800}, new String[] { "Turoth are large vicious creatures with thick hides.", "You'll need a Leaf-Tipped Spear Sword or Battle-axe,", "Broad Arrows, or a Magic Dart to harm them." }, 55, false, false), VAMPIRES(35, new int[] { 1220, 1223, 1225, 6214 }, new String[] { "Vampires are extremely powerful beings. They feed on", "the blood of the living so watch out you don't", "get bitten." }, 1, false, false), @@ -117,8 +118,8 @@ public enum Tasks { // If a grapple is implemented from W Castle Wars to E Posion Swamps // The dungeon connected and populated // then these could be added as a task - WARPED_TERROR_BIRD(1, new int[] { 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6608 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, "The Path of Glouphrie"), - WARPED_TORTOISE(1, new int[] { 6296, 6297 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, "The Path of Glouphrie"), + WARPED_TERROR_BIRD(1, new int[] { 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6608 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, Quests.THE_PATH_OF_GLOUPHRIE), + WARPED_TORTOISE(1, new int[] { 6296, 6297 }, new String[] { "Warped Creatures can supposedly be found within a", "mysterious dungeon on the eastern edge of the Poison", "Waste. Be aware that to defeat them, you'll need to", "purify them in some way." },56, Quests.THE_PATH_OF_GLOUPHRIE), WATERFIENDS(75, new int[] { 5361 }, new String[] { "Waterfiends are creatures of water, which live under", "the Baxtorian Lake. Their watery form is well defended", "against slashing and piercing weapons, so use", "something blunt." }, 1, false, false), WEREWOLVES(60, new int[] { 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[] { "Werewolves are feral creatures, they are strong and", "tough with sharp claws and teeth." }, 1, false, false), WOLVES(20, new int[] { 95, 96, 97, 141, 142, 143, 839, 1198, 1330, 1558, 1559, 1951, 1952, 1953, 1954, 1955, 1956, 4413, 4414, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6829, 6830, 7005 }, new String[] { "Wolves are pack animals, so you'll always find them", "in groups. Watch out for their bite, it can be nasty." }, 1, false, false), @@ -144,7 +145,7 @@ public enum Tasks { public final int[] ids; public boolean undead = false; public boolean dragon = false; - public String questReq = ""; + public Quests questReq = null; Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon){ this.levelReq = levelReq; this.ids = ids; @@ -154,7 +155,7 @@ public enum Tasks { this.combatCheck = combatCheck; } - Tasks (int combatCheck, int[] ids, String[] info, int levelReq, String questReq) { + Tasks (int combatCheck, int[] ids, String[] info, int levelReq, Quests questReq) { this.combatCheck = combatCheck; this.ids = ids; this.info = info; @@ -171,7 +172,7 @@ public enum Tasks { } public boolean hasQuestRequirements (Player player) { - return questReq.isEmpty() || hasRequirement(player, questReq, false); + return questReq == null || hasRequirement(player, questReq, false); } public static Tasks forId(int id){ diff --git a/Server/src/main/content/global/skill/smithing/FurnaceOptionPlugin.java b/Server/src/main/content/global/skill/smithing/FurnaceOptionPlugin.java index 1468549d2..e34e71cc7 100644 --- a/Server/src/main/content/global/skill/smithing/FurnaceOptionPlugin.java +++ b/Server/src/main/content/global/skill/smithing/FurnaceOptionPlugin.java @@ -19,6 +19,7 @@ import core.plugin.Plugin; import java.util.ArrayList; import java.util.List; +import content.data.Quests; /** * Represents the plugin used for the furnace. @@ -64,7 +65,7 @@ public final class FurnaceOptionPlugin extends OptionHandler { private static void show(final Player player) { player.getInterfaceManager().openChatbox(311); player.getPacketDispatch().sendItemZoomOnInterface(2349, 150, 311, 4); - if (player.getQuestRepository().isComplete("The Knight's Sword")) { + if (player.getQuestRepository().isComplete(Quests.THE_KNIGHTS_SWORD)) { player.getPacketDispatch().sendString("



Blurite", 311, 20); } player.getPacketDispatch().sendItemZoomOnInterface(Bar.BLURITE.getProduct().getId(), 150, 311, 5); diff --git a/Server/src/main/content/global/skill/smithing/SmithingPulse.java b/Server/src/main/content/global/skill/smithing/SmithingPulse.java index f9b7eec98..97a844d51 100644 --- a/Server/src/main/content/global/skill/smithing/SmithingPulse.java +++ b/Server/src/main/content/global/skill/smithing/SmithingPulse.java @@ -14,6 +14,7 @@ import core.tools.StringUtils; import static core.api.ContentAPIKt.hasRequirement; import static core.api.ContentAPIKt.sendDialogue; +import content.data.Quests; /** * Represents the pulse used to smith a bar. @@ -67,11 +68,11 @@ public class SmithingPulse extends SkillPulse { player.getDialogueInterpreter().sendDialogue("You need a hammer to work the metal with."); return false; } - if (!player.getQuestRepository().isComplete("The Tourist Trap") && bar.getSmithingType() == SmithingType.TYPE_DART_TIP) { + if (!player.getQuestRepository().isComplete(Quests.THE_TOURIST_TRAP) && bar.getSmithingType() == SmithingType.TYPE_DART_TIP) { player.getDialogueInterpreter().sendDialogue("You need to complete Tourist Trap to smith dart tips."); return false; } - if (!hasRequirement(player, "Death Plateau", false) && bar.getSmithingType() == SmithingType.TYPE_CLAWS) { + if (!hasRequirement(player, Quests.DEATH_PLATEAU, false) && bar.getSmithingType() == SmithingType.TYPE_CLAWS) { sendDialogue(player, "You need to complete Death Plateau to smith claws."); return false; } diff --git a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java index 7ceb2143c..5f7876db9 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java +++ b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java @@ -3,7 +3,6 @@ package content.global.skill.smithing.smelting; import static core.api.ContentAPIKt.*; import core.api.Container; -import core.api.EquipmentSlot; import core.game.event.ResourceProducedEvent; import core.game.container.impl.EquipmentContainer; import core.tools.Log; @@ -19,6 +18,7 @@ import core.game.world.update.flag.context.Graphics; import core.tools.RandomFunction; import core.tools.StringUtils; import org.rs09.consts.Sounds; +import content.data.Quests; /** * Represents the pulse used to smelt. @@ -90,7 +90,7 @@ public class SmeltingPulse extends SkillPulse { if (bar == null || player == null) { return false; } - if (bar == Bar.BLURITE && !player.getQuestRepository().isComplete("The Knight's Sword")) { + if (bar == Bar.BLURITE && !player.getQuestRepository().isComplete(Quests.THE_KNIGHTS_SWORD)) { return false; } if (player.getSkills().getLevel(Skills.SMITHING) < bar.getLevel()) { diff --git a/Server/src/main/content/global/skill/summoning/SummoningTrainingRoom.java b/Server/src/main/content/global/skill/summoning/SummoningTrainingRoom.java index 68d038c0d..6296daef4 100644 --- a/Server/src/main/content/global/skill/summoning/SummoningTrainingRoom.java +++ b/Server/src/main/content/global/skill/summoning/SummoningTrainingRoom.java @@ -34,6 +34,7 @@ import core.plugin.Plugin; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Handles the summoning training room. @@ -81,7 +82,7 @@ public final class SummoningTrainingRoom extends OptionHandler { public boolean handle(final Player player, Node node, String option) { Scenery object = (Scenery) node; Location loc = null; - Quest quest = player.getQuestRepository().getQuest("Wolf Whistle"); + Quest quest = player.getQuestRepository().getQuest(Quests.WOLF_WHISTLE); int questVal = quest.getStage(player) == 0 ? 0 : quest.getStage(player) > 0 && quest.getStage(player) < 100 ? 5 : 28893; switch (option) { case "close": @@ -312,7 +313,7 @@ public final class SummoningTrainingRoom extends OptionHandler { @Override public boolean open(Object... args) { cutscene = (CutscenePlugin) args[0]; - quest = player.getQuestRepository().getQuest("Wolf Whistle"); + quest = player.getQuestRepository().getQuest(Quests.WOLF_WHISTLE); fluffy = NPC.create(6990, cutscene.getBase().transform(41, 52, 1)); fluffy.init(); fluffy.faceTemporary(player, 1); diff --git a/Server/src/main/content/global/skill/summoning/familiar/SummonFamiliarPlugin.java b/Server/src/main/content/global/skill/summoning/familiar/SummonFamiliarPlugin.java index 8f6a407d8..ee216033e 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/SummonFamiliarPlugin.java +++ b/Server/src/main/content/global/skill/summoning/familiar/SummonFamiliarPlugin.java @@ -9,6 +9,7 @@ import core.game.node.item.Item; import core.game.world.map.zone.ZoneBorders; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Handles summoning a familiar. @@ -26,7 +27,7 @@ public final class SummonFamiliarPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { Item item = (Item) node; - if (!player.getQuestRepository().isComplete("Wolf Whistle") && player.getAttribute("in-cutscene", null) == null) { + if (!player.getQuestRepository().isComplete(Quests.WOLF_WHISTLE) && player.getAttribute("in-cutscene", null) == null) { player.getPacketDispatch().sendMessage("You have to complete Wolf Whistle before you can summon a familiar."); return true; } diff --git a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java index 280f2cdcb..b08185335 100644 --- a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java +++ b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java @@ -10,14 +10,13 @@ import core.game.node.item.Item; import core.game.node.scenery.Scenery; import core.game.node.scenery.SceneryBuilder; import core.game.world.GameWorld; -import core.game.world.map.Direction; -import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.update.flag.context.Animation; import core.tools.RandomFunction; import core.tools.StringUtils; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the pulse used to thieve a stall. @@ -74,12 +73,12 @@ public final class StallThiefPulse extends SkillPulse { player.getPacketDispatch().sendMessage("You don't have enough inventory space."); return false; } - if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, "Fremennik Trials") && stall.full_ids.contains(4278)) { + if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && stall.full_ids.contains(4278)) { sendDialogue(player, "The fur trader is staring at you suspiciously. You cannot steal from his stall while he distrusts you."); return false; } - if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, "Fremennik Trials") && stall.full_ids.contains(4277)) { + if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && stall.full_ids.contains(4277)) { sendDialogue(player, "The fishmonger is staring at you suspiciously. You cannot steal from his stall while he distrusts you."); return false; } diff --git a/Server/src/main/content/global/travel/glider/CaptainDalburDialogue.java b/Server/src/main/content/global/travel/glider/CaptainDalburDialogue.java index 3af68e890..67f0cbaa0 100644 --- a/Server/src/main/content/global/travel/glider/CaptainDalburDialogue.java +++ b/Server/src/main/content/global/travel/glider/CaptainDalburDialogue.java @@ -1,6 +1,6 @@ package content.global.travel.glider; -import content.region.kandarin.quest.grandtree.TheGrandTree; +import content.data.Quests; import core.game.component.Component; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -58,7 +58,7 @@ public final class CaptainDalburDialogue extends DialoguePlugin { stage = 1; break; case 1: - if(!isQuestComplete(player, TheGrandTree.questName)){ + if(!isQuestComplete(player, Quests.THE_GRAND_TREE)){ interpreter.sendDialogues(npc, FacialExpression.ANNOYED, "I only fly friends of the gnomes!"); stage = END_DIALOGUE; } diff --git a/Server/src/main/content/global/travel/glider/GliderPlugin.java b/Server/src/main/content/global/travel/glider/GliderPlugin.java index c62e404d9..b3cbe634c 100644 --- a/Server/src/main/content/global/travel/glider/GliderPlugin.java +++ b/Server/src/main/content/global/travel/glider/GliderPlugin.java @@ -1,6 +1,6 @@ package content.global.travel.glider; -import content.region.kandarin.quest.grandtree.TheGrandTree; +import content.data.Quests; import core.api.ContentAPIKt; import core.cache.def.impl.NPCDefinition; import core.game.component.Component; @@ -31,7 +31,7 @@ public final class GliderPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - if(isQuestComplete(player, TheGrandTree.questName)){ + if(isQuestComplete(player, Quests.THE_GRAND_TREE)){ player.getInterfaceManager().open(new Component(138)); Gliders.sendConfig(node.asNpc(), player); } else { diff --git a/Server/src/main/content/global/travel/ship/SeamanDialoguePlugin.java b/Server/src/main/content/global/travel/ship/SeamanDialoguePlugin.java index f7782c200..41b226d36 100644 --- a/Server/src/main/content/global/travel/ship/SeamanDialoguePlugin.java +++ b/Server/src/main/content/global/travel/ship/SeamanDialoguePlugin.java @@ -11,6 +11,7 @@ import core.game.node.entity.player.link.diary.DiaryType; import core.game.node.item.Item; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the dialogue used to handle the sailing from and to karamja. @@ -46,7 +47,7 @@ public class SeamanDialoguePlugin extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - if (args.length > 1 && player.getQuestRepository().isComplete("Pirate's Treasure")) { + if (args.length > 1 && player.getQuestRepository().isComplete(Quests.PIRATES_TREASURE)) { if (player.getEquipment().get(EquipmentContainer.SLOT_RING) != null && player.getEquipment().get(EquipmentContainer.SLOT_RING).getId() == Items.RING_OF_CHAROSA_6465) { travel(); } else if (player.getAchievementDiaryManager().getDiary(DiaryType.KARAMJA).isComplete(0)) { diff --git a/Server/src/main/content/global/travel/ship/ShipCharter.java b/Server/src/main/content/global/travel/ship/ShipCharter.java index 5d275f6a9..9e04a8878 100644 --- a/Server/src/main/content/global/travel/ship/ShipCharter.java +++ b/Server/src/main/content/global/travel/ship/ShipCharter.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents a class used to charter ships. @@ -84,7 +85,7 @@ public final class ShipCharter { */ public static int getCost(final Player player, Destination destination) { int cost = destination.getCost(player, destination); - if (player.getQuestRepository().isComplete("Cabin Fever")) { + if (player.getQuestRepository().isComplete(Quests.CABIN_FEVER)) { cost -= Math.round((cost / 2.)); } if (player.getEquipment().containsItem(RING_OF_CHAROS)) { @@ -142,13 +143,13 @@ public final class ShipCharter { PORT_PHASMATYS(Location.create(3705, 3503, 1), 24, new int[] { 3650, 3250, 1850, 0, 0, 0, 2050, 1850, 3200, 1100 }, Location.create(3702, 3502, 0), 2, 13) { @Override public boolean checkTravel(Player player) { - return requireQuest(player, "Priest in Peril", "to go there."); + return requireQuest(player, Quests.PRIEST_IN_PERIL, "to go there."); } }, CRANDOR(Location.create(2792, 3417, 1), 32, new int[] { 0, 480, 480, 925, 400, 3650, 1600, 400, 3200, 3800 }, null, 10, 21) { @Override public boolean checkTravel(Player player) { - return requireQuest(player, "Dragon Slayer", "to go there."); + return requireQuest(player, Quests.DRAGON_SLAYER, "to go there."); } }, BRIMHAVEN(Location.create(2763, 3238, 1), 28, new int[] { 0, 480, 480, 925, 400, 3650, 1600, 400, 3200, 3800 }, Location.create(2760, 3238, 0), 6, 17){ @@ -170,7 +171,7 @@ public final class ShipCharter { PORT_TYRAS(Location.create(2142, 3122, 0), 23, new int[] { 3200, 3200, 3200, 1600, 3200, 3200, 3200, 3200, 0, 3200 }, Location.create(2143, 3122, 0), 1, 12) { @Override public boolean checkTravel(Player player) { - return hasRequirement(player, "Regicide"); + return hasRequirement(player, Quests.REGICIDE); } }, @@ -193,14 +194,14 @@ public final class ShipCharter { SHIPYARD(Location.create(3001, 3032, 0), 26, new int[] { 400, 1600, 200, 225, 720, 1850, 400, 0, 3200, 900 }, Location.create(3001, 3032, 0), 4, 15) { @Override public boolean checkTravel(Player player) { - return requireQuest(player, "The Grand Tree", "to go there."); + return requireQuest(player, Quests.THE_GRAND_TREE, "to go there."); } }, OO_GLOG(Location.create(2623, 2857, 0), 33, new int[] { 300, 3400, 2000, 550, 5000, 2800, 1400, 900, 3200, 0}, Location.create(2622, 2857, 0), 11, 22), MOS_LE_HARMLESS(Location.create(3671, 2931, 0), 31, new int[] { 725, 625, 1025, 0, 1025, 0, 325, 275, 1600, 500 }, Location.create(3671, 2933, 0), 9, 20) { @Override public boolean checkTravel(Player player) { - return hasRequirement(player, "Cabin Fever"); + return hasRequirement(player, Quests.CABIN_FEVER); } }; diff --git a/Server/src/main/content/global/travel/trees/GnomeSpiritTreeListener.kt b/Server/src/main/content/global/travel/trees/GnomeSpiritTreeListener.kt index 494a79e12..838473c20 100644 --- a/Server/src/main/content/global/travel/trees/GnomeSpiritTreeListener.kt +++ b/Server/src/main/content/global/travel/trees/GnomeSpiritTreeListener.kt @@ -12,12 +12,12 @@ import core.game.world.map.Location import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Graphics import org.rs09.consts.NPCs -import content.region.kandarin.quest.tree.TreeGnomeVillage import core.game.dialogue.DialogueFile import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.world.GameWorld.Pulser import core.tools.END_DIALOGUE +import content.data.Quests class GnomeSpiritTreeListener: InteractionListener { val spiritTrees = intArrayOf(1317,1293,1294) @@ -46,7 +46,7 @@ class GnomeSpiritTreeTeleportDialogue: DialogueFile() { private val GRAPHICS = arrayOf(Graphics(1228), Graphics(1229)) fun hasQuestCompleted(player: Player): Boolean { - if (!isQuestComplete(player, TreeGnomeVillage.questName)) { + if (!isQuestComplete(player, Quests.TREE_GNOME_VILLAGE)) { sendDialogue(player, "The tree doesn't feel like talking.") stage = END_DIALOGUE return false diff --git a/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt b/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt index 08d059bcf..cd50cb9bf 100644 --- a/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt +++ b/Server/src/main/content/minigame/allfiredup/AFUBeaconHandler.kt @@ -10,6 +10,7 @@ import org.rs09.consts.Items import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.world.GameWorld +import content.data.Quests private val VALID_LOGS = intArrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521,Items.WILLOW_LOGS_1519,Items.MAPLE_LOGS_1517,Items.YEW_LOGS_1515,Items.MAGIC_LOGS_1513) private val FILL_ANIM = Animation(9136) @@ -24,8 +25,8 @@ class AFUBeaconListeners : InteractionListener { override fun defineListeners() { on(IntType.SCENERY,"add-logs","light"){ player, node -> val beacon = AFUBeacon.forLocation(node.location) - val questComplete = player.questRepository.isComplete("All Fired Up") - val questStage = player.questRepository.getStage("All Fired Up") + val questComplete = player.questRepository.isComplete(Quests.ALL_FIRED_UP) + val questStage = player.questRepository.getStage(Quests.ALL_FIRED_UP) if ((beacon != AFUBeacon.RIVER_SALVE && beacon != AFUBeacon.RAG_AND_BONE && !questComplete) || (beacon == AFUBeacon.RIVER_SALVE && questStage < 20 && !questComplete) @@ -68,7 +69,7 @@ class AFUBeaconListeners : InteractionListener { } AFUBeacon.GOBLIN_VILLAGE -> { - if(!player.questRepository.isComplete("Lost Tribe")){ + if(!player.questRepository.isComplete(Quests.THE_LOST_TRIBE)){ player.dialogueInterpreter.sendDialogues(NPC(beacon.keeper).getShownNPC(player), core.game.dialogue.FacialExpression.THINKING,"We no trust you outsider. You no light our beacon.","(Complete Lost Tribe to use this beacon.)") return } @@ -151,7 +152,7 @@ class AFUBeaconListeners : InteractionListener { experience += session?.getBonusExperience() ?: 0.0 player.skills.addExperience(Skills.FIREMAKING,experience) } else { - player.questRepository.getQuest("All Fired Up").setStage(player, player.questRepository.getStage("All Fired Up") + 10) + player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player, player.questRepository.getStage(Quests.ALL_FIRED_UP) + 10) } } 2 -> player.unlock().also { return true } @@ -183,7 +184,7 @@ class AFUBeaconListeners : InteractionListener { if(questComplete){ session?.refreshTimer(beacon,logs.id) } else { - player.questRepository.getQuest("All Fired Up").setStage(player, 80) + player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player, 80) } } 2 -> player.unlock().also { return true } diff --git a/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt b/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt index e64b93b67..f95dfb1d9 100644 --- a/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt +++ b/Server/src/main/content/minigame/allfiredup/AFURepairClimbHandler.kt @@ -1,5 +1,6 @@ package content.minigame.allfiredup +import content.data.Quests import core.game.node.entity.impl.ForceMovement import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills @@ -26,7 +27,7 @@ class AFURepairClimbHandler : InteractionListener { override fun defineListeners() { on(repairIDs, IntType.SCENERY, "repair"){ player, _ -> - if (hasRequirement(player, "All Fired Up")){ + if (hasRequirement(player, Quests.ALL_FIRED_UP)){ val rco: RepairClimbObject? = getClimbingObject(player) repair(player,rco!!) return@on true diff --git a/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt b/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt index b54f8dd36..a295a8795 100644 --- a/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt +++ b/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt @@ -13,6 +13,7 @@ import org.rs09.consts.Items import core.game.dialogue.DialogueFile import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests /** * Adds functionality to the pharoah's scepter @@ -23,7 +24,7 @@ class PharaohSceptre : InteractionListener { val SCEPTRES = intArrayOf(Items.PHARAOHS_SCEPTRE_9044, Items.PHARAOHS_SCEPTRE_9046, Items.PHARAOHS_SCEPTRE_9048, Items.PHARAOHS_SCEPTRE_9050) on(SCEPTRES, IntType.ITEM, "teleport", "operate"){ player, node -> - if (!hasRequirement(player, "Icthlarin's Little Helper")) + if (!hasRequirement(player, Quests.ICTHLARINS_LITTLE_HELPER)) return@on true val sceptre = node.asItem() diff --git a/Server/src/main/content/minigame/sorceress/GardenObjectsPlugin.kt b/Server/src/main/content/minigame/sorceress/GardenObjectsPlugin.kt index 4739bf5c2..53eb47fa9 100644 --- a/Server/src/main/content/minigame/sorceress/GardenObjectsPlugin.kt +++ b/Server/src/main/content/minigame/sorceress/GardenObjectsPlugin.kt @@ -23,6 +23,7 @@ import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.world.GameWorld import core.plugin.ClassScanner +import content.data.Quests class GardenObjectsPlugin : InteractionListener { @@ -503,7 +504,7 @@ class GardenObjectsPlugin : InteractionListener { override fun open(vararg args: Any): Boolean { npc = args[0] as NPC - quest = player.questRepository.getQuest("Prince Ali Rescue") + quest = player.questRepository.getQuest(Quests.PRINCE_ALI_RESCUE) when (quest!!.getStage(player)) { 100 -> { interpreter.sendDialogues(player, null, "I'd like to talk about sq'irks.") diff --git a/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java b/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java index 4e6be91c4..bc3aa169b 100644 --- a/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java +++ b/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java @@ -11,6 +11,7 @@ import core.game.world.map.Location; import core.game.world.update.flag.context.Graphics; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Dialogue for Sorceress Apprentice @@ -238,7 +239,7 @@ public class SorceressApprenticeDialogue extends DialoguePlugin { } public static void teleport(final NPC npc, final Player player) { - if (!hasRequirement(player, "Prince Ali Rescue")) + if (!hasRequirement(player, Quests.PRINCE_ALI_RESCUE)) return; npc.faceTemporary(player, 4); npc.graphics(new Graphics(108)); diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BernaldDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BernaldDialogue.kt index 7984ceed8..2e1ca6b44 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BernaldDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BernaldDialogue.kt @@ -20,8 +20,8 @@ class BernaldDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { // // Garden of Tranquility has not been implemented. -// if(hasRequirement(player!!, "Garden of Tranquility")) { -// if (isQuestComplete(player!!, DeathPlateau.questName)) { +// if(hasRequirement(player!!, Quests.GARDEN_OF_TRANQUILITY)) { +// if (isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { // when (stage) { // 0 -> playerl(FacialExpression.FRIENDLY, "How are your grapes coming along?").also { stage++ } // 1 -> npc(FacialExpression.FRIENDLY, "Marvellous, thanks to your help, " + player.username + "!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BreocaDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BreocaDialogue.kt index ca982ff6c..8a885cd94 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BreocaDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/BreocaDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Breoca Dialogue @@ -18,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class BreocaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..3).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/CeolburgDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/CeolburgDialogue.kt index 6eae6fa18..006641ebd 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/CeolburgDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/CeolburgDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Ceolburg Dialogue @@ -18,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class CeolburgDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..3).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DenulthDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DenulthDialogue.kt index 430da5566..2724f9c19 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DenulthDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DenulthDialogue.kt @@ -1,8 +1,7 @@ package content.region.asgarnia.burthorpe.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import content.region.asgarnia.burthorpe.quest.deathplateau.DenulthDialogueFile -import content.region.asgarnia.burthorpe.quest.trollstronghold.TrollStronghold import core.api.isQuestComplete import core.api.isQuestInProgress import core.api.openDialogue @@ -25,7 +24,7 @@ class DenulthDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { // When Troll Stronghold is complete - if (isQuestComplete(player!!, TrollStronghold.questName)) { + if (isQuestComplete(player!!, Quests.TROLL_STRONGHOLD)) { when(stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hello!").also { stage++ } 1 -> npcl(FacialExpression.HAPPY, "Welcome back friend!").also { stage++ } @@ -49,13 +48,13 @@ class DenulthDialogue(player: Player? = null) : DialoguePlugin(player) { } // Troll Stronghold in progress - if (isQuestInProgress(player!!, TrollStronghold.questName, 1, 99)) { + if (isQuestInProgress(player!!, Quests.TROLL_STRONGHOLD, 1, 99)) { openDialogue(player!!, content.region.asgarnia.burthorpe.quest.trollstronghold.DenulthDialogueFile(), npc) return true } // When Death Plateau is completed, start Troll Stronghold - if (isQuestComplete(player!!, DeathPlateau.questName)) { + if (isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when(stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hello!").also { stage++ } 1 -> npcl(FacialExpression.HAPPY, "Welcome back friend!").also { stage++ } @@ -78,7 +77,7 @@ class DenulthDialogue(player: Player? = null) : DialoguePlugin(player) { ) 16 -> npcl(FacialExpression.HAPPY, "God speed friend! I would send some of my men with you, but none of them are brave enough to follow.").also { stage = END_DIALOGUE - setQuestStage(player!!, TrollStronghold.questName, 1) + setQuestStage(player!!, Quests.TROLL_STRONGHOLD, 1) } 20 -> npcl(FacialExpression.ANGRY, "You are right citizen. The White Knights have taken advantage of the old and weak king, they control most of Asgarnia, including Falador. However they do not control Burthorpe!").also { stage++ } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt index 6346fc9f6..92a7b22c2 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt @@ -1,7 +1,6 @@ package content.region.asgarnia.burthorpe.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau -import content.region.asgarnia.burthorpe.quest.trollstronghold.TrollStronghold +import content.data.Quests import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -24,7 +23,7 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { // When Troll Stronghold is complete - if (isQuestComplete(player!!, TrollStronghold.questName)) { + if (isQuestComplete(player!!, Quests.TROLL_STRONGHOLD)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage++ } 1 -> npcl(FacialExpression.FRIENDLY, "Hi! What can I do for you?").also { stage++ } @@ -47,13 +46,13 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { } // Troll Stronghold in progress - if (isQuestInProgress(player!!, TrollStronghold.questName, 1, 99)) { + if (isQuestInProgress(player!!, Quests.TROLL_STRONGHOLD, 1, 99)) { openDialogue(player!!, content.region.asgarnia.burthorpe.quest.trollstronghold.DunstanDialogueFile(), npc) return true } // When Death Plateau is complete - if (isQuestComplete(player!!, DeathPlateau.questName)) { + if (isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage++ } 1 -> npcl(FacialExpression.FRIENDLY, "Hi! What can I do for you?").also { stage++ } @@ -75,7 +74,7 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { } // Death Plateau in progress - if (isQuestInProgress(player!!, DeathPlateau.questName, 21, 24)) { + if (isQuestInProgress(player!!, Quests.DEATH_PLATEAU, 21, 24)) { // Call the dialogue file for Dunstan from the deathplateau quest folder. openDialogue(player!!, content.region.asgarnia.burthorpe.quest.deathplateau.DunstanDialogueFile(), npc) return true diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/EohricDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/EohricDialogue.kt index e9ccfc492..4fb041be6 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/EohricDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/EohricDialogue.kt @@ -1,6 +1,6 @@ package content.region.asgarnia.burthorpe.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import content.region.asgarnia.burthorpe.quest.deathplateau.EohricDialogueFile import core.api.getQuestStage import core.api.openDialogue @@ -19,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class EohricDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if (getQuestStage(player!!, DeathPlateau.questName) >= 5) { + if (getQuestStage(player!!, Quests.DEATH_PLATEAU) >= 5) { // Call the dialogue file for Eohric from the deathplateau quest folder. openDialogue(player!!, EohricDialogueFile(), npc) return true diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HaroldDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HaroldDialogue.kt index b98a66184..62d510ac1 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HaroldDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HaroldDialogue.kt @@ -1,14 +1,12 @@ package content.region.asgarnia.burthorpe.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import content.region.asgarnia.burthorpe.quest.deathplateau.HaroldDialogueFile import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.world.update.flag.context.Animation -import core.game.world.update.flag.context.Graphics import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE @@ -23,7 +21,7 @@ import org.rs09.consts.NPCs @Initializable class HaroldDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if (isQuestInProgress(player!!, DeathPlateau.questName, 10, 29)) { + if (isQuestInProgress(player!!, Quests.DEATH_PLATEAU, 10, 29)) { // Call the dialogue file for Harold from the deathplateau quest folder. openDialogue(player!!, HaroldDialogueFile(), npc) } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HildDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HildDialogue.kt index b8361c40a..6b0116cd3 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HildDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HildDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Hild Dialogue @@ -18,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class HildDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..3).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HygdDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HygdDialogue.kt index 2a7f3f280..3e3b73b90 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HygdDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/HygdDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Hygd Dialogue @@ -18,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class HygdDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..3).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/OcgaDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/OcgaDialogue.kt index 514035edc..0606c4542 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/OcgaDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/OcgaDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** @@ -19,7 +20,7 @@ import org.rs09.consts.NPCs @Initializable class OcgaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..3).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/PendaDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/PendaDialogue.kt index 4cd42579c..0570a0d24 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/PendaDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/PendaDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Penda Dialogue @@ -18,7 +19,7 @@ import org.rs09.consts.NPCs @Initializable class PendaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int) : Boolean { - if(isQuestComplete(player!!, "Death Plateau")) { + if(isQuestComplete(player!!, Quests.DEATH_PLATEAU)) { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage = (1..5).toIntArray().random() } 1 -> npcl(FacialExpression.HAPPY, "I heard about what you did, thank you!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/UnferthDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/UnferthDialogue.kt index 84b26124e..5c0a23214 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/UnferthDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/UnferthDialogue.kt @@ -8,9 +8,8 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable -import core.tools.END_DIALOGUE -import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests /** * Unferth Dialogue @@ -37,7 +36,7 @@ class UnferthDialogue(player: Player? = null) : DialoguePlugin(player) { class UnferthDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onPredicate { player -> isQuestComplete(player, "A Tail of Two Cats") }.playerl( + b.onPredicate { player -> isQuestComplete(player, Quests.A_TAIL_OF_TWO_CATS) }.playerl( FacialExpression.FRIENDLY, "Hi Unferth. How are you doing?" ).npcl( FacialExpression.GUILTY, "It's just not the same without Bob around." diff --git a/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java b/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java index 5c3900341..cc4e8fb62 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java +++ b/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java @@ -18,6 +18,7 @@ import core.plugin.Initializable; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Represents the hero guild. @@ -42,7 +43,7 @@ public final class HeroGuildPlugin extends OptionHandler { switch (id) { case 2624: case 2625: - if (!hasRequirement(player, "Heroes' Quest")) + if (!hasRequirement(player, Quests.HEROES_QUEST)) return true; DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); break; @@ -82,15 +83,15 @@ public final class HeroGuildPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - if (!hasRequirement(player, "Heroes' Quest")) + if (!hasRequirement(player, Quests.HEROES_QUEST)) return true; final EnchantedJewellery jewellery; assert event.getUsedItem() != null; jewellery = EnchantedJewellery.Companion.getIdMap().get(event.getUsedItem().getId()); - if (!hasRequirement(player, "Heroes' Quest")) + if (!hasRequirement(player, Quests.HEROES_QUEST)) return true; if (jewellery == EnchantedJewellery.COMBAT_BRACELET || jewellery == EnchantedJewellery.SKILLS_NECKLACE) - if (!hasRequirement(player, "Legend's Quest")) + if (!hasRequirement(player, Quests.LEGENDS_QUEST)) return true; if (jewellery == null && event.getUsedItem().getId() != 2572) { return true; diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateau.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateau.kt index b6b31939f..24e3f6cbc 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateau.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateau.kt @@ -5,9 +5,9 @@ import core.api.getAttribute import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills -import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Death Plateau Quest @@ -15,16 +15,13 @@ import org.rs09.consts.Items * @author ovenbread */ @Initializable -class DeathPlateau : Quest("Death Plateau",44, 43, 1, 314, 0, 1, 80) { - companion object { - const val questName = "Death Plateau" - } +class DeathPlateau : Quest(Quests.DEATH_PLATEAU,44, 43, 1, 314, 0, 1, 80) { override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 12 var stage = getStage(player) - var started = player?.questRepository?.getStage(questName)!! > 0 + var started = player?.questRepository?.getStage(Quests.DEATH_PLATEAU)!! > 0 if(!started){ line(player, "I can start this quest by speaking to !!Denulth?? who is in his", line++) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauDoorDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauDoorDialogueFile.kt index e0db1a73d..64c29cec7 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauDoorDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauDoorDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.getQuestStage import core.api.getScenery import core.api.sendDialogue @@ -26,7 +27,7 @@ class DeathPlateauDoorDialogueFile(val door: Int) : DialogueFile() { if(door == 2) { npc = NPC(NPCs.TENZING_1071) - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { in 0 .. 19 -> { when (stage) { 0 -> sendDialogue(player!!, "You knock on the door.").also { stage++ } @@ -53,7 +54,7 @@ class DeathPlateauDoorDialogueFile(val door: Int) : DialogueFile() { } if(door == 3) { npc = NPC(NPCs.TENZING_1071) - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { in 0..24 -> { when (stage) { 0 -> npcl(FacialExpression.FRIENDLY, "Where do you think you're going? This is private property!").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt index dde461532..01a253ad4 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DeathPlateauInteractionListener.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.* import core.game.global.action.DoorActionHandler import core.game.interaction.IntType @@ -74,16 +75,16 @@ class DeathPlateauInteractionListener : InteractionListener { GroundItemManager.get(Items.STONE_BALL_3111, location(2895, 3562, 0), player) != null && GroundItemManager.get(Items.STONE_BALL_3112, location(2895, 3563, 0), player) != null && GroundItemManager.get(Items.STONE_BALL_3113, location(2895, 3564, 0), player) != null) { - if (getQuestStage(player, DeathPlateau.questName) == 16) { + if (getQuestStage(player, Quests.DEATH_PLATEAU) == 16) { sendMessage(player, "The equipment room door has unlocked.") - setQuestStage(player, DeathPlateau.questName, 19) + setQuestStage(player, Quests.DEATH_PLATEAU, 19) } } return@onUseWith true } on(Scenery.LARGE_DOOR_3743, SCENERY, "open") { player, node -> - if (getQuestStage(player, DeathPlateau.questName) > 16) { + if (getQuestStage(player, Quests.DEATH_PLATEAU) > 16) { DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery) } else { sendMessage(player, "The door is locked.") diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt index 7838a6c5c..415a29109 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt @@ -1,14 +1,13 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.dialogue.Topic -import core.game.node.entity.npc.NPC import core.game.node.item.Item import core.tools.END_DIALOGUE import org.rs09.consts.Items -import org.rs09.consts.NPCs /** @@ -20,7 +19,7 @@ import org.rs09.consts.NPCs class DenulthDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { in 0..4 -> { when (stage) { 0 -> playerl(FacialExpression.FRIENDLY, "Hello!").also { stage++ } @@ -54,7 +53,7 @@ class DenulthDialogueFile : DialogueFile() { 309 -> playerl(FacialExpression.FRIENDLY, "A stone what...?!").also { stage++ } 310 -> npcl(FacialExpression.FRIENDLY, "Well citizen, the Prince is fond of puzzles. Why we couldn't just have a key is beyond me!").also { stage++ } 311 -> playerl(FacialExpression.SUSPICIOUS, "I'll get on it right away!").also { - setQuestStage(player!!, DeathPlateau.questName, 5) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 5) stage = END_DIALOGUE } } @@ -104,7 +103,7 @@ class DenulthDialogueFile : DialogueFile() { } 11 -> npcl(FacialExpression.FRIENDLY, "This certificate proves that we have accepted Dunstan's son for training in the Imperial Guard!").also { stage++ } 12 -> playerl(FacialExpression.FRIENDLY, "Thank you Denulth, I shall be back shortly!").also { - setQuestStage(player!!, DeathPlateau.questName, 23) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 23) stage = END_DIALOGUE } } @@ -169,7 +168,7 @@ class DenulthDialogueFile : DialogueFile() { 12 -> npcl(FacialExpression.FRIENDLY, "You are now an honourary member of the Imperial Guard!").also { stage++ } 13 -> { stage = END_DIALOGUE - finishQuest(player!!, DeathPlateau.questName) + finishQuest(player!!, Quests.DEATH_PLATEAU) } } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt index 2567c54c8..616635575 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt @@ -3,17 +3,16 @@ package content.region.asgarnia.burthorpe.quest.deathplateau import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC import core.game.node.item.Item import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.Items -import org.rs09.consts.NPCs +import content.data.Quests class DunstanDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { 21 -> { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage++ } @@ -29,7 +28,7 @@ class DunstanDialogueFile : DialogueFile() { 10 -> npcl(FacialExpression.FRIENDLY, "My son has just turned 16 and I'd very much like him to join the Imperial Guard. The Prince's elite forces are invite only so it's very unlikely he'll get in. If you can arrange that you have a deal!").also { stage++ } 11 -> playerl(FacialExpression.FRIENDLY, "That won't be a problem as I'm helping out the Imperial Guard!").also { stage++ } 12 -> npcl(FacialExpression.FRIENDLY, "Excellent! You'll need to bring an Iron bar for the spikes!").also { - setQuestStage(player!!, "Death Plateau", 22) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 22) stage = END_DIALOGUE } } @@ -60,7 +59,7 @@ class DunstanDialogueFile : DialogueFile() { 5 -> npcl(FacialExpression.FRIENDLY, "Thank you!").also { // Jumps to the next stage immediately in one continuous dialogue (questStage 24, stage 2). - setQuestStage(player!!, "Death Plateau", 24) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 24) stage = 2 } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/EohricDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/EohricDialogueFile.kt index 426f4846a..8e0d5f0a6 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/EohricDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/EohricDialogueFile.kt @@ -4,10 +4,9 @@ import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.dialogue.Topic -import core.game.node.entity.npc.NPC import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE -import org.rs09.consts.NPCs +import content.data.Quests /** * Eohric sub dialogue file for death plateau. @@ -17,7 +16,7 @@ import org.rs09.consts.NPCs */ class EohricDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { in 5..9 -> { when (stage) { START_DIALOGUE -> player(FacialExpression.FRIENDLY, "Hi!").also { stage++ } @@ -31,7 +30,7 @@ class EohricDialogueFile : DialogueFile() { 11 -> player(FacialExpression.FRIENDLY, "Do you know where he is staying?").also { stage++ } 12 -> npc(FacialExpression.FRIENDLY, "Harold is staying at the Toad and Chicken.").also { stage++ } 13 -> player(FacialExpression.FRIENDLY, "Thanks!").also { - setQuestStage(player!!, "Death Plateau", 10) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 10) HaroldDialogueFile.resetNpc(player!!) stage = END_DIALOGUE } @@ -58,7 +57,7 @@ class EohricDialogueFile : DialogueFile() { 2 -> playerl(FacialExpression.HALF_GUILTY, "I found Harold but he won't talk to me!.").also { stage++ } 3 -> npcl(FacialExpression.THINKING, "Hmm. Harold has got in trouble a few over his drinking and gambling. Perhaps he'd open up after a drink?").also { stage++ } 4 -> playerl(FacialExpression.FRIENDLY, "Thanks, I'll try that!").also { - setQuestStage(player!!, "Death Plateau", 12) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 12) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt index 810b427b1..50739d72a 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt @@ -11,6 +11,7 @@ import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.Animations import org.rs09.consts.Items +import content.data.Quests /** * Harold sub dialogue file for death plateau. @@ -38,7 +39,7 @@ class HaroldDialogueFile : DialogueFile() { setAttribute(player!!, ATTRIBUTE_JUMPSTAGE, 0) } println(getAttribute(player!!, ATTRIBUTE_HAROLD_MONEY, -1)) - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { 10 -> { // First time meeting. when (stage) { START_DIALOGUE -> player(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } @@ -47,7 +48,7 @@ class HaroldDialogueFile : DialogueFile() { 3 -> npcl(FacialExpression.FRIENDLY, "Yeah.").also { stage++ } 4 -> playerl(FacialExpression.HAPPY, "Denulth said that you lost the combination to the equipment room ?").also { stage++ } 5 -> npcl(FacialExpression.FRIENDLY, "I don't want to talk about it!").also { - setQuestStage(player!!, "Death Plateau", 11) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 11) stage = END_DIALOGUE } } @@ -71,7 +72,7 @@ class HaroldDialogueFile : DialogueFile() { 4 -> { if (inInventory(player!!, Items.ASGARNIAN_ALE_1905, 1)) { removeItem(player!!, Items.ASGARNIAN_ALE_1905) - setQuestStage(player!!, "Death Plateau", 12) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 12) sendMessage(player!!, "You give Harold an Asgarnian Ale.") setAttribute(player!!, ATTRIBUTE_HAROLD_MONEY, 200) sendItemDialogue(player!!, Items.ASGARNIAN_ALE_1905, "You give Harold an Asgarnian Ale.").also { stage++ } @@ -81,7 +82,7 @@ class HaroldDialogueFile : DialogueFile() { } 5 -> { end() - setQuestStage(player!!, "Death Plateau", 13) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 13) animate(npc!!, Animations.HUMAN_EATTING_829) runTask(npc!!, 5) { npcl(FacialExpression.FRIENDLY, "Arrh. That hit the spot!").also { stage = END_DIALOGUE } @@ -120,7 +121,7 @@ class HaroldDialogueFile : DialogueFile() { } 24 -> { end() - setQuestStage(player!!, DeathPlateau.questName, 14) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 14) npc!!.isWalks = false animate(npc!!, Animations.HUMAN_EATTING_829) runTask(npc!!, 4) { @@ -204,7 +205,7 @@ class HaroldDialogueFile : DialogueFile() { 37 -> npcl(FacialExpression.FRIENDLY, "I'll write you out an IOU for the rest.").also { stage++ } 38 -> { addItemOrDrop(player!!, Items.IOU_3103) - setQuestStage(player!!, DeathPlateau.questName, 15) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 15) sendMessage(player!!, "Harold has given you an IOU scribbled on some paper.") sendItemDialogue(player!!, Items.IOU_3103, "Harold has given you an IOU scribbled on some paper.").also {stage = END_DIALOGUE} } @@ -292,7 +293,7 @@ class HaroldDialogueFile : DialogueFile() { 34 -> npcl(FacialExpression.DRUNK, "I owe you the resht!").also { stage++ } 35 -> { addItemOrDrop(player!!, Items.IOU_3103) - setQuestStage(player!!, DeathPlateau.questName, 15) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 15) sendMessage(player!!, "Harold has given you an IOU scribbled on some paper.") sendItemDialogue(player!!, Items.IOU_3103, "Harold has given you an IOU scribbled on some paper.").also {stage = END_DIALOGUE} } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/IOUNoteDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/IOUNoteDialogueFile.kt index 0d44bc767..4a4531422 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/IOUNoteDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/IOUNoteDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -9,7 +10,7 @@ import org.rs09.consts.Items class IOUNoteDialogueFile : DialogueFile() { var a = 0 override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { in 15..16 -> { when (stage) { 0 -> player(FacialExpression.NEUTRAL, "The IOU says that Harold owes me some money.").also { stage++ } @@ -18,7 +19,7 @@ class IOUNoteDialogueFile : DialogueFile() { 3 -> { if (removeItem(player!!, Items.IOU_3103)) { addItemOrDrop(player!!, Items.COMBINATION_3102) - setQuestStage(player!!, DeathPlateau.questName, 16) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 16) sendItemDialogue(player!!, Items.COMBINATION_3102, "You have found the combination!").also { stage++ } } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SabaDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SabaDialogueFile.kt index 3c1c90632..820fdf26e 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SabaDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SabaDialogueFile.kt @@ -5,11 +5,12 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.dialogue.Topic import core.tools.END_DIALOGUE +import content.data.Quests class SabaDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { 19 -> { when (stage) { 0 -> player(FacialExpression.FRIENDLY, "Hello!").also { stage++ } @@ -34,7 +35,7 @@ class SabaDialogueFile : DialogueFile() { 29 -> npcl(FacialExpression.HALF_GUILTY,"Before the trolls came there used to be a nettlesome Sherpa that took humans exploring or something equally stupid. Perhaps he'd know another way.").also { stage++ } 30 -> playerl(FacialExpression.FRIENDLY, "Where does this Sherpa live?").also { stage++ } 31 -> npcl(FacialExpression.ANNOYED,"I don't know but it can't be far as he used to be around all the time!").also { - setQuestStage(player!!, "Death Plateau", 20) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 20) stage = END_DIALOGUE } } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SecretWayLocation.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SecretWayLocation.kt index 3a078a77d..96d821a9f 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SecretWayLocation.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/SecretWayLocation.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.* import core.game.node.entity.Entity import core.game.node.entity.player.Player @@ -11,9 +12,9 @@ class SecretWayLocation : MapArea { } override fun areaEnter(entity: Entity) { - if (entity is Player && getQuestStage(entity, DeathPlateau.questName) == 25) { + if (entity is Player && getQuestStage(entity, Quests.DEATH_PLATEAU) == 25) { sendPlayerDialogue(entity, "I think this is far enough, I can see Death Plateau and it looks like the trolls haven't found the path. I'd better go and tell Denulth.") - setQuestStage(entity, DeathPlateau.questName, 26) + setQuestStage(entity, Quests.DEATH_PLATEAU, 26) } } } \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/TenzingDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/TenzingDialogueFile.kt index aacba1673..c69cb4a94 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/TenzingDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/TenzingDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.deathplateau +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -12,7 +13,7 @@ import org.rs09.consts.Items class TenzingDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, DeathPlateau.questName)) { + when (getQuestStage(player!!, Quests.DEATH_PLATEAU)) { 20 -> { when (stage) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hello!").also { stage++ } @@ -34,7 +35,7 @@ class TenzingDialogueFile : DialogueFile() { 20 -> npcl(FacialExpression.FRIENDLY, "Thank you traveller!").also { stage++ } 21 -> sendItemDialogue(player!!, Items.CLIMBING_BOOTS_3105, "Tenzing has given you his Climbing boots.").also { addItemOrDrop(player!!, Items.CLIMBING_BOOTS_3105, 1) - setQuestStage(player!!, DeathPlateau.questName, 21) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 21) stage = END_DIALOGUE } 30 -> npcl(FacialExpression.ANNOYED, "Hmph.").also { stage = END_DIALOGUE } @@ -104,7 +105,7 @@ class TenzingDialogueFile : DialogueFile() { 9 -> npcl(FacialExpression.FRIENDLY, "I don't think the Trolls have found the secret way yet, if they had I would've been attacked by now.").also { stage++ } 10 -> playerl(FacialExpression.FRIENDLY, "OK thanks but I think I'd better check the path. I don't want to send the Imperial Guards to their death!").also { stage++ } 11 -> npcl(FacialExpression.FRIENDLY, "You are wise for one so young.").also { - setQuestStage(player!!, DeathPlateau.questName, 25) + setQuestStage(player!!, Quests.DEATH_PLATEAU, 25) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt index 4d23b5ad2..be02fd712 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AchiettiesDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -31,9 +32,9 @@ class AchiettiesDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(HeroesQuest.questName, 0,1) + b.onQuestStages(Quests.HEROES_QUEST, 0,1) .branch { player -> - return@branch getQuestStage(player, HeroesQuest.questName) + return@branch getQuestStage(player, Quests.HEROES_QUEST) }.let{ branch -> branch.onValue(0) .npcl(FacialExpression.FRIENDLY, "Greetings. Welcome to the Heroes' Guild.") @@ -58,8 +59,8 @@ class AchiettiesDialogueFile : DialogueBuilderFile() { return@let branch }.onValue(1) .betweenStage { df, player, _, _ -> - if(getQuestStage(player, HeroesQuest.questName) == 0) { - setQuestStage(player, HeroesQuest.questName, 1) + if(getQuestStage(player, Quests.HEROES_QUEST) == 0) { + setQuestStage(player, Quests.HEROES_QUEST, 1) } } .npcl("Well you seem to meet our initial requirements, so you may now begin the tasks to earn membership in the Heroes' Guild.") @@ -107,7 +108,7 @@ class AchiettiesDialogueFile : DialogueBuilderFile() { } } - b.onQuestStages(HeroesQuest.questName, 2,3,4) + b.onQuestStages(Quests.HEROES_QUEST, 2, 3, 4) .npcl("Greetings. Welcome to the Heroes' Guild.") .npcl("How goes thy quest adventurer?") .playerl("It's tough. I've not done it yet.") @@ -129,7 +130,7 @@ class AchiettiesDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(HeroesQuest.questName, 6) + b.onQuestStages(Quests.HEROES_QUEST, 6) .npcl("Greetings. Welcome to the Heroes' Guild.") .npcl("How goes thy quest adventurer?") .branch { player -> @@ -166,14 +167,14 @@ class AchiettiesDialogueFile : DialogueBuilderFile() { removeItem(player, Items.FIRE_FEATHER_1583) removeItem(player, Items.LAVA_EEL_2149) removeItem(player, Items.THIEVES_ARMBAND_1579) - if (getQuestStage(player, HeroesQuest.questName) == 6) { - finishQuest(player, HeroesQuest.questName) + if (getQuestStage(player, Quests.HEROES_QUEST) == 6) { + finishQuest(player, Quests.HEROES_QUEST) } } } } - b.onQuestStages(HeroesQuest.questName, 100) + b.onQuestStages(Quests.HEROES_QUEST, 100) .npcl("Greetings. Welcome to the Heroes' Guild.") } } \ No newline at end of file diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt index 41395fd1e..efb262b09 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/AlfonseTheWaiterDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.getQuestStage import core.api.openDialogue import core.api.openNpcShop @@ -7,7 +8,6 @@ import core.api.setQuestStage import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs @@ -40,13 +40,16 @@ class AlfonseTheWaiterDialogueFile : DialogueBuilderFile() { optionBuilder.option_playerl("No thank you.") .end() - optionBuilder.optionIf("Do you sell Gherkins?"){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 2 && HeroesQuest.isPhoenix(player) } + optionBuilder.optionIf("Do you sell Gherkins?"){ player -> return@optionIf getQuestStage( + player, + Quests.HEROES_QUEST + ) >= 2 && HeroesQuest.isPhoenix(player) } .playerl("Do you sell Gherkins?") .npc("Hmmmm Gherkins eh? Ask Charlie the cook, round the", "back. He may have some 'gherkins' for you!") .linel("Alfonse winks at you.") .endWith { _, player -> - if(getQuestStage(player, HeroesQuest.questName) == 2) { - setQuestStage(player, HeroesQuest.questName, 3) + if(getQuestStage(player, Quests.HEROES_QUEST) == 2) { + setQuestStage(player, Quests.HEROES_QUEST, 3) } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt index 851dbfc6d..2bd65f817 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/CharlieTheCookDialogue.kt @@ -1,8 +1,8 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.getQuestStage import core.api.openDialogue -import core.api.openNpcShop import core.api.setQuestStage import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -33,11 +33,11 @@ class CharlieTheCookDialogueFile : DialogueBuilderFile() { .let { optionBuilder -> val continuePath = b.placeholder() - optionBuilder.optionIf("I'm looking for a gherkin..."){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player) } + optionBuilder.optionIf("I'm looking for a gherkin...") { player -> return@optionIf getQuestStage(player, Quests.HEROES_QUEST) >= 3 && HeroesQuest.isPhoenix(player) } .playerl("I'm looking for a gherkin...") .goto(continuePath) - optionBuilder.optionIf("I'm a fellow member of the Phoenix Gang."){ player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player) } + optionBuilder.optionIf("I'm a fellow member of the Phoenix Gang.") { player -> return@optionIf getQuestStage(player, Quests.HEROES_QUEST) >= 3 && HeroesQuest.isPhoenix(player) } .playerl("I'm a fellow member of the Phoenix Gang.") .goto(continuePath) @@ -61,8 +61,8 @@ class CharlieTheCookDialogueFile : DialogueBuilderFile() { .playerl("Mind if I check it out for myself?") .npcl("Not at all! The more minds we have working on the problem, the quicker we get that loot!") .endWith { _, player -> - if (getQuestStage(player, HeroesQuest.questName) == 3) { - setQuestStage(player, HeroesQuest.questName, 4) + if (getQuestStage(player, Quests.HEROES_QUEST) == 3) { + setQuestStage(player, Quests.HEROES_QUEST, 4) } } @@ -74,8 +74,8 @@ class CharlieTheCookDialogueFile : DialogueBuilderFile() { .playerl("Mind if I check it out for myself?") .npcl("Not at all! The more minds we have working on the problem, the quicker we get that loot!") .endWith { _, player -> - if (getQuestStage(player, HeroesQuest.questName) == 3) { - setQuestStage(player, HeroesQuest.questName, 4) + if (getQuestStage(player, Quests.HEROES_QUEST) == 3) { + setQuestStage(player, Quests.HEROES_QUEST, 4) } } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt index 90ece14be..dc9433443 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GarvDialogue.kt @@ -1,8 +1,8 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.* -import core.game.global.action.DoorActionHandler import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items @@ -28,7 +28,7 @@ class GarvDialogue(player: Player? = null) : DialoguePlugin(player){ class GarvDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { // Technically this won't happen since you have to get past Grubor. - b.onQuestStages(HeroesQuest.questName, 0,1,2) + b.onQuestStages(Quests.HEROES_QUEST, 0, 1, 2) .npcl("Hello. What do you want?") .options() .let { optionBuilder -> @@ -40,7 +40,7 @@ class GarvDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(HeroesQuest.questName, 3,4,5,6,100) + b.onQuestStages(Quests.HEROES_QUEST, 3, 4, 5, 6, 100) // .npcl("Oi! Where do you think you're going pal?") - When you click on the door instead of Garv. .npcl("Hello. What do you want?") .playerl("Hi. I'm Hartigen. I've come to work here.") @@ -55,8 +55,8 @@ class GarvDialogueFile : DialogueBuilderFile() { branch2.onValue(1) .npcl("You'd better come in then, Grip will want to talk to you.") .endWith { _, player -> - if(getQuestStage(player, HeroesQuest.questName) == 3) { - setQuestStage(player, HeroesQuest.questName, 4) + if(getQuestStage(player, Quests.HEROES_QUEST) == 3) { + setQuestStage(player, Quests.HEROES_QUEST, 4) } } branch2.onValue(0) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt index 22341f133..c106acdec 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GerrantDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -38,7 +39,7 @@ class GerrantDialogueFile : DialogueBuilderFile() { optionBuilder.option_playerl("Sorry, I'm not interested.") .end() - optionBuilder.optionIf("I want to find out how to catch a lava eel.") { player -> return@optionIf getQuestStage(player, HeroesQuest.questName) >= 1 } + optionBuilder.optionIf("I want to find out how to catch a lava eel.") { player -> return@optionIf getQuestStage(player, Quests.HEROES_QUEST) >= 1 } .playerl("I want to find out how to catch a lava eel.") .npcl("Lava eels, eh? That's a tricky one, that is. You'll need a lava-proof fishing rod. The method for making this would be to take an ordinary fishing rod, and then cover it with fire-proof blamish oil.") .branch { player -> diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt index b1103adea..62d72dc0d 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GripBehavior.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.node.entity.Entity @@ -38,8 +39,8 @@ class GripBehavior : NPCBehavior(NPCs.GRIP_792) { override fun onDeathFinished(self: NPC, killer: Entity) { if (killer is Player) { - if (getQuestStage(killer, HeroesQuest.questName) == 4) { - setQuestStage(killer, HeroesQuest.questName, 5) + if (getQuestStage(killer, Quests.HEROES_QUEST) == 4) { + setQuestStage(killer, Quests.HEROES_QUEST, 5) } val gi = GroundItem( diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt index d1378dd9f..958d893b5 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/GruborDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -26,7 +27,8 @@ class GruborDialogue (player: Player? = null) : DialoguePlugin(player) { class GruborDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onPredicate { player -> getQuestStage(player, HeroesQuest.questName) >= 2 && + b.onPredicate { player -> + getQuestStage(player, Quests.HEROES_QUEST) >= 2 && getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && HeroesQuest.isBlackArm(player) } @@ -34,7 +36,8 @@ class GruborDialogueFile : DialogueBuilderFile() { .npcl("Hi, I'm a little busy right now.") .end() - b.onPredicate { player -> getQuestStage(player, HeroesQuest.questName) >= 2 && + b.onPredicate { player -> + getQuestStage(player, Quests.HEROES_QUEST) >= 2 && !getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && HeroesQuest.isBlackArm(player) } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt index 829dcc8ae..7eadbf5e5 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuest.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import content.region.misthalin.varrock.quest.shieldofarrav.ShieldofArrav import core.api.* import core.game.node.entity.player.Player @@ -12,7 +13,7 @@ import org.rs09.consts.Items * Heroes' Quest */ @Initializable -class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { +class HeroesQuest : Quest(Quests.HEROES_QUEST,75, 74, 1, 188, 0, 1, 15) { /** * Do note: "other players can help you even if they have already finished Heroes' Quest" * 1 - Talked to Achietties to start the quest @@ -34,7 +35,6 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { */ companion object { - const val questName = "Heroes' Quest" const val attributeGruborLetsYouIn = "/save:quest:heroesquest-gruborletsyouin" const val attributeGripTookPapers = "/save:quest:heroesquest-griptookpapers" const val attributeGripSaidDuties = "/save:quest:heroesquest-gripsaidduties" @@ -42,10 +42,10 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { const val attributeHasOpenedChestDoor = "/save:quest:heroesquest-hasopenedchestdoor" fun checkQuestsAreComplete(player: Player): Boolean { - return isQuestComplete(player, "Shield of Arrav") && - isQuestComplete(player, "Lost City") && - isQuestComplete(player, "Merlin's Crystal") && - isQuestComplete(player, "Dragon Slayer") && + return isQuestComplete(player, Quests.SHIELD_OF_ARRAV) && + isQuestComplete(player, Quests.LOST_CITY) && + isQuestComplete(player, Quests.MERLINS_CRYSTAL) && + isQuestComplete(player, Quests.DRAGON_SLAYER) && getQuestPoints(player) >= 55 } @@ -65,10 +65,10 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { hasLevelStat(player, Skills.MINING, 50), hasLevelStat(player, Skills.FISHING, 53), hasLevelStat(player, Skills.COOKING, 53), - isQuestComplete(player, "Shield of Arrav"), - isQuestComplete(player, "Lost City"), - isQuestComplete(player, "Merlin's Crystal"), - isQuestComplete(player, "Dragon Slayer"), + isQuestComplete(player, Quests.SHIELD_OF_ARRAV), + isQuestComplete(player, Quests.LOST_CITY), + isQuestComplete(player, Quests.MERLINS_CRYSTAL), + isQuestComplete(player, Quests.DRAGON_SLAYER), getQuestPoints(player) >= 55, ).all { it } } @@ -85,7 +85,7 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { var line = 12 var stage = getStage(player) - var started = getQuestStage(player!!, questName) > 0 + var started = getQuestStage(player!!, Quests.HEROES_QUEST) > 0 if(!started){ if (checkQuestsAreComplete(player)) { @@ -95,10 +95,10 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { } else { line(player, "I can start this quest by speaking to !!Achietties?? at the", line++) line(player, "!!Heroes' Guild?? located !!North?? of !!Taverly?? after completing", line++) - line(player, "!!The Shield of Arrav??", line++, isQuestComplete(player, "Shield of Arrav")) - line(player, "!!The Lost City??", line++, isQuestComplete(player, "Lost City")) - line(player, "!!Merlin's Crystal??", line++, isQuestComplete(player, "Merlin's Crystal")) - line(player, "!!The Dragon Slayer??", line++, isQuestComplete(player, "Dragon Slayer")) + line(player, "!!The Shield of Arrav??", line++, isQuestComplete(player, Quests.SHIELD_OF_ARRAV)) + line(player, "!!The Lost City??", line++, isQuestComplete(player, Quests.LOST_CITY)) + line(player, "!!Merlin's Crystal??", line++, isQuestComplete(player, Quests.MERLINS_CRYSTAL)) + line(player, "!!The Dragon Slayer??", line++, isQuestComplete(player, Quests.DRAGON_SLAYER)) line(player, "!!and gaining 55 Quest Points??", line++, getQuestPoints(player) >= 55) } line(player, "To complete this quest I need:", line++, false) @@ -217,7 +217,7 @@ class HeroesQuest : Quest("Heroes' Quest",75, 74, 1, 188, 0, 1, 15) { } override fun reset(player: Player) { - if (getQuestStage(player, questName) == 0) { + if (getQuestStage(player, Quests.HEROES_QUEST) == 0) { removeAttribute(player, attributeGruborLetsYouIn) removeAttribute(player, attributeGripTookPapers) removeAttribute(player, attributeGripSaidDuties) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt index aa9e3b7c7..8764e7ba2 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/HeroesQuestListener.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -22,7 +23,7 @@ class HeroesQuestListener: InteractionListener { override fun defineListeners() { // Black arm gang office door. on(Scenery.DOOR_2626, IntType.SCENERY, "open") { player, node -> - if (getQuestStage(player, HeroesQuest.questName) >= 2 && + if (getQuestStage(player, Quests.HEROES_QUEST) >= 2 && getAttribute(player, HeroesQuest.attributeGruborLetsYouIn, false) && HeroesQuest.isBlackArm(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) @@ -34,7 +35,7 @@ class HeroesQuestListener: InteractionListener { // Kitchen entrance on(Scenery.DOOR_2628, IntType.SCENERY, "open") { player, node -> - if (getQuestStage(player, HeroesQuest.questName) >= 3 && HeroesQuest.isPhoenix(player)) { + if (getQuestStage(player, Quests.HEROES_QUEST) >= 3 && HeroesQuest.isPhoenix(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendDialogue(player, "This door is locked.") @@ -44,7 +45,7 @@ class HeroesQuestListener: InteractionListener { // Kitchen wall on(Scenery.WALL_2629, IntType.SCENERY, "push") { player, node -> - if (getQuestStage(player, HeroesQuest.questName) >= 4 && HeroesQuest.isPhoenix(player)) { + if (getQuestStage(player, Quests.HEROES_QUEST) >= 4 && HeroesQuest.isPhoenix(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { openDialogue(player, CharlieTheCookDialogueFile(), NPC(NPCs.CHARLIE_THE_COOK_794)) @@ -54,7 +55,7 @@ class HeroesQuestListener: InteractionListener { // Mansion frontdoor on(Scenery.DOOR_2627, IntType.SCENERY, "open") { player, node -> - if (getQuestStage(player, HeroesQuest.questName) >= 4 && HeroesQuest.isBlackArm(player)) { + if (getQuestStage(player, Quests.HEROES_QUEST) >= 4 && HeroesQuest.isBlackArm(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { openDialogue(player, GarvDialogueFile(), NPC(NPCs.GARV_788)) @@ -127,8 +128,8 @@ class HeroesQuestListener: InteractionListener { if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { sendMessage(player, "You search the chest but find nothing.") } else { - if (getQuestStage(player, HeroesQuest.questName) == 4) { - setQuestStage(player, HeroesQuest.questName, 5) + if (getQuestStage(player, Quests.HEROES_QUEST) == 4) { + setQuestStage(player, Quests.HEROES_QUEST, 5) } sendDialogue(player, "You find two candlesticks in the chest. So that will be one for you, and one for the person who killed Grip for you.") addItemOrDrop(player, Items.PETES_CANDLESTICK_1577, 2) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt index df6bf22c4..f5c3f1d56 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/KatrineDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.* import org.rs09.consts.Items @@ -7,7 +8,7 @@ import org.rs09.consts.Items class KatrineDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { // 0 is handled by default in the old KatrineDialogue. - b.onQuestStages(HeroesQuest.questName, 1) + b.onQuestStages(Quests.HEROES_QUEST, 1) .playerl("Hey.") .npcl("Hey.") .options() @@ -30,15 +31,15 @@ class KatrineDialogueFile : DialogueBuilderFile() { .npcl("Visit our hideout in the alleyway on palm street.") .npcl("To get in you will need to tell them the secret password 'four leaved clover'.") .endWith { _, player -> - if(getQuestStage(player, HeroesQuest.questName) == 1) { - setQuestStage(player, HeroesQuest.questName, 2) + if(getQuestStage(player, Quests.HEROES_QUEST) == 1) { + setQuestStage(player, Quests.HEROES_QUEST, 2) } } } // This is not authentic, she falls back to a boring default conversation, but I guess people might need help during the quest - b.onQuestStages(HeroesQuest.questName, 2,3,4) + b.onQuestStages(Quests.HEROES_QUEST, 2, 3, 4) .playerl("What am I supposed to be doing again?") .npcl("You told me you wanted to get the rank of master thief! Now pay attention.") .npcl("Some of the MOST coveted prizes in thiefdom right now are in the pirate town of Brimhaven on Karamja.") @@ -72,7 +73,7 @@ class KatrineDialogueFile : DialogueBuilderFile() { */ - b.onQuestStages(HeroesQuest.questName, 5) + b.onQuestStages(Quests.HEROES_QUEST, 5) .branch { player -> return@branch if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { 1 } else { 0 } }.let { branch -> @@ -94,8 +95,8 @@ class KatrineDialogueFile : DialogueBuilderFile() { .endWith { _, player -> if (removeItem(player, Items.PETES_CANDLESTICK_1577)) { addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) - if (getQuestStage(player, HeroesQuest.questName) == 5) { - setQuestStage(player, HeroesQuest.questName, 6) + if (getQuestStage(player, Quests.HEROES_QUEST) == 5) { + setQuestStage(player, Quests.HEROES_QUEST, 6) } } } @@ -114,7 +115,7 @@ class KatrineDialogueFile : DialogueBuilderFile() { } // I lost the armband and some stupid default shit. - b.onQuestStages(HeroesQuest.questName, 6) + b.onQuestStages(Quests.HEROES_QUEST, 6) .playerl("I have lost my master thief's armband...") .npcl("Lucky I 'ave a spare ain't it? Don't lose it again.") .endWith { _, player -> diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt index 1f94f41fb..68d236905 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/StravenDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.* import org.rs09.consts.Items @@ -7,7 +8,7 @@ import org.rs09.consts.Items class StravenDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { // 0 is handled by default in the old StravenDialogue. - b.onQuestStages(HeroesQuest.questName, 1) + b.onQuestStages(Quests.HEROES_QUEST, 1) .playerl("How would I go about getting a Master Thief armband?") .npcl("Ooh... tricky stuff. Took me YEARS to get that rank.") .npcl("Well, what some of the more aspiring thieves in our gang are working on right now is to steal some very valuable candlesticks from Scarface Pete - the pirate leader on Karamja.") @@ -15,12 +16,12 @@ class StravenDialogueFile : DialogueBuilderFile() { .npcl("Go talk to our man Alfonse, the waiter in the Shrimp and Parrot.") .npcl("Use the secret word 'gherkin' to show you're one of us.") .endWith { _, player -> - if(getQuestStage(player, HeroesQuest.questName) == 1) { - setQuestStage(player, HeroesQuest.questName, 2) + if(getQuestStage(player, Quests.HEROES_QUEST) == 1) { + setQuestStage(player, Quests.HEROES_QUEST, 2) } } - b.onQuestStages(HeroesQuest.questName, 2,3,4) + b.onQuestStages(Quests.HEROES_QUEST, 2, 3, 4) .playerl("What am I supposed to be doing again?") .npcl("You told me you wanted to get a Master thief's armband! Now pay attention.") .npcl("Some of the more aspiring thieves in our gang are working on right now is to steal some very valuable candlesticks from Scarface Pete - the pirate leader on Karamja.") @@ -30,7 +31,7 @@ class StravenDialogueFile : DialogueBuilderFile() { .end() - b.onQuestStages(HeroesQuest.questName, 5) + b.onQuestStages(Quests.HEROES_QUEST, 5) .branch { player -> return@branch if (inInventory(player, Items.PETES_CANDLESTICK_1577)) { 1 } else { 0 } }.let { branch -> @@ -44,8 +45,8 @@ class StravenDialogueFile : DialogueBuilderFile() { .endWith { _, player -> if (removeItem(player, Items.PETES_CANDLESTICK_1577)) { addItemOrDrop(player, Items.THIEVES_ARMBAND_1579) - if (getQuestStage(player, HeroesQuest.questName) == 5) { - setQuestStage(player, HeroesQuest.questName, 6) + if (getQuestStage(player, Quests.HEROES_QUEST) == 5) { + setQuestStage(player, Quests.HEROES_QUEST, 6) } } } @@ -61,7 +62,7 @@ class StravenDialogueFile : DialogueBuilderFile() { } // I lost the armband and some stupid default shit. - b.onQuestStages(HeroesQuest.questName, 6) + b.onQuestStages(Quests.HEROES_QUEST, 6) .playerl("I'm afraid I've lost my master thief's armband.") .npcl("Lucky for you I have a spare. Don't lose it again!") .endWith { _, player -> diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt index 14ffa3073..12561ad44 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/heroesquest/TrobertDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.heroesquest +import content.data.Quests import core.api.* import core.game.dialogue.* import core.game.node.entity.player.Player @@ -27,13 +28,13 @@ class TrobertDialogue(player: Player? = null) : DialoguePlugin(player){ class TrobertDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { // Technically this won't happen since you have to get past Grubor. - b.onQuestStages(HeroesQuest.questName, 0,1) + b.onQuestStages(Quests.HEROES_QUEST, 0, 1) .npcl("Welcome to our Brimhaven headquarters. I'm Trobert and I'm in charge here.") .playerl("Pleased to meet you.") .npcl("Likewise.") .end() - b.onQuestStages(HeroesQuest.questName, 2) + b.onQuestStages(Quests.HEROES_QUEST, 2) .npcl("Welcome to our Brimhaven headquarters. I'm Trobert and I'm in charge here.") .options() .let { optionBuilder -> @@ -56,8 +57,8 @@ class TrobertDialogueFile : DialogueBuilderFile() { .npcl("Good good. Well, here's the ID papers, take them and introduce yourself to the guards at Scarface Pete's mansion, we'll have that treasure in no time.") .endWith { _, player -> addItemOrDrop(player, Items.ID_PAPERS_1584) - if(getQuestStage(player, HeroesQuest.questName) == 2) { - setQuestStage(player, HeroesQuest.questName, 3) + if(getQuestStage(player, Quests.HEROES_QUEST) == 2) { + setQuestStage(player, Quests.HEROES_QUEST, 3) } } @@ -66,7 +67,7 @@ class TrobertDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(HeroesQuest.questName, 3,4,5) + b.onQuestStages(Quests.HEROES_QUEST, 3, 4, 5) .branch { player -> return@branch if (inInventory(player, Items.ID_PAPERS_1584)) { 1 } else { 0 } }.let { branch -> @@ -82,7 +83,7 @@ class TrobertDialogueFile : DialogueBuilderFile() { } } - b.onQuestStages(HeroesQuest.questName, 6,100) + b.onQuestStages(Quests.HEROES_QUEST, 6, 100) .npcl("How's it going?") .playerl("Fine, thanks.") .end() diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/BerryNpc.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/BerryNpc.kt index 116a95063..0b04d9ba1 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/BerryNpc.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/BerryNpc.kt @@ -1,8 +1,8 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.isQuestInProgress import core.api.produceGroundItem -import core.api.transformNpc import core.game.node.entity.Entity import core.game.node.entity.combat.CombatStyle import core.game.node.entity.npc.AbstractNPC @@ -44,7 +44,7 @@ class BerryNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id, locati } override fun finalizeDeath(killer: Entity?) { - if (isQuestInProgress(killer as Player, TrollStronghold.questName, 8, 10)) { + if (isQuestInProgress(killer as Player, Quests.TROLL_STRONGHOLD, 8, 10)) { produceGroundItem(killer, Items.CELL_KEY_2_3137, 1, this.location) } super.finalizeDeath(killer) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogue.kt index 2a2b2df0a..a1d76a63e 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -13,7 +14,7 @@ import org.rs09.consts.NPCs @Initializable class DadDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when (getQuestStage(player!!, TrollStronghold.questName)) { + when (getQuestStage(player!!, Quests.TROLL_STRONGHOLD)) { in 3..4 -> { when (stage) { START_DIALOGUE -> npcl(FacialExpression.OLD_HAPPY, "What tiny human do in troll arena? Dad challenge human to fight!").also { stage++ } @@ -27,7 +28,7 @@ class DadDialogue(player: Player? = null) : DialoguePlugin(player) { 3 -> npcl(FacialExpression.OLD_HAPPY, "Tiny human brave. Dad squish!").also { stage++ } 4 -> npc!!.attack(player).also { npc!!.skills.lifepoints = npc!!.skills.maximumLifepoints // Reset dad to max hitpoints. - setQuestStage(player!!, TrollStronghold.questName, 4) + setQuestStage(player!!, Quests.TROLL_STRONGHOLD, 4) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogueFile.kt index 69b9d5334..4428bf902 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.setQuestStage import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -13,14 +14,14 @@ class DadDialogueFile(private val dialogueNum: Int = 0) : DialogueFile() { 1 -> when (stage) { START_DIALOGUE -> npcl(FacialExpression.OLD_HAPPY, "No human pass through arena without defeating Dad!").also { stage = END_DIALOGUE - setQuestStage(player!!, TrollStronghold.questName, 3) + setQuestStage(player!!, Quests.TROLL_STRONGHOLD, 3) } } 2 -> when (stage) { START_DIALOGUE -> npcl(FacialExpression.OLD_NORMAL, "Tiny human brave. Dad squish!").also { stage++ } 1 -> npc!!.attack(player).also { npc!!.skills.lifepoints = npc!!.skills.maximumLifepoints // Reset dad to max hitpoints. - setQuestStage(player!!, TrollStronghold.questName, 4) + setQuestStage(player!!, Quests.TROLL_STRONGHOLD, 4) stage = END_DIALOGUE } } @@ -31,7 +32,7 @@ class DadDialogueFile(private val dialogueNum: Int = 0) : DialogueFile() { Topic(FacialExpression.ANGRY_WITH_SMILE, "I'm not done yet! Prepare to die!", 2) ) 2 -> player!!.attack(npc).also { - setQuestStage(player!!, TrollStronghold.questName, 5) + setQuestStage(player!!, Quests.TROLL_STRONGHOLD, 5) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadNpc.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadNpc.kt index d7c5e58cd..f489aa1ed 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadNpc.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DadNpc.kt @@ -1,7 +1,7 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.* -import core.game.node.Node import core.game.node.entity.Entity import core.game.node.entity.combat.BattleState import core.game.node.entity.combat.CombatStyle @@ -27,7 +27,7 @@ class DadNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id, location val player = entity.asPlayer() // Attack Dad. If quest is done, you cannot attack Dad. - when (getQuestStage(player, TrollStronghold.questName)) { + when (getQuestStage(player, Quests.TROLL_STRONGHOLD)) { 3 -> openDialogue(player, DadDialogueFile(2), this.asNpc()).also { return false } 4 -> { return attackable } in 5 .. 100 -> sendMessage(player, "You don't need to fight him again.").also { return false } @@ -44,8 +44,8 @@ class DadNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id, location if (opponent.skills.lifepoints < 30) { player.properties.combatPulse.stop() opponent.properties.combatPulse.stop() - if (getQuestStage(player!!.asPlayer(), TrollStronghold.questName) == 4){ - setQuestStage(player!!.asPlayer(), TrollStronghold.questName, 5) + if (getQuestStage(player!!.asPlayer(), Quests.TROLL_STRONGHOLD) == 4){ + setQuestStage(player!!.asPlayer(), Quests.TROLL_STRONGHOLD, 5) } submitWorldPulse(object : Pulse(){ var counter = 0 @@ -64,8 +64,8 @@ class DadNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id, location override fun finalizeDeath(killer: Entity?) { // In case Dad gets one shotted to death. super.finalizeDeath(killer) - if (getQuestStage(killer!!.asPlayer(), TrollStronghold.questName) == 4){ - setQuestStage(killer!!.asPlayer(), TrollStronghold.questName, 5) + if (getQuestStage(killer!!.asPlayer(), Quests.TROLL_STRONGHOLD) == 4){ + setQuestStage(killer!!.asPlayer(), Quests.TROLL_STRONGHOLD, 5) } } override fun handleTickActions() { diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DenulthDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DenulthDialogueFile.kt index 45318ea53..2575fc4b6 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DenulthDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DenulthDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -14,7 +15,7 @@ import org.rs09.consts.Items */ class DenulthDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, TrollStronghold.questName)) { + when (getQuestStage(player!!, Quests.TROLL_STRONGHOLD)) { in 1..7 -> { when (stage) { START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "How are you getting on with rescuing Godric?").also { stage++ } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt index aa9615ea7..0719be236 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.finishQuest import core.api.getQuestStage import core.game.dialogue.DialogueFile @@ -10,7 +11,7 @@ import core.tools.START_DIALOGUE class DunstanDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, TrollStronghold.questName)) { + when (getQuestStage(player!!, Quests.TROLL_STRONGHOLD)) { in 1..10 -> { when (stage) { START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "Have you managed to rescue Godric yet?").also { stage++ } @@ -35,7 +36,7 @@ class DunstanDialogueFile : DialogueFile() { 3 -> npcl(FacialExpression.FRIENDLY, "I have very little to offer you by way of thanks, but perhaps you will accept these family heirlooms. They were found by my great-great-grandfather, but we still don't have any idea what they do.").also { stage++ } 4 -> { stage = END_DIALOGUE - finishQuest(player!!, TrollStronghold.questName) + finishQuest(player!!, Quests.TROLL_STRONGHOLD) } } } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollGeneralsNpc.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollGeneralsNpc.kt index 1a0488e69..cee11ddfc 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollGeneralsNpc.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollGeneralsNpc.kt @@ -1,10 +1,7 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold -import content.region.kandarin.quest.grandtree.ForemanDialogue -import content.region.kandarin.quest.grandtree.TheGrandTree +import content.data.Quests import core.api.* -import core.game.interaction.IntType -import core.game.interaction.InteractionListener import core.game.node.entity.Entity import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player @@ -25,7 +22,7 @@ class TrollGeneralsNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id } override fun finalizeDeath(killer: Entity?) { - if(isQuestInProgress(killer as Player, TrollStronghold.questName, 1, 7)) { + if(isQuestInProgress(killer as Player, Quests.TROLL_STRONGHOLD, 1, 7)) { produceGroundItem(killer, Items.PRISON_KEY_3135, 1, this.location) } super.finalizeDeath(killer) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt index 1a3e1657b..6630bfa14 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStronghold.kt @@ -1,51 +1,37 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau import core.api.* import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Troll Stronghold Quest * @author ovenbread */ @Initializable -class TrollStronghold : Quest("Troll Stronghold",128, 127, 1, 317, 0, 1, 50) { +class TrollStronghold : Quest(Quests.TROLL_STRONGHOLD,128, 127, 1, 317, 0, 1, 50) { - /** - * 1 - Talked to Denulth to start the quest - * 3 - Enter the Arena with Dad - * 4 - Start fighting Dad - * 5 - Dad surrenders or gets killed, allowed to exit the Arena - * 8 - Unlocks Prison Gate - * 9 - Unlocked Mad Eadgar's cell - * 10 - Unlocked Godric's cell - * 11 - Unlocked both Mad Eadgar's and Godric's cell - * 100 - Finish at Dunstan - */ - companion object { - const val questName = "Troll Stronghold" - } override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 12 var stage = getStage(player) - var started = getQuestStage(player!!, questName) > 0 + var started = getQuestStage(player!!, Quests.TROLL_STRONGHOLD) > 0 if(!started){ line(player, "I can start this quest by speaking to !!Denulth?? in his tent at", line++) line(player, "the !!Imperial Guard camp?? in !!Burthorpe?? after completing the", line++) - line(player, "!!Death Plateau Quest??", line++, isQuestComplete(player, DeathPlateau.questName)) + line(player, "!!Death Plateau Quest??", line++, isQuestComplete(player, Quests.DEATH_PLATEAU)) line++ line(player, "To complete this quest I need:", line++) line(player, "Level 15 Agility.", line++, hasLevelStat(player, Skills.AGILITY, 15)) line(player, "I also need to be able to defeat a !!level 113 Troll??.", line++) line(player, "Level 30 Thieving might be useful.", line++, hasLevelStat(player, Skills.THIEVING, 30)) - if (isQuestComplete(player, DeathPlateau.questName) && hasLevelStat(player, Skills.AGILITY, 15) && hasLevelStat(player, Skills.THIEVING, 30)) { + if (isQuestComplete(player, Quests.DEATH_PLATEAU) && hasLevelStat(player, Skills.AGILITY, 15) && hasLevelStat(player, Skills.THIEVING, 30)) { line(player, "I have all the requirements to start this quest.", line++) } } else { diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStrongholdListener.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStrongholdListener.kt index 9e03991ab..f276b3944 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStrongholdListener.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TrollStrongholdListener.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold +import content.data.Quests import core.api.* import core.game.global.action.DoorActionHandler import core.game.interaction.IntType @@ -22,12 +23,12 @@ class TrollStrongholdListener: InteractionListener { // Entrance to arena with Dad in it. on(intArrayOf(Scenery.ARENA_ENTRANCE_3782, Scenery.ARENA_ENTRANCE_3783), IntType.SCENERY, "open"){ player, node -> // Only get the dialogue once. - if (getQuestStage(player, TrollStronghold.questName) == 1) { + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 1) { openDialogue(player, DadDialogueFile(1), findNPC(NPCs.DAD_1125)!!) } // Only allow players through when they start Troll Stronghold. // No one is allowed to go to GWD unless they start the Troll Stronghold quest. - if (getQuestStage(player, TrollStronghold.questName) > 0) { + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) > 0) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendMessage(player, "You need to start the Troll Stronghold quest.") @@ -37,7 +38,7 @@ class TrollStrongholdListener: InteractionListener { // Not allowed to exit arena into the troll stronghold until Dad is defeated. on(intArrayOf(Scenery.ARENA_EXIT_3785, Scenery.ARENA_EXIT_3786), IntType.SCENERY, "open"){ player, node -> - if (getQuestStage(player, TrollStronghold.questName) < 5){ + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) < 5){ openDialogue(player, DadDialogueFile(1), findNPC(NPCs.DAD_1125)!!) } else { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) @@ -47,12 +48,12 @@ class TrollStrongholdListener: InteractionListener { // Key to unlock the prison door on(Scenery.PRISON_DOOR_3780, IntType.SCENERY, "unlock"){ player, node -> - if (getQuestStage(player, TrollStronghold.questName) >= 8){ + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) >= 8){ DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { if (inInventory(player, Items.PRISON_KEY_3135)) { - if (getQuestStage(player, TrollStronghold.questName) == 5) { - setQuestStage(player, TrollStronghold.questName, 8) + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 5) { + setQuestStage(player, Quests.TROLL_STRONGHOLD, 8) } if (removeItem(player, Items.PRISON_KEY_3135)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) @@ -84,7 +85,7 @@ class TrollStrongholdListener: InteractionListener { 3 -> { val success: Boolean = success(player, Skills.THIEVING) if(success){ - if(isQuestInProgress(player, TrollStronghold.questName, 8, 10)) { + if(isQuestInProgress(player, Quests.TROLL_STRONGHOLD, 8, 10)) { addItem(player, Items.CELL_KEY_1_3136) sendMessage(player, "You find a small key on Twig.") } else { @@ -124,7 +125,7 @@ class TrollStrongholdListener: InteractionListener { 3 -> { val success: Boolean = success(player, Skills.THIEVING) if(success){ - if(isQuestInProgress(player, TrollStronghold.questName, 8, 10)) { + if(isQuestInProgress(player, Quests.TROLL_STRONGHOLD, 8, 10)) { addItem(player, Items.CELL_KEY_2_3137) sendMessage(player, "You find a small key on Berry.") } else { @@ -149,10 +150,10 @@ class TrollStrongholdListener: InteractionListener { fun unlockMadEadgarCellDoor(player: Player, node: Node) { if (inInventory(player, Items.CELL_KEY_1_3136)){ sendMessage(player, "You unlock the cell door.") - if (getQuestStage(player, TrollStronghold.questName) == 8) { - setQuestStage(player, TrollStronghold.questName, 9) - } else if (getQuestStage(player, TrollStronghold.questName) == 10) { - setQuestStage(player, TrollStronghold.questName, 11) + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 8) { + setQuestStage(player, Quests.TROLL_STRONGHOLD, 9) + } else if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 10) { + setQuestStage(player, Quests.TROLL_STRONGHOLD, 11) } // Animate Mad Eadgar leaving cell. val npc = findNPC(NPCs.EADGAR_1113)!! @@ -219,10 +220,10 @@ class TrollStrongholdListener: InteractionListener { fun unlockGodricCellDoor(player: Player, node: Node) { if (inInventory(player, Items.CELL_KEY_2_3137)){ sendMessage(player, "You unlock the cell door.") - if (getQuestStage(player, TrollStronghold.questName) == 8) { - setQuestStage(player, TrollStronghold.questName, 10) - } else if (getQuestStage(player, TrollStronghold.questName) == 9) { - setQuestStage(player, TrollStronghold.questName, 11) + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 8) { + setQuestStage(player, Quests.TROLL_STRONGHOLD, 10) + } else if (getQuestStage(player, Quests.TROLL_STRONGHOLD) == 9) { + setQuestStage(player, Quests.TROLL_STRONGHOLD, 11) } // Animate Godric leaving cell. val npc = findNPC(NPCs.GODRIC_1114)!! @@ -292,7 +293,7 @@ class TrollStrongholdListener: InteractionListener { // Reentry Secret Door on(Scenery.SECRET_DOOR_3762, IntType.SCENERY, "open"){ player, _ -> - if (getQuestStage(player, TrollStronghold.questName) >= 8) { + if (getQuestStage(player, Quests.TROLL_STRONGHOLD) >= 8) { player.properties.teleportLocation = Location.create(2824, 10050, 0) } else { sendMessage(player, "The door is locked.") diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TwigNpc.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TwigNpc.kt index 97e253d71..deb316aeb 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TwigNpc.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/TwigNpc.kt @@ -1,16 +1,14 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold -import core.api.getQuestStage +import content.data.Quests import core.api.isQuestInProgress import core.api.produceGroundItem -import core.api.transformNpc import core.game.node.entity.Entity import core.game.node.entity.combat.CombatStyle import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player import core.game.world.map.Location import core.plugin.Initializable -import core.tools.RandomFunction import org.rs09.consts.Items import org.rs09.consts.NPCs @@ -46,7 +44,7 @@ class TwigNpc(id: Int = 0, location: Location? = null) : AbstractNPC(id, locatio } override fun finalizeDeath(killer: Entity?) { - if (isQuestInProgress(killer as Player, TrollStronghold.questName, 8, 10)) { + if (isQuestInProgress(killer as Player, Quests.TROLL_STRONGHOLD, 8, 10)) { produceGroundItem(killer, Items.CELL_KEY_1_3136, 1, this.location) } super.finalizeDeath(killer) diff --git a/Server/src/main/content/region/asgarnia/dialogue/OracleDialogue.java b/Server/src/main/content/region/asgarnia/dialogue/OracleDialogue.java index a4a58570c..b811dbc74 100644 --- a/Server/src/main/content/region/asgarnia/dialogue/OracleDialogue.java +++ b/Server/src/main/content/region/asgarnia/dialogue/OracleDialogue.java @@ -5,6 +5,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the oracle dialogue plugin related to dragon slayer. @@ -43,7 +44,7 @@ public final class OracleDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); switch (quest.getStage(player)) { case 20: player("I seek a piece of the map to the island of Crandor."); diff --git a/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java b/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java index 761c0977c..af9e253f3 100644 --- a/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java +++ b/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for thurgo. @@ -77,7 +78,7 @@ public final class ThuroDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("The Knight's Sword"); + quest = player.getQuestRepository().getQuest(Quests.THE_KNIGHTS_SWORD); player.removeAttribute("thurgo:1"); switch (quest.getStage(player)) { default: diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/DoricDialogue.kt b/Server/src/main/content/region/asgarnia/falador/dialogue/DoricDialogue.kt index a829c840b..0d8e029eb 100644 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/DoricDialogue.kt +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/DoricDialogue.kt @@ -16,12 +16,13 @@ import core.game.world.map.Location import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class DoricDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - val qStage = getQuestStage(player, "Doric's Quest") + val qStage = getQuestStage(player, Quests.DORICS_QUEST) if(qStage == 0) { npcl(FacialExpression.OLD_NORMAL, "Hello traveller, what brings you to my humble smithy?").also { stage = 0 } } else if(qStage in 1..99) { diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/FaladorSquireDialogue.java b/Server/src/main/content/region/asgarnia/falador/dialogue/FaladorSquireDialogue.java index 5d026893d..8fe25153e 100644 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/FaladorSquireDialogue.java +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/FaladorSquireDialogue.java @@ -10,6 +10,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.world.GameWorld; +import content.data.Quests; /** * Represents the falador squire dialogue plugin. @@ -59,7 +60,7 @@ public final class FaladorSquireDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("The Knight's Sword"); + quest = player.getQuestRepository().getQuest(Quests.THE_KNIGHTS_SWORD); interpreter.sendOptions("What do you want to do?", "Chat", "Talk about the Falador Achievement Diary"); stage = -1; replacementReward = AchievementDiary.canReplaceReward(player, DiaryType.FALADOR, level); diff --git a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt index 25c8bfbf7..70abbe778 100644 --- a/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt +++ b/Server/src/main/content/region/asgarnia/falador/dialogue/SirTiffyCashienDialogue.kt @@ -1,6 +1,6 @@ package content.region.asgarnia.falador.dialogue -import content.region.asgarnia.falador.quest.recruitmentdrive.RecruitmentDrive +import content.data.Quests import content.region.asgarnia.falador.quest.recruitmentdrive.SirTiffyCashienDialogueFile import core.ServerConstants import core.api.* @@ -20,13 +20,13 @@ class SirTiffyCashienDialogue (player: Player? = null) : DialoguePlugin(player) override fun handle(interfaceId: Int, buttonId: Int): Boolean { // Completed Recruitment Drive & Start Wanted!! Quest - if (isQuestComplete(player!!, RecruitmentDrive.questName)) { + if (isQuestComplete(player!!, Quests.RECRUITMENT_DRIVE)) { openDialogue(player, SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile(), npc) return true } // Recruitment Drive Quest - if (isQuestInProgress(player!!, RecruitmentDrive.questName, 1, 99)) { + if (isQuestInProgress(player!!, Quests.RECRUITMENT_DRIVE, 1, 99)) { openDialogue(player, SirTiffyCashienDialogueFile(), npc) return true } diff --git a/Server/src/main/content/region/asgarnia/falador/quest/TheKnightsSword.java b/Server/src/main/content/region/asgarnia/falador/quest/TheKnightsSword.java index 535885464..70ca79515 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/TheKnightsSword.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/TheKnightsSword.java @@ -5,6 +5,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents The KnightSword quest. @@ -23,7 +24,7 @@ public class TheKnightsSword extends Quest { * Constructs a new {@code TheKnightsSword} {@code Object}. */ public TheKnightsSword() { - super("The Knight's Sword", 22, 21, 1, 122, 0, 1, 7); + super(Quests.THE_KNIGHTS_SWORD, 22, 21, 1, 122, 0, 1, 7); } @Override diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKCabbagePlugin.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKCabbagePlugin.java index 36684ff28..1fdcd3565 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKCabbagePlugin.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKCabbagePlugin.java @@ -5,6 +5,7 @@ import core.game.interaction.UseWithHandler; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the plugin used to send the cabbage down the hole. @@ -29,7 +30,7 @@ public class BKCabbagePlugin extends UseWithHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest("Black Knights' Fortress"); + final Quest quest = player.getQuestRepository().getQuest(Quests.BLACK_KNIGHTS_FORTRESS); if (quest.getStage(player) == 20) { if (event.getUsedItem().getId() == 1967) { player.getDialogueInterpreter().sendDialogue("This is the wrong sort of cabbage!"); diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKListenDialogue.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKListenDialogue.java index df55f800b..b8d4dd509 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKListenDialogue.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BKListenDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the dialogue of listening throug a grill during the black knights' @@ -117,7 +118,7 @@ public final class BKListenDialogue extends DialoguePlugin { stage = 8; break; case 8: - player.getQuestRepository().getQuest("Black Knights' Fortress").setStage(player, 20); + player.getQuestRepository().getQuest(Quests.BLACK_KNIGHTS_FORTRESS).setStage(player, 20); end(); break; case 10: @@ -142,7 +143,7 @@ public final class BKListenDialogue extends DialoguePlugin { break; case 15: if (player.getInventory().remove(CABBAGE)) { - player.getQuestRepository().getQuest("Black Knights' Fortress").setStage(player, 30); + player.getQuestRepository().getQuest(Quests.BLACK_KNIGHTS_FORTRESS).setStage(player, 30); interpreter.sendDialogues(player, FacialExpression.HAPPY, "Looks like my work here is done. Seems like that's", "successfully sabotaged their little secret weapon plan."); stage = 16; } diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BlackKnightsFortress.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BlackKnightsFortress.java index 6e5da0e7d..a3a1bf405 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BlackKnightsFortress.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/BlackKnightsFortress.java @@ -5,6 +5,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the black knights fortress quest. @@ -23,7 +24,7 @@ public final class BlackKnightsFortress extends Quest { * Constructs a new {@Code BlackKnightsFortress} {@Code Object} */ public BlackKnightsFortress() { - super("Black Knights' Fortress", 14, 13, 3, 130, 0, 1, 4); + super(Quests.BLACK_KNIGHTS_FORTRESS, 14, 13, 3, 130, 0, 1, 4); } @Override diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java index ae5904dde..93901c19e 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/SirAmikVarzeDialogue.java @@ -10,6 +10,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import static core.api.ContentAPIKt.openDialogue; +import content.data.Quests; /** * Represents the sir amik varze dialogue. @@ -48,7 +49,7 @@ public class SirAmikVarzeDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Black Knights' Fortress"); + quest = player.getQuestRepository().getQuest(Quests.BLACK_KNIGHTS_FORTRESS); switch (quest.getStage(player)) { case 30: interpreter.sendDialogues(player, FacialExpression.HAPPY, "I have ruined the Black Knights' invincibility potion."); diff --git a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricDoricsQuestDialogue.kt b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricDoricsQuestDialogue.kt index 9857961b6..3c34fca1f 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricDoricsQuestDialogue.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricDoricsQuestDialogue.kt @@ -4,12 +4,11 @@ import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.dialogue.Topic -import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.END_DIALOGUE import org.rs09.consts.Items -import org.rs09.consts.NPCs +import content.data.Quests class DoricDoricsQuestDialogue(private val dStage: Int) : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { @@ -40,7 +39,7 @@ class DoricDoricsQuestDialogue(private val dStage: Int) : DialogueFile() { 40 -> npc(FacialExpression.OLD_NORMAL, "Clay is what I use more than anything, to make casts.", "Could you get me 6 clay, 4 copper ore, and 2 iron ore,", "please? I could pay a little, and let you use my anvils.", "Take this pickaxe with you just in case you need it.").also { stage++ } 41 -> { playerl(FacialExpression.FRIENDLY, "Certainly, I'll be right back!") - startQuest(player, "Doric's Quest") + startQuest(player, Quests.DORICS_QUEST) if(!inInventory(player, Items.BRONZE_PICKAXE_1265)) addItemOrDrop(player, Items.BRONZE_PICKAXE_1265) stage = END_DIALOGUE } @@ -65,7 +64,7 @@ class DoricDoricsQuestDialogue(private val dStage: Int) : DialogueFile() { 3 -> { if(removeItem(player, Item(Items.CLAY_434, 6)) && removeItem(player, Item(Items.COPPER_ORE_436, 4)) && removeItem(player, Item(Items.IRON_ORE_440, 2))) { sendItemDialogue(player, Items.COPPER_ORE_436, "You hand the clay, copper, and iron to Doric.") - finishQuest(player, "Doric's Quest") + finishQuest(player, Quests.DORICS_QUEST) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt index cc189df02..0bc49f173 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/doricsquest/DoricsQuest.kt @@ -7,9 +7,10 @@ import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Components import org.rs09.consts.Items +import content.data.Quests @Initializable -class DoricsQuest : Quest("Doric's Quest", 17, 16, 1, 31, 0, 1, 100) { +class DoricsQuest : Quest(Quests.DORICS_QUEST, 17, 16, 1, 31, 0, 1, 100) { override fun newInstance(`object`: Any?): Quest { return this } override fun drawJournal(player: Player?, stage: Int) { diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt index 6a7b174cd..f608fc923 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Recruitment Drive Quest @@ -22,9 +23,8 @@ import org.rs09.consts.Items * 100 - Finish by talking to Tiffy. */ @Initializable -class RecruitmentDrive : Quest("Recruitment Drive", 103, 102, 1, 496, 0, 1, 2) { +class RecruitmentDrive : Quest(Quests.RECRUITMENT_DRIVE, 103, 102, 1, 496, 0, 1, 2) { companion object { - const val questName = "Recruitment Drive" const val attributeOriginalGender = "/save:quest:recruitmentdrive-originalgender" // Stage state: (0: reset), (1: passed), (-1: failed) @@ -43,17 +43,17 @@ class RecruitmentDrive : Quest("Recruitment Drive", 103, 102, 1, 496, 0, 1, 2) { var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.RECRUITMENT_DRIVE) > 0 if(!started){ line(player, "I can start this quest by speaking to !!Sir Amik Varze??,", line++) line(player, "upstairs in !!Falador Castle,??", line++) - if (isQuestComplete(player, "Druidic Ritual")) { + if (isQuestComplete(player, Quests.DRUIDIC_RITUAL)) { line(player, "with the Druidic Ritual Quest completed,", line++, true) } else { line(player, "with the !!Druidic Ritual Quest?? completed,", line++) } - if (isQuestComplete(player, "Black Knights' Fortress")) { + if (isQuestComplete(player, Quests.BLACK_KNIGHTS_FORTRESS)) { line(player, "and since I have completed the Black Knights' Fortress", line++, true) line(player, "Quest.", line++, true) } else { diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt index d3494000a..39afdf1f4 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDriveListeners.kt @@ -1,7 +1,6 @@ package content.region.asgarnia.falador.quest.recruitmentdrive -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau -import core.ServerConstants +import content.data.Quests import core.api.* import core.game.activity.Cutscene import core.game.dialogue.FacialExpression @@ -12,7 +11,6 @@ import core.game.interaction.QueueStrength import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player -import core.game.node.item.Item import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction @@ -255,8 +253,8 @@ class RecruitmentDriveListeners : InteractionListener { override fun runStage(stage: Int) { when (stage) { 0 -> { - if (getQuestStage(player, RecruitmentDrive.questName) == 2) { - setQuestStage(player, RecruitmentDrive.questName, 3) + if (getQuestStage(player, Quests.RECRUITMENT_DRIVE) == 2) { + setQuestStage(player, Quests.RECRUITMENT_DRIVE, 3) } closeDialogue(player) fadeToBlack() diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt index 754b3de4b..a9aacdc6b 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirAmikVarzeDialogueFile.kt @@ -2,14 +2,15 @@ package content.region.asgarnia.falador.quest.recruitmentdrive import core.api.* import core.game.dialogue.* +import content.data.Quests class SirAmikVarzeDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(RecruitmentDrive.questName, 0) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 0) .npcl(FacialExpression.FRIENDLY,"Hello, friend!") .playerl(FacialExpression.THINKING, "Do you have any other quests for me to do?") - .branch { player -> if(isQuestComplete(player, "Black Knights' Fortress") && isQuestComplete(player, "Druidic Ritual")) { 1 } else { 0 } } + .branch { player -> if(isQuestComplete(player, Quests.BLACK_KNIGHTS_FORTRESS) && isQuestComplete(player, Quests.DRUIDIC_RITUAL)) { 1 } else { 0 } } .let{ branch -> // Failure branch branch.onValue(0) @@ -27,9 +28,9 @@ class SirAmikVarzeDialogueFile : DialogueBuilderFile() { .npc("They are the Temple Knights, and you are to", "meet Sir Tiffy Cashien in Falador park for testing", "immediately.") .playerl("Okey dokey, I'll go do that then.") .endWith { _, player -> - if(getQuestStage(player, RecruitmentDrive.questName) == 0) { + if(getQuestStage(player, Quests.RECRUITMENT_DRIVE) == 0) { setAttribute(player, RecruitmentDrive.attributeOriginalGender, player.isMale) - setQuestStage(player, RecruitmentDrive.questName, 1) + setQuestStage(player, Quests.RECRUITMENT_DRIVE, 1) } } optionBuilder.option_playerl("No thanks") @@ -44,14 +45,14 @@ class SirAmikVarzeDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(RecruitmentDrive.questName, 1,2,3,4) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 1, 2, 3, 4) .npcl(FacialExpression.FRIENDLY,"Hello, friend!") .playerl(FacialExpression.THINKING, "Can I just skip the test to become a Temple Knight?") .npcl("No, I'm afraid not. I suggest you go meet Sir Tiffy in Falador Park, he will be expecting you.") .end() // This should be after the Wanted Quest, but is the placeholder until that quest is implemented. - b.onQuestStages(RecruitmentDrive.questName, 100) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 100) .npcl(FacialExpression.FRIENDLY,"Hello, friend!") .npcl(FacialExpression.FRIENDLY,"Well @name, now that you are a White Knight, I expect you should be out there hunting Black Knights for us!") .options().let { optionBuilder -> diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt index 0d057494b..9bd2ecf93 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/SirTiffyCashienDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.falador.quest.recruitmentdrive +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -8,7 +9,7 @@ import org.rs09.consts.Items class SirTiffyCashienDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(RecruitmentDrive.questName, 1) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 1) .player(FacialExpression.FRIENDLY, "Sir Amik Varze sent me to meet you here for some", "sort of testing...") .npc(FacialExpression.FRIENDLY, "Ah, @name!", "Amik told me all about you, dontchaknow!", "Spliffing job you you did with the old Black Knights there,", "absolutely first class.") .playerl(FacialExpression.GUILTY, "...Thanks I think.") @@ -84,13 +85,13 @@ class SirTiffyCashienDialogueFile : DialogueBuilderFile() { } }.endWith { _, player -> - if (getQuestStage(player, RecruitmentDrive.questName) == 1) { - setQuestStage(player, RecruitmentDrive.questName, 2) + if (getQuestStage(player, Quests.RECRUITMENT_DRIVE) == 1) { + setQuestStage(player, Quests.RECRUITMENT_DRIVE, 2) } RecruitmentDriveListeners.shuffleStages(player) RecruitmentDriveListeners.StartTestCutscene(player).start() } - b.onQuestStages(RecruitmentDrive.questName, 2) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 2) .npc(FacialExpression.FRIENDLY, "Ah, what ho!", "Back for another go at the old testing, what?") .options().let { optionBuilder -> val continuePath = b.placeholder() @@ -115,7 +116,7 @@ class SirTiffyCashienDialogueFile : DialogueBuilderFile() { .end() return@let continuePath.builder() } - b.onQuestStages(RecruitmentDrive.questName, 3) + b.onQuestStages(Quests.RECRUITMENT_DRIVE, 3) .npc(FacialExpression.HAPPY, "Oh, jolly well done!", "Your performance will need to be evaluated by Sir Vey", "personally, but I don't think it's going too far ahead of", "myself to welcome you to the team!") .endWith { _, player -> // Get a voucher and $3000 to change gender if you did do it during the quest. @@ -124,7 +125,7 @@ class SirTiffyCashienDialogueFile : DialogueBuilderFile() { addItemOrDrop(player, Items.COINS_995, 3000) } removeAttribute(player, RecruitmentDrive.attributeOriginalGender) - finishQuest(player, RecruitmentDrive.questName) + finishQuest(player, Quests.RECRUITMENT_DRIVE) } } } diff --git a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GDiplomacyCutscene.java b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GDiplomacyCutscene.java index 487467ae2..3743a5c2c 100644 --- a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GDiplomacyCutscene.java +++ b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GDiplomacyCutscene.java @@ -1,5 +1,6 @@ package content.region.asgarnia.goblinvillage.quest.goblindiplomacy; +import content.data.Quests; import core.game.component.Component; import core.game.node.entity.player.link.emote.Emotes; import core.game.activity.ActivityManager; @@ -54,7 +55,7 @@ public final class GDiplomacyCutscene extends CutscenePlugin { @Override public boolean start(final Player player, final boolean login, Object... args) { - Quest quest = player.getQuestRepository().getQuest(GoblinDiplomacy.NAME); + Quest quest = player.getQuestRepository().getQuest(Quests.GOBLIN_DIPLOMACY); final NPC grubfoot = NPC.create(quest.getStage(player) == 10 ? 4495 : quest.getStage(player) == 20 ? 4497 : quest.getStage(player) == 30 ? 4498 : 4496, getBase().transform(10, 55, 0)); grubfoot.setWalks(false); npcs.add(grubfoot); @@ -182,8 +183,8 @@ public final class GDiplomacyCutscene extends CutscenePlugin { type = GrubFoot.forConfig(player); dialIndex = RandomFunction.random(DIALOGUES.length); other = Repository.findNPC(npc.getId() == 4494 ? 4493 : 4494); - quest = player.getQuestRepository().getQuest(GoblinDiplomacy.NAME); - if(player.getQuestRepository().getQuest("Lost Tribe").getStage(player) == 43){ + quest = player.getQuestRepository().getQuest(Quests.GOBLIN_DIPLOMACY); + if(player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 43){ player("Have you heard of the Dorgeshuun?"); stage = 5000; return true; @@ -367,8 +368,8 @@ public final class GDiplomacyCutscene extends CutscenePlugin { player.setAttribute("/save:tlt-goblin-emotes",true); player.getEmoteManager().unlock(Emotes.GOBLIN_BOW); player.getEmoteManager().unlock(Emotes.GOBLIN_SALUTE); - setVarbit(player, 532, 7, true); - player.getQuestRepository().getQuest("Lost Tribe").setStage(player,44); + setVarbit(player, 532, 7, true); + player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).setStage(player,44); stage++; break; case 5055: diff --git a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GoblinDiplomacy.java b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GoblinDiplomacy.java index a3e744b86..a85d815cb 100644 --- a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GoblinDiplomacy.java +++ b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GoblinDiplomacy.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the demon slayer quest. @@ -15,12 +16,6 @@ import core.plugin.ClassScanner; */ @Initializable public class GoblinDiplomacy extends Quest { - - /** - * The name of the quest. - */ - public static final String NAME = "Goblin Diplomacy"; - /** * Represents the orange goblin mail. */ @@ -45,7 +40,7 @@ public class GoblinDiplomacy extends Quest { * Constructs a new {@Code GoblinDiplomacy} {@Code Object} */ public GoblinDiplomacy() { - super("Goblin Diplomacy", 20, 19, 5); + super(Quests.GOBLIN_DIPLOMACY, 20, 19, 5); } @Override diff --git a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GrubfootDialogue.java b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GrubfootDialogue.java index 0eaed3038..ca562e9c6 100644 --- a/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GrubfootDialogue.java +++ b/Server/src/main/content/region/asgarnia/goblinvillage/quest/goblindiplomacy/GrubfootDialogue.java @@ -1,5 +1,6 @@ package content.region.asgarnia.goblinvillage.quest.goblindiplomacy; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -42,7 +43,7 @@ public final class GrubfootDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(GoblinDiplomacy.NAME); + quest = player.getQuestRepository().getQuest(Quests.GOBLIN_DIPLOMACY); switch (quest.getStage(player)) { case 100: npc("Me lonely."); diff --git a/Server/src/main/content/region/asgarnia/portsarim/dialogue/AhabDialogue.java b/Server/src/main/content/region/asgarnia/portsarim/dialogue/AhabDialogue.java index 493bc1973..5f5446083 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/dialogue/AhabDialogue.java +++ b/Server/src/main/content/region/asgarnia/portsarim/dialogue/AhabDialogue.java @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.plugin.Initializable; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the dialogue plugin used for the npc Ahav. @@ -117,7 +118,7 @@ public final class AhabDialogue extends DialoguePlugin { stage = 28; break; case 28: - if (player.getQuestRepository().isComplete("Dragon Slayer")) { + if (player.getQuestRepository().isComplete(Quests.DRAGON_SLAYER)) { player("Well, I do have a ship that I'm not using.", "It's the Lady Lumbridge."); stage = 29; } else { diff --git a/Server/src/main/content/region/asgarnia/portsarim/dialogue/KlarenseDialogue.java b/Server/src/main/content/region/asgarnia/portsarim/dialogue/KlarenseDialogue.java index e09ea0149..6c5e14b1e 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/dialogue/KlarenseDialogue.java +++ b/Server/src/main/content/region/asgarnia/portsarim/dialogue/KlarenseDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue used for the klarense npc. @@ -51,7 +52,7 @@ public final class KlarenseDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); if (args.length > 1) { interpreter.sendDialogues(npc, FacialExpression.ANGRY, "Hey, stay off my ship! That's private property!"); stage = 0; diff --git a/Server/src/main/content/region/asgarnia/portsarim/dialogue/RedbeardFrankDialogue.java b/Server/src/main/content/region/asgarnia/portsarim/dialogue/RedbeardFrankDialogue.java index 214b5f9f4..e3a46166c 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/dialogue/RedbeardFrankDialogue.java +++ b/Server/src/main/content/region/asgarnia/portsarim/dialogue/RedbeardFrankDialogue.java @@ -12,6 +12,7 @@ import core.plugin.Initializable; import core.game.node.item.Item; import static core.tools.DialogueConstKt.END_DIALOGUE; +import content.data.Quests; /** * Represents the dialogue to handle Rebeard Frank. @@ -59,7 +60,7 @@ public class RedbeardFrankDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Pirate's Treasure"); + quest = player.getQuestRepository().getQuest(Quests.PIRATES_TREASURE); npc("Arr, Matey!"); stage = 0; replacementReward = AchievementDiary.canReplaceReward(player, DiaryType.FALADOR, level); diff --git a/Server/src/main/content/region/asgarnia/portsarim/handlers/PortSarimPlugin.java b/Server/src/main/content/region/asgarnia/portsarim/handlers/PortSarimPlugin.java index 47df99e03..8746b7e93 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/handlers/PortSarimPlugin.java +++ b/Server/src/main/content/region/asgarnia/portsarim/handlers/PortSarimPlugin.java @@ -15,6 +15,7 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; import core.plugin.Initializable; import core.tools.RandomFunction; +import content.data.Quests; /** * Represents the port sarim plugin. @@ -72,7 +73,7 @@ public final class PortSarimPlugin extends OptionHandler { player.getDialogueInterpreter().open(238284); break; case "attack": - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 20) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 20) { player.getPacketDispatch().sendMessage("The goblin is already in prison. You have no reason to attack him."); } else { player.getProperties().getCombatPulse().attack(node); diff --git a/Server/src/main/content/region/asgarnia/portsarim/handlers/PortsObjectPlugin.java b/Server/src/main/content/region/asgarnia/portsarim/handlers/PortsObjectPlugin.java index 206b3860c..7f45a94f4 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/handlers/PortsObjectPlugin.java +++ b/Server/src/main/content/region/asgarnia/portsarim/handlers/PortsObjectPlugin.java @@ -11,6 +11,7 @@ import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the option handler for port sarim. @@ -206,7 +207,7 @@ public class PortsObjectPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("You disembark the ship."); break; case 2593: - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 100) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) == 100) { player.getDialogueInterpreter().open(744, Repository.findNPC(744), true);// lady // lumbridge. return true; diff --git a/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasure.java b/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasure.java index ae22be400..65ab84c0e 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasure.java +++ b/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasure.java @@ -7,6 +7,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the pirates treasure quest. @@ -50,7 +51,7 @@ public final class PiratesTreasure extends Quest { * Constructs a new {@Code PiratesTreasure} {@Code Object} */ public PiratesTreasure() { - super("Pirate's Treasure", 23, 22, 2, 71, 0, 1, 4); + super(Quests.PIRATES_TREASURE, 23, 22, 2, 71, 0, 1, 4); } @Override diff --git a/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasurePlugin.java b/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasurePlugin.java index a4f64a4dc..ce41de603 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasurePlugin.java +++ b/Server/src/main/content/region/asgarnia/portsarim/quest/piratestreasure/PiratesTreasurePlugin.java @@ -15,6 +15,7 @@ import core.game.node.item.Item; import core.game.node.scenery.Scenery; import core.game.world.map.Location; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the pirates treasure plugin. @@ -92,7 +93,7 @@ public final class PiratesTreasurePlugin extends OptionHandler { @Override public void run(Player player) { - final Quest quest = player.getQuestRepository().getQuest("Pirate's Treasure"); + final Quest quest = player.getQuestRepository().getQuest(Quests.PIRATES_TREASURE); player.lock(2); if (quest.getStage(player) == 20) { if (player.getSavedData().getQuestData().isGardenerAttack()) { diff --git a/Server/src/main/content/region/asgarnia/rimmington/dialogue/HettyDialogue.kt b/Server/src/main/content/region/asgarnia/rimmington/dialogue/HettyDialogue.kt index 5f9d41e3f..39a15588a 100644 --- a/Server/src/main/content/region/asgarnia/rimmington/dialogue/HettyDialogue.kt +++ b/Server/src/main/content/region/asgarnia/rimmington/dialogue/HettyDialogue.kt @@ -1,7 +1,7 @@ package content.region.asgarnia.rimmington.dialogue +import content.data.Quests import content.region.asgarnia.rimmington.quest.witchpotion.HettyWitchsPotionDialogue -import content.region.asgarnia.rimmington.quest.witchpotion.WitchsPotion import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -20,7 +20,7 @@ class HettyDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - val questStage = getQuestStage(player, WitchsPotion.QUEST_NAME) + val questStage = getQuestStage(player, Quests.WITCHS_POTION) when(questStage) { 0 -> npcl(FacialExpression.NEUTRAL, "What could you want with an old woman like me?").also { stage = 0 } diff --git a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/HettyWitchsPotionDialogue.kt b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/HettyWitchsPotionDialogue.kt index 2cc4ca2fd..50169689b 100644 --- a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/HettyWitchsPotionDialogue.kt +++ b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/HettyWitchsPotionDialogue.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.rimmington.quest.witchpotion +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -30,8 +31,8 @@ class HettyWitchsPotionDialogue(private val dStage: Int) : DialogueFile() { 3 -> npcl(FacialExpression.NEUTRAL, "You need an eye of newt, a rat's tail, an onion... Oh and a piece of burnt meat.").also { stage++ } 4 -> { playerl(FacialExpression.HAPPY, "Great, I'll go and get them.") - startQuest(player, WitchsPotion.QUEST_NAME) - setQuestStage(player, WitchsPotion.QUEST_NAME, 20) + startQuest(player, Quests.WITCHS_POTION) + setQuestStage(player, Quests.WITCHS_POTION, 20) stage = END_DIALOGUE } } @@ -67,7 +68,7 @@ class HettyWitchsPotionDialogue(private val dStage: Int) : DialogueFile() { removeItem(player, Item(Items.BURNT_MEAT_2146, 1)) && removeItem(player, Item(Items.EYE_OF_NEWT_221, 1))) { npcl(FacialExpression.HAPPY, "Ok, now drink from the cauldron.") - setQuestStage(player, WitchsPotion.QUEST_NAME, 40) + setQuestStage(player, Quests.WITCHS_POTION, 40) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotion.kt b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotion.kt index 3f002ff85..0ada42b79 100644 --- a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotion.kt +++ b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotion.kt @@ -7,15 +7,13 @@ import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Components import org.rs09.consts.Items +import content.data.Quests /** * Represents the Witch's Potion Quest */ @Initializable -class WitchsPotion : Quest(QUEST_NAME, 31, 30, 1, 67, 0, 1, 3) { - companion object { - const val QUEST_NAME = "Witch's Potion" - } +class WitchsPotion : Quest(Quests.WITCHS_POTION, 31, 30, 1, 67, 0, 1, 3) { override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) diff --git a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotionListeners.kt b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotionListeners.kt index 1c6ccc15a..0d00cee47 100644 --- a/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotionListeners.kt +++ b/Server/src/main/content/region/asgarnia/rimmington/quest/witchpotion/WitchsPotionListeners.kt @@ -1,5 +1,6 @@ package content.region.asgarnia.rimmington.quest.witchpotion +import content.data.Quests import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -13,9 +14,9 @@ class WitchsPotionListener : InteractionListener { override fun defineListeners() { on(Scenery.CAULDRON_2024, IntType.SCENERY, "drink from") { player, node -> - if (getQuestStage(player, WitchsPotion.QUEST_NAME) == 40) { + if (getQuestStage(player, Quests.WITCHS_POTION) == 40) { sendDialogue(player, "You drink from the cauldron, it tastes horrible! You feel yourself imbued with power.") - finishQuest(player, WitchsPotion.QUEST_NAME) + finishQuest(player, Quests.WITCHS_POTION) } else { sendDialogue(player, "As nice as that looks I think I'll give it a miss for now.") } diff --git a/Server/src/main/content/region/asgarnia/taverley/dialogue/KaqemeexDialogue.java b/Server/src/main/content/region/asgarnia/taverley/dialogue/KaqemeexDialogue.java index e5ab79fd7..487939a33 100644 --- a/Server/src/main/content/region/asgarnia/taverley/dialogue/KaqemeexDialogue.java +++ b/Server/src/main/content/region/asgarnia/taverley/dialogue/KaqemeexDialogue.java @@ -7,6 +7,7 @@ import core.plugin.Initializable; import core.game.node.entity.skill.Skills; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the kaqemeex dialogue plugin. @@ -55,17 +56,17 @@ public final class KaqemeexDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().isComplete("Druidic Ritual")) { + if (player.getQuestRepository().isComplete(Quests.DRUIDIC_RITUAL)) { interpreter.sendDialogues(npc, null, "Hello again. How is the Herblore going?"); stage = 600; break; } - if (player.getQuestRepository().getQuest("Druidic Ritual").getStage(player) == 10) { + if (player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).getStage(player) == 10) { interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "Hello again."); stage = 40; break; } - if (player.getQuestRepository().getQuest("Druidic Ritual").getStage(player) == 99) { + if (player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).getStage(player) == 99) { interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "I have word from Sanfew that you have been very", "helpful in assisting him with his preparations for the", "purification ritual. As promised I will now teach you the", "ancient arts of Herblore."); stage = 200; break; @@ -74,7 +75,7 @@ public final class KaqemeexDialogue extends DialoguePlugin { stage = 1; break; case 1: - if (player.getQuestRepository().getQuest("Druidic Ritual").isStarted(player)) { + if (player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).isStarted(player)) { if (Skillcape.isMaster(player, Skills.HERBLORE)) { interpreter.sendOptions("Select an Option", "Can I buy a Skillcape of Herblore?", "Who are you?", "Did you build this?"); stage = 800; @@ -164,7 +165,7 @@ public final class KaqemeexDialogue extends DialoguePlugin { stage = 13; break; case 26: - player.getQuestRepository().getQuest("Druidic Ritual").start(player); + player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).start(player); interpreter.sendDialogues(npc, FacialExpression.HAPPY, "Excellent. Go to the village south of this place and speak", "to my fellow Sanfew who is working on the purification", "ritual. He knows better than I what is required to", "complete it."); stage = 27; break; @@ -184,7 +185,7 @@ public final class KaqemeexDialogue extends DialoguePlugin { break; case 200: end(); - player.getQuestRepository().getQuest("Druidic Ritual").finish(player); + player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).finish(player); break; case 500: switch (buttonId) { diff --git a/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java b/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java index 3162dbdf1..f953d2783 100644 --- a/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java +++ b/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java @@ -11,6 +11,7 @@ import core.plugin.Initializable; import core.game.node.item.Item; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Handles the PikkupstixDialogue dialogue. @@ -85,7 +86,7 @@ public final class PikkupstixDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Wolf Whistle"); + quest = player.getQuestRepository().getQuest(Quests.WOLF_WHISTLE); switch (quest.getStage(player)) { case 0: npc("You there! What are you doing here, as if I didn't have", "enough troubles?"); diff --git a/Server/src/main/content/region/asgarnia/taverley/dialogue/SanfewDialogue.java b/Server/src/main/content/region/asgarnia/taverley/dialogue/SanfewDialogue.java index acf1f9f8b..0c5d09444 100644 --- a/Server/src/main/content/region/asgarnia/taverley/dialogue/SanfewDialogue.java +++ b/Server/src/main/content/region/asgarnia/taverley/dialogue/SanfewDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Handles the SanfewDialogue dialogue. @@ -40,12 +41,12 @@ public class SanfewDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().getQuest("Druidic Ritual").getStage(player) == 20) { + if (player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).getStage(player) == 20) { interpreter.sendDialogues(npc, FacialExpression.HALF_ASKING, "Did you bring me the required ingredients for the", "potion?"); stage = 100; break; } - if (player.getQuestRepository().getQuest("Druidic Ritual").getStage(player) == 10) { + if (player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).getStage(player) == 10) { interpreter.sendOptions("Select an Option", "I've been sent to help purify the Varrock stone circle.", "Actually, I don't need to speak to you."); stage = 2; break; @@ -89,7 +90,7 @@ public class SanfewDialogue extends DialoguePlugin { break; case 8: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "It is located somewhere in the mysterious underground", "halls which are located somewhere in the woods just", "South of here. They are too dangerous for me to go", "myself however."); - player.getQuestRepository().getQuest("Druidic Ritual").setStage(player, 20); + player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).setStage(player, 20); stage = 9; break; case 9: @@ -129,7 +130,7 @@ public class SanfewDialogue extends DialoguePlugin { break; case 202: player.getInventory().remove(new Item(522, 1), new Item(523, 1), new Item(524, 1), new Item(525, 1)); - player.getQuestRepository().getQuest("Druidic Ritual").setStage(player, 99); + player.getQuestRepository().getQuest(Quests.DRUIDIC_RITUAL).setStage(player, 99); player.getQuestRepository().syncronizeTab(player); interpreter.sendDialogues(npc, null, "Now go and talk to Kaqemeex and he will introduce", "you to the wonderful world of herblore and potion", "making!"); stage = 203; diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/DruidicRitual.kt b/Server/src/main/content/region/asgarnia/taverley/quest/DruidicRitual.kt index af35cb386..15440a4bd 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/DruidicRitual.kt +++ b/Server/src/main/content/region/asgarnia/taverley/quest/DruidicRitual.kt @@ -1,6 +1,5 @@ package content.region.asgarnia.taverley.quest -import content.region.asgarnia.taverley.dialogue.KaqemeexDialogue import core.api.* import core.game.component.Component import core.game.interaction.QueueStrength @@ -10,23 +9,20 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items -import org.rs09.consts.NPCs +import content.data.Quests /** * Druidic Ritual Quest */ @Initializable -class DruidicRitual : Quest("Druidic Ritual", 48, 47, 4, 80, 0, 3, 4) { +class DruidicRitual : Quest(Quests.DRUIDIC_RITUAL, 48, 47, 4, 80, 0, 3, 4) { - companion object { - const val questName = "Druidic Ritual" - } override fun drawJournal(player: Player, stage: Int) { super.drawJournal(player, stage) var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.DRUIDIC_RITUAL) > 0 if (!started) { line(player, "I can start this quest by speaking to !!Kaqemeex?? who is at", line++) diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java index cb1c137e2..ec4661ccf 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/WolfWhistle.java @@ -8,6 +8,7 @@ import core.game.node.item.Item; import org.rs09.consts.Items; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -26,7 +27,7 @@ public class WolfWhistle extends Quest { * Constructs a new {@code WolfWhistle} {@code Object}. */ public WolfWhistle() { - super("Wolf Whistle", 146, 145, 1); + super(Quests.WOLF_WHISTLE, 146, 145, 1); } @Override diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java index 3a92d309f..c4d254a64 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java @@ -6,6 +6,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import content.data.Quests; /** * Created for 2009Scape @@ -32,7 +33,7 @@ public class BoyDialoguePlugin extends DialoguePlugin { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest("Witch's House"); + final Quest quest = player.getQuestRepository().getQuest(Quests.WITCHS_HOUSE); player.debug(quest.isStarted(player) + " " + quest.getStage(player) ); if (!quest.isStarted(player) && quest.getStage(player) < 10) { player("Hello young man."); @@ -55,7 +56,7 @@ public class BoyDialoguePlugin extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Witch's House"); + final Quest quest = player.getQuestRepository().getQuest(Quests.WITCHS_HOUSE); switch(stage) { case -1: end(); diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java index cafc82acc..ab2b32e00 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHouse.java @@ -4,6 +4,7 @@ import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; +import content.data.Quests; /** * Created for 2009Scape @@ -19,7 +20,7 @@ public class WitchsHouse extends Quest { * Constructs a new {@code WitchsHouse} {@code Object}. */ public WitchsHouse() { - super("Witch's House", 124, 123, 4, 226, 0, 1, 7); + super(Quests.WITCHS_HOUSE, 124, 123, 4, 226, 0, 1, 7); } @Override diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHousePlugin.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHousePlugin.java index 3600be5c6..5e8ccb1d9 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHousePlugin.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsHousePlugin.java @@ -18,6 +18,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import core.plugin.ClassScanner; import core.tools.RandomFunction; +import content.data.Quests; /** * Created for 2009Scape @@ -39,7 +40,7 @@ public class WitchsHousePlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Witch's House"); + final Quest quest = player.getQuestRepository().getQuest(Quests.WITCHS_HOUSE); final int id = node instanceof Item ? ((Item) node).getId() : node instanceof Scenery ? ((Scenery) node).getId() : node instanceof NPC ? ((NPC) node).getId() : node.getId(); // boolean killedExperiment = player.getAttribute("witchs_house:experiment_killed",false); // boolean experimentAlive = !player.getAttribute("witchs_house:experiment_killed", false); diff --git a/Server/src/main/content/region/asgarnia/trollheim/dialogue/SabaDialogue.kt b/Server/src/main/content/region/asgarnia/trollheim/dialogue/SabaDialogue.kt index f904fe12e..9eb7daf39 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/dialogue/SabaDialogue.kt +++ b/Server/src/main/content/region/asgarnia/trollheim/dialogue/SabaDialogue.kt @@ -1,6 +1,6 @@ package content.region.asgarnia.trollheim.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import content.region.asgarnia.burthorpe.quest.deathplateau.SabaDialogueFile import core.api.getQuestStage import core.api.openDialogue @@ -20,7 +20,7 @@ import org.rs09.consts.NPCs @Initializable class SabaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if (getQuestStage(player!!, DeathPlateau.questName) >= 19) { + if (getQuestStage(player!!, Quests.DEATH_PLATEAU) >= 19) { openDialogue(player!!, SabaDialogueFile(), npc) return true } diff --git a/Server/src/main/content/region/asgarnia/trollheim/dialogue/TenzingDialogue.kt b/Server/src/main/content/region/asgarnia/trollheim/dialogue/TenzingDialogue.kt index a657189c2..2101a9b77 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/dialogue/TenzingDialogue.kt +++ b/Server/src/main/content/region/asgarnia/trollheim/dialogue/TenzingDialogue.kt @@ -1,6 +1,6 @@ package content.region.asgarnia.trollheim.dialogue -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import content.region.asgarnia.burthorpe.quest.deathplateau.TenzingDialogueFile import core.api.* import core.game.dialogue.DialoguePlugin @@ -21,7 +21,7 @@ import org.rs09.consts.NPCs @Initializable class TenzingDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if (isQuestInProgress(player!!, DeathPlateau.questName, 20, 29)) { + if (isQuestInProgress(player!!, Quests.DEATH_PLATEAU, 20, 29)) { openDialogue(player!!, TenzingDialogueFile(), npc) return true } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java index c1be4295f..8803d9d88 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java @@ -18,6 +18,7 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Handles the entrance hole to the godwars dungeon. @@ -67,7 +68,7 @@ public final class GodwarsEntranceHandler extends OptionHandler { }); return true; case 26338: - if (!hasRequirement(player, "Troll Stronghold")) + if (!hasRequirement(player, Quests.TROLL_STRONGHOLD)) return true; if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 60) { player.getPacketDispatch().sendMessage("You need a Strength level of 60 to move this boulder."); diff --git a/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt b/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt index 50f351f37..a0bc89b30 100644 --- a/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt +++ b/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt @@ -8,6 +8,7 @@ import core.plugin.Initializable import org.rs09.consts.NPCs import core.api.* +import content.data.Quests /** * Represents the ali morrisane dialogue. @@ -36,7 +37,7 @@ class AliMorrisaneDialogue(player: Player? = null) : DialoguePlugin(player) { 1 -> playerl(FacialExpression.ASKING, "If you are, then why are you still selling goods from a stall?").also { stage = 10 } 2 -> { end() - if (!hasRequirement(player, "The Feud")) + if (!hasRequirement(player, Quests.THE_FEUD)) return true npc.openShop(player) } @@ -59,7 +60,7 @@ class AliMorrisaneDialogue(player: Player? = null) : DialoguePlugin(player) { } 2 -> { end() - if (!hasRequirement(player, "The Feud")) + if (!hasRequirement(player, Quests.THE_FEUD)) return true npc.openShop(player) } diff --git a/Server/src/main/content/region/desert/alkharid/dialogue/BorderGuardDialogue.java b/Server/src/main/content/region/desert/alkharid/dialogue/BorderGuardDialogue.java index c31f6d468..4331b9370 100644 --- a/Server/src/main/content/region/desert/alkharid/dialogue/BorderGuardDialogue.java +++ b/Server/src/main/content/region/desert/alkharid/dialogue/BorderGuardDialogue.java @@ -9,6 +9,7 @@ import core.game.node.scenery.Scenery; import core.game.world.map.Location; import core.plugin.Initializable; import core.game.world.map.RegionManager; +import content.data.Quests; /** * Represents the border guard dialogue plugin. @@ -80,7 +81,7 @@ public final class BorderGuardDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().getQuest("Prince Ali Rescue").getStage(player) > 50) { + if (player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE).getStage(player) > 50) { npc("You may pass for free, you are a friend of Al-Kharid."); stage = 100; } else { diff --git a/Server/src/main/content/region/desert/alkharid/dialogue/GemTraderDialogue.kt b/Server/src/main/content/region/desert/alkharid/dialogue/GemTraderDialogue.kt index 65e45420c..cd6bd5d5e 100644 --- a/Server/src/main/content/region/desert/alkharid/dialogue/GemTraderDialogue.kt +++ b/Server/src/main/content/region/desert/alkharid/dialogue/GemTraderDialogue.kt @@ -1,11 +1,13 @@ package content.region.desert.alkharid.dialogue import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests +import core.api.getQuestStage +import core.api.setQuestStage /** * Represents the gem trader Dialogue plugin @@ -21,17 +23,8 @@ class GemTraderDialogue (player: Player? = null): DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("Family Crest") ?: -1 - if(qstage == 12){ - npc("Good day to you, traveller. ", - "Would you be interested in buying some gems?") - stage = 1 - } - else{ - npc("Good day to you, traveller. ", - "Would you be interested in buying some gems?") - stage = 2 - } + npc("Good day to you, traveller.", "Would you be interested in buying some gems?") + stage = if (getQuestStage(player, Quests.FAMILY_CREST) == 12) 1 else 2 return true } @@ -74,7 +67,7 @@ class GemTraderDialogue (player: Player? = null): DialoguePlugin(player){ 103 -> npc("Well, maybe we'll all get lucky ", "and the scorpions will deal with him.").also{ stage = 1000 - player.questRepository.getQuest("Family Crest").setStage(player, 13) + setQuestStage(player, Quests.FAMILY_CREST, 13) } 1000 -> end() diff --git a/Server/src/main/content/region/desert/alkharid/dialogue/HassanDialogue.java b/Server/src/main/content/region/desert/alkharid/dialogue/HassanDialogue.java index ce0192046..7c711edab 100644 --- a/Server/src/main/content/region/desert/alkharid/dialogue/HassanDialogue.java +++ b/Server/src/main/content/region/desert/alkharid/dialogue/HassanDialogue.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue used to handle the Hassan npc. @@ -52,7 +53,7 @@ public final class HassanDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); switch (quest.getStage(player)) { case 100: interpreter.sendDialogues(npc, null, "You are a friend of the town of Al-Kharid. If we have", "more tasks to complete, we will ask you. Please, keep in", "contact. Good employees are not easy to find."); diff --git a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java index 5cc974b9b..038567099 100644 --- a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java +++ b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java @@ -10,6 +10,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.game.world.GameWorld; import core.game.world.map.RegionManager; +import content.data.Quests; /** * Represents the dialogue which handles the lady keli transcript. @@ -58,7 +59,7 @@ public final class LadyKeliDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); switch (quest.getStage(player)) { case 60: case 100: diff --git a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescue.java b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescue.java index 4cd5acffa..3df88587a 100644 --- a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescue.java +++ b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescue.java @@ -6,6 +6,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the prince ali rescue quest. @@ -44,7 +45,7 @@ public class PrinceAliRescue extends Quest { * Constructs a new {@Code PrinceAliRescue} {@Code Object} */ public PrinceAliRescue() { - super("Prince Ali Rescue", 24, 23, 3, 273, 0, 1, 110); + super(Quests.PRINCE_ALI_RESCUE, 24, 23, 3, 273, 0, 1, 110); } @Override diff --git a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescuePlugin.java b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescuePlugin.java index 7327333fb..3f38c3489 100644 --- a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescuePlugin.java +++ b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/PrinceAliRescuePlugin.java @@ -13,6 +13,7 @@ import core.game.world.GameWorld; import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the plugin used to handle prince ali rescue quest interaction nodes. @@ -35,7 +36,7 @@ public class PrinceAliRescuePlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + final Quest quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); final int id = node instanceof Scenery ? ((Scenery) node).getId() : node instanceof NPC ? ((NPC) node).getId() : 0; switch (id) { case 925: diff --git a/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java b/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java index 577cb1151..a4a3c626a 100644 --- a/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java +++ b/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java @@ -23,6 +23,7 @@ import core.plugin.Plugin; import core.plugin.ClassScanner; import org.rs09.consts.Items; import org.rs09.consts.Sounds; +import content.data.Quests; /** @@ -158,11 +159,11 @@ public final class RugMerchantDialogue extends DialoguePlugin { } end(); destination = options.length == 1 ? options[0] : options[buttonId - 1]; - if (destination == RugDestination.UZER && !hasRequirement(player, "The Golem")) + if (destination == RugDestination.UZER && !hasRequirement(player, Quests.THE_GOLEM)) break; - else if (destination == RugDestination.BEDABIN_CAMP && !hasRequirement(player, "The Tourist Trap")) + else if (destination == RugDestination.BEDABIN_CAMP && !hasRequirement(player, Quests.THE_TOURIST_TRAP)) break; - else if (destination == RugDestination.SOPHANEM && !hasRequirement(player, "Icthlarin's Little Helper")) + else if (destination == RugDestination.SOPHANEM && !hasRequirement(player, Quests.ICTHLARINS_LITTLE_HELPER)) break; if(player.getEquipment().get(EquipmentContainer.SLOT_WEAPON) != null){ player.sendMessage(colorize("%RYou must unequip all your weapons before you can fly on a carpet.")); diff --git a/Server/src/main/content/region/desert/handlers/TollGateOptionPlugin.java b/Server/src/main/content/region/desert/handlers/TollGateOptionPlugin.java index a07dcbed6..2c9f338a9 100644 --- a/Server/src/main/content/region/desert/handlers/TollGateOptionPlugin.java +++ b/Server/src/main/content/region/desert/handlers/TollGateOptionPlugin.java @@ -13,6 +13,7 @@ import core.plugin.Plugin; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_ALKHARID_GATE; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE; +import content.data.Quests; @Initializable public class TollGateOptionPlugin extends OptionHandler { @@ -20,7 +21,7 @@ public class TollGateOptionPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { if (option.equals("pay-toll(10gp)")) { - if (player.getQuestRepository().getQuest("Prince Ali Rescue").getStage(player) > 50) { + if (player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE).getStage(player) > 50) { player.getPacketDispatch().sendMessage("The guards let you through for free."); DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); } else { diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt index 79a033158..0ec1e3d33 100644 --- a/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt +++ b/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests /** * @author qmqz @@ -18,13 +19,13 @@ class ArchaeologistDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!player.questRepository.hasStarted("Desert Treasure")) { - if (player.questRepository.isComplete("The Digsite Quest") && - player.questRepository.isComplete("The Tourist Trap") && - player.questRepository.isComplete("The Temple of Ikov") && - player.questRepository.isComplete("Priest In Peril") && - player.questRepository.isComplete("Waterfall Quest") && - player.questRepository.isComplete("Troll Stronghold") && + if (!player.questRepository.hasStarted(Quests.DESERT_TREASURE)) { + if (player.questRepository.isComplete(Quests.THE_DIG_SITE) && + player.questRepository.isComplete(Quests.THE_TOURIST_TRAP) && + player.questRepository.isComplete(Quests.TEMPLE_OF_IKOV) && + player.questRepository.isComplete(Quests.PRIEST_IN_PERIL) && + player.questRepository.isComplete(Quests.WATERFALL_QUEST) && + player.questRepository.isComplete(Quests.TROLL_STRONGHOLD) && player.skills.getStaticLevel(Skills.SLAYER) >= 10 && player.skills.getStaticLevel(Skills.FIREMAKING) >= 50 && player.skills.getStaticLevel(Skills.MAGIC) >= 50 && @@ -79,8 +80,8 @@ class ArchaeologistDialogue(player: Player? = null) : DialoguePlugin(player){ "Come back and let me know what he says, I would hate", "to waste my time excavating anything that isn't worth", "my time as a world famous archaeologist!").also { - player.questRepository.getQuest("Desert Treasure").start(player) - setQuestStage(player, "Desert Treasure", 1) + player.questRepository.getQuest(Quests.DESERT_TREASURE).start(player) + setQuestStage(player, Quests.DESERT_TREASURE, 1) stage = 99 } diff --git a/Server/src/main/content/region/desert/quest/shadowofthestorm/DarklightListener.kt b/Server/src/main/content/region/desert/quest/shadowofthestorm/DarklightListener.kt index 26e72c57f..1daba317d 100644 --- a/Server/src/main/content/region/desert/quest/shadowofthestorm/DarklightListener.kt +++ b/Server/src/main/content/region/desert/quest/shadowofthestorm/DarklightListener.kt @@ -6,11 +6,12 @@ import core.api.removeItem import core.game.interaction.IntType import core.game.interaction.InteractionListener import org.rs09.consts.Items +import content.data.Quests class DarklightListener : InteractionListener { override fun defineListeners() { onUseWith(IntType.ITEM, Items.BLACK_MUSHROOM_INK_4622, Items.SILVERLIGHT_2402) { player, used, with -> - if (!hasRequirement(player, "Shadow of the Storm") || (!player.inventory.contains(Items.BLACK_MUSHROOM_INK_4622, 1) && (!player.inventory.contains(Items.SILVERLIGHT_2402, 1)))) + if (!hasRequirement(player, Quests.SHADOW_OF_THE_STORM) || (!player.inventory.contains(Items.BLACK_MUSHROOM_INK_4622, 1) && (!player.inventory.contains(Items.SILVERLIGHT_2402, 1)))) return@onUseWith false if (removeItem(player, used.id) && removeItem(player, with.id)) addItem(player, Items.DARKLIGHT_6746) diff --git a/Server/src/main/content/region/desert/quest/thegolem/TheGolemDialogue.kt b/Server/src/main/content/region/desert/quest/thegolem/TheGolemDialogue.kt index b045a1cf1..c1331e614 100644 --- a/Server/src/main/content/region/desert/quest/thegolem/TheGolemDialogue.kt +++ b/Server/src/main/content/region/desert/quest/thegolem/TheGolemDialogue.kt @@ -8,6 +8,7 @@ import core.plugin.Initializable import org.rs09.consts.NPCs import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile +import content.data.Quests @Initializable public final class ClayGolemDialoguePlugin(player: Player? = null) : DialoguePlugin(player) { @@ -29,22 +30,22 @@ public final class ClayGolemDialoguePlugin(player: Player? = null) : DialoguePlu class ClayGolemDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - val opt1 = b.onQuestStages("The Golem", 0) + val opt1 = b.onQuestStages(Quests.THE_GOLEM, 0) .npc("Damage... severe...", "task... incomplete...") .options() opt1 - .optionIf("Shall I try to repair you?") { player -> return@optionIf player.questRepository.getQuest("The Golem").hasRequirements(player) } + .optionIf("Shall I try to repair you?") { player -> return@optionIf player.questRepository.getQuest(Quests.THE_GOLEM).hasRequirements(player) } .playerl("Shall I try to repair you?") .npcl("Repairs... needed...") - .endWith(){ _, player -> if (player.questRepository.getStage("The Golem") < 1 ) { setQuestStage(player, "The Golem", 1) } } + .endWith(){ _, player -> if (player.questRepository.getStage(Quests.THE_GOLEM) < 1 ) { setQuestStage(player, Quests.THE_GOLEM, 1) } } opt1 .option("I'm not going to find a conversation here!") .playerl("I'm not going to find a conversation here!") .end() - b.onQuestStages("The Golem", 1) + b.onQuestStages(Quests.THE_GOLEM, 1) .npcl("Repairs... needed...") .end() - b.onQuestStages("The Golem", 2) + b.onQuestStages(Quests.THE_GOLEM, 2) .npcl("Damage repaired...") .npcl("Thank you. My body and mind are fully healed.") .npcl("Now I must complete my task by defeating the great enemy.") @@ -52,43 +53,43 @@ class ClayGolemDialogueFile : DialogueBuilderFile() { .npcl("A great demon. It broke through from its dimension to attack the city.") .npcl("The golem army was created to fight it. Many were destroyed, but we drove the demon back!") .npcl("The demon is still wounded. You must open the portal so that I can strike the final blow and complete my task.") - .endWith() { _, player -> setQuestStage(player, "The Golem", 3) } - b.onQuestStages("The Golem", 3) + .endWith() { _, player -> setQuestStage(player, Quests.THE_GOLEM, 3) } + b.onQuestStages(Quests.THE_GOLEM, 3) .npcl("The demon is still wounded. You must open the portal so that I can strike the final blow and complete my task.") .end() - b.onQuestStages("The Golem", 4) + b.onQuestStages(Quests.THE_GOLEM, 4) .npcl("My task is incomplete. You must open the portal so I can defeat the great demon.") .playerl("It's ok, the demon is dead!") .npcl("The demon must be defeated...") .playerl("No, you don't understand. I saw the demon's skeleton. It must have died of its wounds.") .npcl("Demon must be defeated! Task incomplete.") - .endWith() { _, player -> setQuestStage(player, "The Golem", 5) } - b.onQuestStages("The Golem", 5) + .endWith() { _, player -> setQuestStage(player, Quests.THE_GOLEM, 5) } + b.onQuestStages(Quests.THE_GOLEM, 5) .npcl("Task incomplete.") .playerl("Oh, how am I going to convince you?") - .endWith() { _, player -> setQuestStage(player, "The Golem", 6) } - b.onQuestStages("The Golem", 6, 7) + .endWith() { _, player -> setQuestStage(player, Quests.THE_GOLEM, 6) } + b.onQuestStages(Quests.THE_GOLEM, 6, 7) .npcl("My task is incomplete. You must open the portal so I can defeat the great demon.") .playerl("I already told you, he's dead!") .npcl("Task incomplete.") .playerl("Oh, how am I going to convince you?") - .endWith() { df, player -> if(player.questRepository.getStage("The Golem") < 7) { setQuestStage(player, "The Golem", 7) } } + .endWith() { df, player -> if(player.questRepository.getStage(Quests.THE_GOLEM) < 7) { setQuestStage(player, Quests.THE_GOLEM, 7) } } } } class ClayGolemProgramDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages("The Golem", 8) + b.onQuestStages(Quests.THE_GOLEM, 8) .npc("New instructions...", "Updating program...") .npcl("Task complete!") .npcl("Thank you. Now my mind is at rest.") - .endWith() { _, player -> finishQuest(player, "The Golem") } + .endWith() { _, player -> finishQuest(player, Quests.THE_GOLEM) } } } class CuratorHaigHalenGolemDialogue : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - val opt1 = b.onQuestStages("The Golem", 3) + val opt1 = b.onQuestStages(Quests.THE_GOLEM, 3) .npcl("Ah yes, a very impressive artefact. The people of that city were excellent sculptors.") .npcl("It's in the display case upstairs.") .playerl("No, I need to take it away with me.") diff --git a/Server/src/main/content/region/desert/quest/thegolem/TheGolemQuest.kt b/Server/src/main/content/region/desert/quest/thegolem/TheGolemQuest.kt index 8ae98312a..89d485f91 100644 --- a/Server/src/main/content/region/desert/quest/thegolem/TheGolemQuest.kt +++ b/Server/src/main/content/region/desert/quest/thegolem/TheGolemQuest.kt @@ -19,9 +19,10 @@ import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.interaction.InterfaceListener import core.game.world.GameWorld +import content.data.Quests @Initializable -class TheGolemQuest : Quest("The Golem", 70, 69, 1, 437, 0, 1, 10) { +class TheGolemQuest : Quest(Quests.THE_GOLEM, 70, 69, 1, 437, 0, 1, 10) { override fun newInstance(`object`: Any?): Quest { return this } @@ -140,7 +141,7 @@ class DisplayCaseListener : InterfaceListener { class TheGolemListeners : InteractionListener { fun repairGolem(player: Player): Boolean { - if(player.questRepository.getStage("The Golem") == 1) { + if(player.questRepository.getStage(Quests.THE_GOLEM) == 1) { var clayUsed = player.getAttribute("the-golem:clay-used", 0) val msg = when(clayUsed) { 0 -> "You apply some clay to the golem's wounds. The clay begins to harden in the hot sun." @@ -157,7 +158,7 @@ class TheGolemListeners : InteractionListener { player.setAttribute("/save:the-golem:clay-used", clayUsed) updateVarps(player) if(clayUsed == 4) { - setQuestStage(player, "The Golem", 2) + setQuestStage(player, Quests.THE_GOLEM, 2) } } } @@ -213,13 +214,13 @@ class TheGolemListeners : InteractionListener { val rotation3 = player.getAttribute("the-golem:statuette-rotation:3", 0) val doorOpen = player.getAttribute("the-golem:door-open", false) var clientStage = 0 - if(player.questRepository.getStage("The Golem") > 0) { + if(player.questRepository.getStage(Quests.THE_GOLEM) > 0) { clientStage = Math.max(clientStage, 1) } if(doorOpen) { clientStage = Math.max(clientStage, 5) } - if(player.questRepository.getStage("The Golem") >= 100) { + if(player.questRepository.getStage(Quests.THE_GOLEM) >= 100) { clientStage = Math.max(clientStage, 10) } setVarbit(player, 346, clientStage) @@ -346,9 +347,9 @@ class TheGolemListeners : InteractionListener { player.sendMessage("You don't know what that would do.") return true } - if(player.questRepository.getStage("The Golem") == 7) { + if(player.questRepository.getStage(Quests.THE_GOLEM) == 7) { player.sendMessage("You insert the key and the golem's skull hinges open.") - setQuestStage(player, "The Golem", 8) + setQuestStage(player, Quests.THE_GOLEM, 8) } return true } @@ -393,7 +394,7 @@ class TheGolemListeners : InteractionListener { if(!player.getAttribute("the-golem:seen-demon", false)) { player.sendMessage("The room is dominated by a colossal horned skeleton!") player.setAttribute("/save:the-golem:seen-demon", true) - setQuestStage(player, "The Golem", 4) + setQuestStage(player, Quests.THE_GOLEM, 4) } teleport(player, Location.create(3552, 4948, 0)) return@on true diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/AlShabimDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/AlShabimDialogue.java index 93e263e25..4afd56007 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/AlShabimDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/AlShabimDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -48,7 +49,7 @@ public final class AlShabimDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { default: npc("Hello Effendi!"); diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java index 6f5d0444a..efb949796 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.interaction.NodeUsageEvent; import core.game.interaction.UseWithHandler; @@ -57,7 +58,7 @@ public final class AnaDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if ((quest.getStage(player) == 71 || quest.getStage(player) == 72) && args.length > 1) { player.getDialogueInterpreter().sendDialogue("You see a barrel coming to the surface. Before too long you haul it", "onto the side. The barrel seems quite heavy and you hear a muffled", "sound coming from inside."); stage = 400; @@ -277,7 +278,7 @@ public final class AnaDialogue extends DialoguePlugin { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { case 61: player.getDialogueInterpreter().open(822, event.getUsedWith(), true); @@ -320,7 +321,7 @@ public final class AnaDialogue extends DialoguePlugin { @Override public boolean isHidden(final Player player) { - Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (quest.getStage(player) > 61) { return true; } diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/BedabinNomadDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/BedabinNomadDialogue.java index 8cdabc88d..420714f24 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/BedabinNomadDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/BedabinNomadDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -46,7 +47,7 @@ public final class BedabinNomadDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (npc.getId()) { case 834:// guard switch (quest.getStage(player)) { diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/CaptainSiadDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/CaptainSiadDialogue.java index 447929a6c..9de225a64 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/CaptainSiadDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/CaptainSiadDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -42,7 +43,7 @@ public final class CaptainSiadDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { default: player.getPacketDispatch().sendMessage("The captain looks up from his work as you address him."); diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java index e979daefd..9c9a08367 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java @@ -2,6 +2,7 @@ package content.region.desert.quest.thetouristrap; import java.util.List; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.npc.NPC; @@ -57,7 +58,7 @@ public final class DesertGuardDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (npc.getId()) { case 5001: switch (quest.getStage(player)) { diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/IrenaDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/IrenaDialogue.java index 19b3b768f..8788371b8 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/IrenaDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/IrenaDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.skill.Skills; import core.game.node.entity.npc.NPC; @@ -48,7 +49,7 @@ public final class IrenaDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (quest.getStage(player) == 95 && player.getInventory().containsItem(TouristTrap.ANNA_BARREL)) { npc("Hey, great you've found Ana!"); stage = 900; diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/MaleSlaveDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/MaleSlaveDialogue.java index 2ee5e3456..269f4185a 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/MaleSlaveDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/MaleSlaveDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -47,7 +48,7 @@ public final class MaleSlaveDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (npc.getShownNPC(player).getId()) { case 4985: case 825: diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryCaptainDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryCaptainDialogue.java index f959a1fbe..e020f6793 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryCaptainDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryCaptainDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.Entity; import core.game.node.entity.npc.AbstractNPC; @@ -52,7 +53,7 @@ public final class MercenaryCaptainDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { case 11: interpreter.sendDialogue("You approach the Mercenary Captain."); @@ -183,7 +184,7 @@ public final class MercenaryCaptainDialogue extends DialoguePlugin { super.finalizeDeath(killer); if (killer instanceof Player) { final Player player = (Player) killer; - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { case 0: case 10: diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryDialogue.java index c9fd6d862..4f063203c 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/MercenaryDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -46,7 +47,7 @@ public final class MercenaryDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { default: npc("What are you doing here?"); diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/MinecartDriverDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/MinecartDriverDialogue.java index e9ef2dbb6..a748227fd 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/MinecartDriverDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/MinecartDriverDialogue.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -46,7 +47,7 @@ public final class MinecartDriverDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); switch (quest.getStage(player)) { case 90: npc("Quickly, get in the back of the cart."); diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/MiningCampZone.java b/Server/src/main/content/region/desert/quest/thetouristrap/MiningCampZone.java index 75aa27944..ae06c8e0a 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/MiningCampZone.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/MiningCampZone.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.game.interaction.Option; import core.game.node.Node; import core.game.node.entity.Entity; @@ -83,7 +84,7 @@ public final class MiningCampZone extends MapZone implements Plugin { * @return {@code True} if removed. */ public boolean checkAnna(final Player p) { - final Quest quest = p.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = p.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (p.getAttribute("ana-delay", 0) > GameWorld.getTicks()) { return false; } diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrap.java b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrap.java index e81eb6764..75f4d6134 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrap.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrap.java @@ -14,6 +14,7 @@ import core.plugin.Initializable; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * The main type for the tourist trap quest. @@ -23,12 +24,6 @@ import static core.api.ContentAPIKt.*; */ @Initializable public final class TouristTrap extends Quest { - - /** - * The name of the quest. - */ - public static final String NAME = "The Tourist Trap"; - /** * The metal key item. */ @@ -113,7 +108,7 @@ public final class TouristTrap extends Quest { * Constructs a new {@code TouristTrap} {@code Object}. */ public TouristTrap() { - super(NAME, 123, 122, 2, 197, 0, 1, 30); + super(Quests.THE_TOURIST_TRAP, 123, 122, 2, 197, 0, 1, 30); } @Override diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java index e8a9750dd..463d61272 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java @@ -1,5 +1,6 @@ package content.region.desert.quest.thetouristrap; +import content.data.Quests; import core.cache.def.impl.AnimationDefinition; import core.cache.def.impl.NPCDefinition; import core.cache.def.impl.SceneryDefinition; @@ -135,7 +136,7 @@ public final class TouristTrapPlugin extends OptionHandler { @Override public boolean handle(final Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); final int id = node.getId(); switch (option) { case "read": @@ -356,7 +357,7 @@ public final class TouristTrapPlugin extends OptionHandler { player.getInventory().add(TouristTrap.CELL_DOOR_KEY, player); player.getDialogueInterpreter().sendItemMessage(TouristTrap.CELL_DOOR_KEY, "You find a cell door key."); break; - } else if (hasItem(player, TouristTrap.WROUGHT_IRON_KEY) && player.getQuestRepository().isComplete(TouristTrap.NAME)) { + } else if (hasItem(player, TouristTrap.WROUGHT_IRON_KEY) && player.getQuestRepository().isComplete(Quests.THE_TOURIST_TRAP)) { player.getInventory().add(TouristTrap.WROUGHT_IRON_KEY, player); player.getDialogueInterpreter().sendItemMessage(TouristTrap.WROUGHT_IRON_KEY, "You find the key to the main gate."); break; @@ -633,7 +634,7 @@ public final class TouristTrapPlugin extends OptionHandler { case 516: player.getInventory().remove(TouristTrap.ANNA_BARREL); player.getBank().remove(TouristTrap.ANNA_BARREL); - player.getQuestRepository().getQuest(TouristTrap.NAME).setStage(player, 71); + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 71); end(); break; case 0: @@ -700,7 +701,7 @@ public final class TouristTrapPlugin extends OptionHandler { @Override public boolean handle(final NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (event.getUsedWith().getId() == 18958) {// cart if (quest.getStage(player) == 72) { player.lock(4); @@ -800,7 +801,7 @@ public final class TouristTrapPlugin extends OptionHandler { } break; case 33: - player.getQuestRepository().getQuest(TouristTrap.NAME).setStage(player, 70); + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 70); player.getInventory().remove(TouristTrap.ANNA_BARREL); player.removeAttribute("ana-delay"); AnnaCartCutscene.this.stop(true); @@ -905,7 +906,7 @@ public final class TouristTrapPlugin extends OptionHandler { case 6: player.unlock(); player.getInterfaceManager().closeOverlay(); - player.getQuestRepository().getQuest(TouristTrap.NAME).setStage(player, 95); + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 95); player.getInterfaceManager().close(); player.getProperties().setTeleportLocation(Location.create(3258, 3029, 0)); player.getInventory().add(TouristTrap.ANNA_BARREL); @@ -1303,7 +1304,7 @@ public final class TouristTrapPlugin extends OptionHandler { @Override public boolean open(Object... args) { barrel = (Scenery) args[0]; - quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if ((quest.getStage(player) == 70 || quest.getStage(player) == 72) && !player.hasItem(TouristTrap.ANNA_BARREL)) { interpreter.sendDialogue("You search the barrels and find Ana."); stage = 400; @@ -1402,7 +1403,7 @@ public final class TouristTrapPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (quest.getStage(player) == 54 && player.getInventory().containsItem(TouristTrap.TECHNICAL_PLANS)) { player.getDialogueInterpreter().open("bedabin-anvil"); return true; @@ -1436,7 +1437,7 @@ public final class TouristTrapPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(TouristTrap.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); if (!event.getUsedWith().getLocation().equals(Location.create(3292, 9423, 0))) { return false; } diff --git a/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java b/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java index 776b39973..219c1caa9 100644 --- a/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java +++ b/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java @@ -2,6 +2,7 @@ package content.region.desert.sophanem.handlers; import core.cache.def.impl.SceneryDefinition; import core.game.global.action.ClimbActionHandler; +import core.game.global.action.DoorActionHandler; import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.player.Player; @@ -13,10 +14,11 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * The plugin for handling stuff in Sophanem. - * @author jamix77 + * @author jamix77, Player Name * */ @Initializable @@ -26,6 +28,8 @@ public class SophanemPlugin extends OptionHandler { public Plugin newInstance(Object arg) throws Throwable { SceneryDefinition.forId(20277).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(20275).getHandlers().put("option:climb-down", this); + SceneryDefinition.forId(20391).getHandlers().put("option:open", this); + SceneryDefinition.forId(28514).getHandlers().put("option:open", this); return this; } @@ -34,15 +38,22 @@ public class SophanemPlugin extends OptionHandler { final int id = node instanceof Scenery ? ((Scenery) node).getId() : ((Item) node).getId(); switch (id) { case 20275: - if (!hasRequirement(player, "Contact!")) - break; + if (!hasRequirement(player, Quests.CONTACT)) { + break; + } ClimbActionHandler.climb(player, new Animation(827), Location.create(2799, 5160, 0)); break; case 20277: ClimbActionHandler.climb(player, new Animation(828), Location.create(3315,2796,0)); break; + case 20391: + case 28514: + if (!hasRequirement(player, Quests.ICTHLARINS_LITTLE_HELPER)) { + break; + } + DoorActionHandler.handleDoor(player, (Scenery) node); + break; } return true; } - } diff --git a/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java b/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java index 1b2af20f7..19e639678 100644 --- a/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java +++ b/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java @@ -12,6 +12,7 @@ import core.net.packet.context.MinimapStateContext; import core.plugin.Initializable; import core.net.packet.out.MinimapState; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the lokar searunner dialogue. @@ -110,7 +111,7 @@ public class LokarSearunnerDialogue extends DialoguePlugin { * @param location the location. */ private void travel(final Player player, final Location location) { - if (!hasRequirement(player, "Lunar Diplomacy")) + if (!hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return; player.lock(); GameWorld.getPulser().submit(new Pulse(1, player) { diff --git a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt index e6367c387..51d160974 100644 --- a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt +++ b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt @@ -17,6 +17,7 @@ import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills import core.game.world.map.zone.ZoneBorders import org.rs09.consts.* +import content.data.Quests class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { companion object { @@ -322,7 +323,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } // You can alternatively browse her regular clothing store to complete the task, no purchase necessary. - if (event.target.id == NPCs.YRSA_1301 && event.option == "trade" && player.questRepository.isComplete("Fremennik Trials") && inBorders(player, YRSA_SHOP_BORDERS)) { + if (event.target.id == NPCs.YRSA_1301 && event.option == "trade" && player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS) && inBorders(player, YRSA_SHOP_BORDERS)) { finishTask( player, DiaryLevel.MEDIUM, diff --git a/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt b/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt index b4e2b45bf..e4ed6b691 100644 --- a/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt +++ b/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt @@ -8,6 +8,7 @@ import content.region.fremennik.rellekka.handlers.RellekkaDestination import content.region.fremennik.rellekka.handlers.RellekkaUtils import core.tools.END_DIALOGUE import core.api.* +import content.data.Quests @Initializable class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { @@ -35,7 +36,7 @@ class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialogueP 2 -> { end() - if (!hasRequirement(player, "Fremennik Trials")) + if (!hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)) return true RellekkaUtils.sail(player, if(npc.id == NPCs.MORD_GUNNARS_5481) RellekkaDestination.RELLEKKA_TO_JATIZSO else RellekkaDestination.JATIZSO_TO_RELLEKKA) } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/BjornAndEldgrimDialogues.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/BjornAndEldgrimDialogues.kt index 216967b80..47b7a42e5 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/BjornAndEldgrimDialogues.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/BjornAndEldgrimDialogues.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,9 +19,9 @@ class BjornAndEldgrimDialogues(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { player(FacialExpression.FRIENDLY, "Hello there.").also { stage = 0 } - } else if (isQuestComplete(player, "Fremennik Trials")) { + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npc(FacialExpression.DRUNK, "Hey! Itsh you again! Whatshyerfashe!").also { stage = 10 } } return true diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/BlaninDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/BlaninDialogue.kt index 1bc5c3712..52a931e01 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/BlaninDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/BlaninDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class BlaninDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { player(FacialExpression.FRIENDLY, "Good day.").also { stage = 0 } } else { player(FacialExpression.FRIENDLY, "That's one less thing to worry about.").also { stage = 10 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/CouncilWorkerDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/CouncilWorkerDialogue.kt index 8e6434f54..c54085080 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/CouncilWorkerDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/CouncilWorkerDialogue.kt @@ -7,12 +7,13 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.entity.player.link.diary.DiaryType import core.plugin.Initializable +import content.data.Quests @Initializable class CouncilWorkerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if(getQuestStage(player, "Fremennik Trials") in 1..99){ + if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) in 1..99){ player.dialogueInterpreter.open((CouncilWorkerFTDialogue(1))) } else if(player.achievementDiaryManager.getDiary(DiaryType.FREMENNIK).isComplete(0, true)){ diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/DronDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/DronDialogue.kt index 586034287..d2f20660e 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/DronDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/DronDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class DronDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Making History")) { + if (!isQuestComplete(player, Quests.MAKING_HISTORY)) { player(FacialExpression.FRIENDLY, "Excuse me.").also { stage = 0 } } else { player(FacialExpression.FRIENDLY, "Excuse me.").also { stage = 10 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/FishmongerRellekkaDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/FishmongerRellekkaDialogue.kt index 8a35e9dc3..ae896659c 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/FishmongerRellekkaDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/FishmongerRellekkaDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class FishmongerRellekkaDialogue(player: Player? = null) : DialoguePlugin(player override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npc(FacialExpression.ANNOYED, "I don't sell to outerlanders.").also { stage = END_DIALOGUE } } else { npcl(FacialExpression.FRIENDLY,"Hello there, ${player.getAttribute("fremennikname","fremmyname")}. Looking for fresh fish?").also { stage = 0 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/FurTraderDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/FurTraderDialogue.kt index e8f11f81c..a117d29ed 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/FurTraderDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/FurTraderDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class FurTraderDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npc(FacialExpression.ANNOYED, "I don't sell to outerlanders.").also { stage = END_DIALOGUE } } else { npcl(FacialExpression.FRIENDLY,"Welcome back, ${player.getAttribute("fremennikname","fremmyname")}. Have you seen the furs I have today?").also { stage = 10 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/IngridHradsonDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/IngridHradsonDialogue.kt index bf81e8182..ba86e5be8 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/IngridHradsonDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/IngridHradsonDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,11 +19,11 @@ class IngridHradsonDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npcl(FacialExpression.ANNOYED, "Outlander, I have work to be getting on with... Please stop bothering me.").also { stage = END_DIALOGUE } - } else if (isQuestComplete(player, "Fremennik Trials") && !isQuestComplete(player, "Olaf's Quest")) { + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && !isQuestComplete(player, Quests.OLAFS_QUEST)) { npc(FacialExpression.FRIENDLY, "Good afternoon! How do you like our village?").also { stage = 0 } - } else if (isQuestComplete(player, "Fremennik Trials") && isQuestComplete(player, "Olaf's Quest")) { + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && isQuestComplete(player, Quests.OLAFS_QUEST)) { npc(FacialExpression.ASKING, "Hello again! Have you any word from my husband?").also { stage = 10 } } return true diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt index 289ae1bd0..b4dfcbdf2 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/JarvaldDialogue.kt @@ -11,6 +11,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests /** @@ -25,7 +26,7 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { val fremname = player.getAttribute("fremennikname","lebron james") if (npc.id == NPCs.JARVALD_2438) { // We're on Waterbirth Island - if (isQuestComplete(player, "Fremennik Trials")) { + if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { if (travelOption) { npc("So what say you, stay here for the hunt,","or return home to sweet Rellekka to feast","and drink with your tribe?").also { stage = 201 } } else { @@ -40,7 +41,7 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { } } else { // We're in Rellekka - if (isQuestComplete(player, "Fremennik Trials")) { + if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { if (travelOption) { npc("Of course, ${fremname}! Your presence is more than welcome","on this cull! You wish to leave now?").also { stage = 131 } } else { @@ -49,7 +50,7 @@ class JarvaldDialogue(player: Player? = null) : DialoguePlugin(player) { } else { if (travelOption) { npc("So do you have the 1,000 coins for my service, and are", "you ready to leave?").also { stage = 41 } - } else if (isQuestInProgress(player, "Fremennik Trials", 1, 100)) { + } else if (isQuestInProgress(player, Quests.THE_FREMENNIK_TRIALS, 1, 100)) { player("Hi, I don't suppose you are a member of", "the council of elders are you?").also { stage = 0 } } else { npc("What do you want from me outerlander?", "It is our policy not to associate with those not of our", "tribe.").also { stage = 3 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/LonghallBouncerDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/LonghallBouncerDialogue.kt index 6e7db868e..296b0a7fc 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/LonghallBouncerDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/LonghallBouncerDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class LonghallBouncerDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npcl(FacialExpression.ANNOYED, "Hey, outerlander. You can't go through there. Talent only, backstage.").also { stage = END_DIALOGUE } } else{ npcl(FacialExpression.ANNOYED, "You can't go through there. Talent only, backstage.").also { stage = 0 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java b/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java index 766227b3a..b998fa8af 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java @@ -7,6 +7,7 @@ import content.region.fremennik.rellekka.handlers.RellekkaDestination; import content.region.fremennik.rellekka.handlers.RellekkaUtils; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the maria gunnars dialogue. @@ -65,7 +66,7 @@ public class MariaGunnarsDialogue extends DialoguePlugin { break; case 3: end(); - if (!hasRequirement(player, "Fremennik Trials")) + if (!hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)) break; if (npc.getId() == 5508) { RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT); diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/ReesoDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/ReesoDialogue.kt index b1ae7e78d..9636f23ae 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/ReesoDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/ReesoDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,7 +19,7 @@ class ReesoDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npcl(FacialExpression.ANNOYED, "Please do not disturb me, outerlander. I have much to do.").also { stage = END_DIALOGUE } } else { npcl(FacialExpression.STRUGGLE, "Sorry, ${player.getAttribute("fremennikname","fremmyname")}, I must get on with my work.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/TalkToChiefDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/TalkToChiefDialogue.kt index ecb633408..6c371733a 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/TalkToChiefDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/TalkToChiefDialogue.kt @@ -8,10 +8,11 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz - * There is no available dialogue for after Fremennik Trials, + * There is no available dialogue for after The Fremennik Trials, * only after Hero's Welcome which isn't in this revision. */ @@ -20,7 +21,7 @@ class TalkToChiefDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npcl(FacialExpression.ANNOYED, "I cannot speak to you outerlander! Talk to Brundt, the Chieftain!").also { stage = END_DIALOGUE } } else { player(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/VolfOlasfsonDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/dialogue/VolfOlasfsonDialogue.kt index 59e104ce2..315312236 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/VolfOlasfsonDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/VolfOlasfsonDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests /** * @author qmqz @@ -18,11 +19,11 @@ class VolfOlasfsonDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { npc(FacialExpression.ANNOYED, "Sorry, outlander, but I have things to be doing.").also { stage = END_DIALOGUE } - } else if (isQuestComplete(player, "Fremennik Trials") && !isQuestComplete(player, "Olaf's Quest")) { + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && !isQuestComplete(player, Quests.OLAFS_QUEST)) { npc(FacialExpression.FRIENDLY, "Hello there. Enjoying the view?").also { stage = 0 } - } else if (isQuestComplete(player, "Fremennik Trials") && isQuestComplete(player, "Olaf's Quest")) { + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) && isQuestComplete(player, Quests.OLAFS_QUEST)) { npcl(FacialExpression.ASKING, "Hello again, friend! Does my father send any word... or treasures like before?").also { stage = 10 } } return true diff --git a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt index 33fc0d94f..cac9e67e8 100644 --- a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt @@ -5,6 +5,7 @@ import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.world.map.Location import org.rs09.consts.NPCs +import content.data.Quests /** * File to be used for anything Rellekka related. @@ -48,7 +49,7 @@ class RellekkaListeners : InteractionListener { } on(NPCs.MARIA_GUNNARS_5508, IntType.NPC, "ferry-neitiznot"){ player, _ -> - if (!hasRequirement(player, "Fremennik Trials")) + if (!hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)) return@on true RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT) playJingle(player, 171) @@ -62,7 +63,7 @@ class RellekkaListeners : InteractionListener { } on(NPCs.MORD_GUNNARS_5481, IntType.NPC, "ferry-jatizso"){ player, node -> - if (!hasRequirement(player, "Fremennik Trials")) + if (!hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)) return@on true RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_JATIZSO) playJingle(player, 171) diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/AskeladdenDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/AskeladdenDialogue.kt index 387ccc2e7..526732374 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/AskeladdenDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/AskeladdenDialogue.kt @@ -6,6 +6,7 @@ import core.game.dialogue.FacialExpression import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable //Disabled because the quest isn't done yet. @@ -27,12 +28,12 @@ class AskeladdenDialogue(player: Player? = null) : DialoguePlugin(player) { stage = 35 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello again Askeladden.") stage = 40 return true } - else if (it.questRepository.getStage("Fremennik Trials") > 0) { + else if (it.questRepository.getStage(Quests.THE_FREMENNIK_TRIALS) > 0) { player("Hello there.") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt index ddf926874..d9a4dc814 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt @@ -10,6 +10,7 @@ import core.tools.END_DIALOGUE import kotlin.random.Random import org.rs09.consts.* +import content.data.Quests @Initializable class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ @@ -62,12 +63,12 @@ class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ stage = 530 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(FacialExpression.HAPPY,"Hello again, $gender $fName. I hope your travels have brought you wealth and joy! What compels you to visit me on this day?") stage = 600 return true } - else if(player?.questRepository?.getStage("Fremennik Trials")!! == 0) { + else if(player?.questRepository?.getStage(Quests.THE_FREMENNIK_TRIALS)!! == 0) { npc("Greetings outerlander!") stage = 0 } @@ -124,7 +125,7 @@ class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ //I think I would enjoy the challenge of becoming an honorary fremennik 320 -> {npc("As I say outerlander, you must find and speak to the","twelve members of the council of elders, and see what","tasks they might set you.");stage++} - 321 -> {npc("If you can gain the support of seven of the twelve, then","you will be accepted as one of us without question.");stage = 1000;player?.questRepository?.getQuest("Fremennik Trials")?.start(player)} + 321 -> {npc("If you can gain the support of seven of the twelve, then","you will be accepted as one of us without question.");stage = 1000;player?.questRepository?.getQuest(Quests.THE_FREMENNIK_TRIALS)?.start(player)} //That sounds too complicated for me. 322 -> {npc("Well, that's what I expect from an outerlander.");stage = 1000} @@ -180,7 +181,7 @@ class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ 560 -> npcl(FacialExpression.HAPPY,"From this day onward, you are outerlander no more! In honour of your acceptance into the Fremennik, you gain a new name: ${player.getAttribute("fremennikname","how did u break this")}.").also { cleanupAttributes(player) - player.questRepository.getQuest("Fremennik Trials").finish(player) + player.questRepository.getQuest(Quests.THE_FREMENNIK_TRIALS).finish(player) stage = 1000 } @@ -258,7 +259,7 @@ class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ 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))) + if (!hasRequirement(player, Quests.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++ } diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/CouncilWorkerFTDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/CouncilWorkerFTDialogue.kt index f3cb507fd..f9b6223af 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/CouncilWorkerFTDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/CouncilWorkerFTDialogue.kt @@ -5,6 +5,7 @@ import org.rs09.consts.Items import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests const val COUNCIL_WORKER = 1287 @@ -32,7 +33,7 @@ class CouncilWorkerFTDialogue(val questStage: Int, var isBeerInteraction: Boolea else if(questStage in 1..99){ when(stage){ START_DIALOGUE -> - if(getQuestStage(player!!, "Fremennik Trials") > 0) { + if(getQuestStage(player!!, Quests.THE_FREMENNIK_TRIALS) > 0) { player("I know this is an odd question, but are you","a member of the elder council?"); stage = 1 } else { end() diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FishermanDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FishermanDialogue.kt index 30f9bb225..c0c3f4f3f 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FishermanDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FishermanDialogue.kt @@ -8,6 +8,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE +import content.data.Quests @Initializable class FishermanDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -37,9 +38,9 @@ class FishermanDialogue(player: Player? = null) : DialoguePlugin(player) { playerl(FacialExpression.ASKING,"I don't suppose you have any idea where I could find an exotic and extremely odd fish, do you?") stage = 1 return true - } else if (isQuestComplete(player, "Fremennik Trials")){ + } else if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)){ player(FacialExpression.FRIENDLY, "Hello there.").also { stage = 100 } - } else if (!isQuestComplete(player, "Fremennik Trials")) { + } else if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { player(FacialExpression.FRIENDLY, "Hello there.").also { stage = 200 } } return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FremennikTrials.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FremennikTrials.kt index d50e8f42f..ec693af62 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FremennikTrials.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/FremennikTrials.kt @@ -1,16 +1,14 @@ package core.game.content.quest.fremtrials import core.game.node.entity.player.Player -import core.api.* import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills -import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items -import content.minigame.allfiredup.AFUBeacon +import content.data.Quests @Initializable -class FremennikTrials : Quest("Fremennik Trials",64,63,3,347,0,1,10){ +class FremennikTrials : Quest(Quests.THE_FREMENNIK_TRIALS,64,63,3,347,0,1,10){ class SkillRequirement(val skill: Int?, val level: Int?) @@ -19,7 +17,7 @@ class FremennikTrials : Quest("Fremennik Trials",64,63,3,347,0,1,10){ override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 11 - val started = player?.questRepository?.getStage("Fremennik Trials")!! > 0 + val started = player?.questRepository?.getStage(Quests.THE_FREMENNIK_TRIALS)!! > 0 if(!started){ line(player,"Requirements to complete quest:",line++) diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/LalliDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/LalliDialogue.kt index e4f2c9f65..a6d1f37de 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/LalliDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/LalliDialogue.kt @@ -9,13 +9,14 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.item.Item import org.rs09.consts.Items +import content.data.Quests @Initializable class LalliDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { player?.let { println(it.getAttribute("lalliEatStew", false)) - if (it.questRepository.isComplete("Fremennik Trials")){ + if (it.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.NEUTRAL,"Hello there.") stage = 100 return true @@ -45,12 +46,12 @@ class LalliDialogue(player: Player? = null) : DialoguePlugin(player){ stage = 50 return true } - if(player.questRepository.isComplete("Fremennik Trials")){ + if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello there.") stage = 100 return true } - if (it.questRepository.getStage("Fremennik Trials") > 0) { + if (it.questRepository.getStage(Quests.THE_FREMENNIK_TRIALS) > 0) { player("Hello there.").also { stage = 0; return true } } } diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt index 689fc14d1..125bf5702 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt @@ -12,13 +12,14 @@ import core.game.world.map.Location import core.game.world.update.flag.context.Animation import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class ManniDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ var curNPC: NPC? = NPC(0,Location(0,0,0)) override fun open(vararg args: Any?): Boolean { curNPC = args[0] as? NPC - if(player?.questRepository?.getStage("Fremennik Trials")!! > 0){ + if(player?.questRepository?.getStage(Quests.THE_FREMENNIK_TRIALS)!! > 0){ if(player?.inventory?.contains(3707, 1) == true){ playerl(core.game.dialogue.FacialExpression.HAPPY,"Hey. I got your cocktail for you.") stage = 170 @@ -60,7 +61,7 @@ class ManniDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin( stage = 1000 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(core.game.dialogue.FacialExpression.HAPPY,"Howdy!") stage = 190 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt index 8af316688..953098cf6 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt @@ -5,6 +5,7 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable class OlafTheBard(player: Player? = null) : DialoguePlugin(player){ @@ -43,12 +44,12 @@ class OlafTheBard(player: Player? = null) : DialoguePlugin(player){ stage = 1000 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(FacialExpression.HAPPY,"Hello again to you, ${player.getAttribute("fremennikname","schlonko")}. Us bards should stick together, what can I do for you?") stage = 98 return true } - else if(player.questRepository.hasStarted("Fremennik Trials")){ + else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ npc("Hello? Yes? You want something outerlander?") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt index 88ea2456b..daf4e9d34 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt @@ -10,6 +10,7 @@ import core.plugin.Initializable import core.tools.RandomFunction import core.tools.END_DIALOGUE import kotlin.random.Random +import content.data.Quests @Initializable class PeerTheSeerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { @@ -69,17 +70,17 @@ class PeerTheSeerDialogue(player: Player? = null) : core.game.dialogue.DialogueP stage = 120 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(core.game.dialogue.FacialExpression.SAD,"Uuuh... What was that dark presence I felt?") stage = 150 return true } - else if(player.questRepository.hasStarted("Fremennik Trials")){ + else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ npcl(core.game.dialogue.FacialExpression.SAD,"Uuuh... What was that dark presence I felt?") stage = 50 return true } - if (getQuestStage(player, "Fremennik Trials") == 0) { + if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) == 0) { npc(core.game.dialogue.FacialExpression.SAD,"Uuuh... What was that dark presence I felt?").also { stage = 300 } } return true @@ -210,7 +211,7 @@ class PeerTheSeerDialogue(player: Player? = null) : core.game.dialogue.DialogueP 123 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Absolutely, outerlander. Your wisdom in passing my test marks you as worthy in my eyes.").also { stage = 1000 } - //After Fremennik Trials + //After The Fremennik Trials 150 -> npcl(core.game.dialogue.FacialExpression.AMAZED,"!").also { stage++ } 151 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Ahem, sorry about that.").also { stage = if(player.achievementDiaryManager.getDiary(DiaryType.FREMENNIK).isComplete(0)){ diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PoisonSalesman.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PoisonSalesman.kt index e3d874010..f214c66d2 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PoisonSalesman.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PoisonSalesman.kt @@ -6,19 +6,20 @@ import core.game.node.item.Item import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests @Initializable class PoisonSalesman(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { - options("Talk about the Murder Mystery Quest","Talk about the Fremennik Trials") + options("Talk about the Murder Mystery Quest","Talk about the The Fremennik Trials") stage = START_DIALOGUE return true } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - //val murderMysteryStage = player.questRepository.isComplete("Murder Mystery") - val fremennikTrialsStage = player.questRepository.getStage("Fremennik Trials") + //val murderMysteryStage = player.questRepository.isComplete(Quests.MURDER_MYSTERY) + val fremennikTrialsStage = player.questRepository.getStage(Quests.THE_FREMENNIK_TRIALS) when (stage) { START_DIALOGUE -> when (buttonId) { @@ -26,7 +27,7 @@ class PoisonSalesman(player: Player? = null) : DialoguePlugin(player) { 2 -> { player("Hello."); stage = 10 } } - //Fremennik Trials + //The Fremennik Trials 10 -> { /**when (fremennikTrialsStage) { 0 -> { npc("Come see me if you ever need low-alcohol beer!"); stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt index d987e061e..884959dee 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt @@ -3,11 +3,11 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem import core.api.removeItem import core.game.node.entity.player.Player -import core.game.node.entity.player.info.PlayerDetails import core.game.node.item.Item import core.plugin.Initializable import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression +import content.data.Quests @Initializable class SigliTheHuntsman(player: Player? = null) : DialoguePlugin(player){ @@ -47,12 +47,12 @@ class SigliTheHuntsman(player: Player? = null) : DialoguePlugin(player){ stage = 100 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello again Sigli.") stage = 180 return true } - else if(player.questRepository.hasStarted("Fremennik Trials")){ + else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ npc("What do you want outerlander?") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt index d00e6cf7f..131d1adb8 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class SigmundDialogue (player: Player? = null) : DialoguePlugin(player) { @@ -22,12 +23,12 @@ class SigmundDialogue (player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if(player.questRepository.isComplete("Fremennik Trials")){ + if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello there!") stage = 50 return true } - else if(!player.questRepository.hasStarted("Fremennik Trials")){ + else if(!player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello there!") stage = 60 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SkulgrimenDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SkulgrimenDialogue.kt index f51b1cf71..e4ec8ecfb 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SkulgrimenDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SkulgrimenDialogue.kt @@ -7,6 +7,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable class SkulgrimenDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -38,7 +39,7 @@ class SkulgrimenDialogue(player: Player? = null) : DialoguePlugin(player) { stage = 1 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(FacialExpression.HAPPY,"Hello again, ${player.getAttribute("fremennikname","ringo")}. Come to see what's for sale?") stage = 1001 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt index c06ff2266..77983ca63 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt @@ -3,10 +3,10 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem import core.api.removeItem import core.game.node.entity.player.Player -import core.game.node.entity.player.info.PlayerDetails import core.plugin.Initializable import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression +import content.data.Quests @Initializable class SwensenTheNavigator(player: Player? = null) : DialoguePlugin(player){ @@ -47,12 +47,12 @@ class SwensenTheNavigator(player: Player? = null) : DialoguePlugin(player){ stage = 1000 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(FacialExpression.HAPPY,"Hello!") stage = 140 return true } - else if(player.questRepository.hasStarted("Fremennik Trials")){ + else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ player("Hello!") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt index 5a6686c29..d65bbe126 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt @@ -21,6 +21,7 @@ import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.system.config.ItemConfigParser import core.game.world.GameWorld.Pulser +import content.data.Quests class TFTInteractionListeners : InteractionListener { @@ -167,7 +168,7 @@ class TFTInteractionListeners : InteractionListener { on(LYRE_IDs, IntType.ITEM, "play"){ player, lyre -> if(getAttribute(player,"onStage",false) && !getAttribute(player,"lyreConcertPlayed",false)){ Pulser.submit(LyreConcertPulse(player,lyre.id)) - } else if(getQuestStage(player, "Fremennik Trials") < 20 || !isQuestComplete(player, "Fremennik Trials")){ + } else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) < 20 || !isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)){ sendMessage(player,"You lack the knowledge to play this.") } else if(LYRE_IDs.isLast(lyre.id)){ sendMessage(player,"Your lyre is out of charges!") @@ -216,7 +217,7 @@ class TFTInteractionListeners : InteractionListener { } on(THORVALD_LADDER, IntType.SCENERY, "climb-down") { player, _ -> - if (isQuestComplete(player, "Fremennik Trials") || getAttribute(player, "fremtrials:thorvald-vote", false)) { + if (isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) || getAttribute(player, "fremtrials:thorvald-vote", false)) { sendMessage(player,"You have no reason to go back down there.") return@on true } else if (!getAttribute(player,"fremtrials:warrior-accepted",false)) { @@ -263,7 +264,7 @@ class TFTInteractionListeners : InteractionListener { } on(SHOPNPCS, IntType.NPC, "Trade") { player, npc -> - if(isQuestComplete(player, "Fremennik Trials")){ + if(isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)){ npc.asNpc().openShop(player) } else when(npc.id){ NPCs.THORA_THE_BARKEEP_1300 -> sendDialogue(player,"Only Fremenniks may buy drinks here.") diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThoraDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThoraDialogue.kt index 647d74df1..51159d5d6 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThoraDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThoraDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.item.Item import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class ThoraDialogue(player: Player? = null) : DialoguePlugin(player){ @@ -36,7 +37,7 @@ class ThoraDialogue(player: Player? = null) : DialoguePlugin(player){ playerl(FacialExpression.ASKING,"I don't suppose you have any idea where I could find the longhall barkeeps' legendary cocktail, do you?") stage = 1 } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(FacialExpression.HAPPY,"Hello again, $fName. I suppose you want a drink? Or are you going to try another scam with that terrible Askeladden again?") stage = 50 } diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt index 0d3523007..ff0d5deb2 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt @@ -5,6 +5,7 @@ import core.api.removeItem import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ @@ -39,7 +40,7 @@ class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlug stage = 150 return true } - else if (player?.questRepository?.isComplete("Fremennik Trials")!!) { + else if (player?.questRepository?.isComplete(Quests.THE_FREMENNIK_TRIALS)!!) { playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Howdy Thorvald!") stage = 0 return true @@ -49,12 +50,12 @@ class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlug stage = 160 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ playerl(core.game.dialogue.FacialExpression.HAPPY,"Howdy Thorvald!") stage = 250 return true } - else if(!player.questRepository.hasStarted("Fremennik Trials")){ + else if(!player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ npcl(core.game.dialogue.FacialExpression.ANNOYED, "Leave me be, outerlander. I have nothing to say to the likes of you.") stage = 1000 return true @@ -75,7 +76,7 @@ class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlug override fun handle(interfaceId: Int, buttonId: Int): Boolean { when(stage){ - //After Fremennik Trials + //After The Fremennik Trials 0 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "And greetings to you too. It is good to see new blood entering the Fremennik; we gain our strength by bringing new warriors into the tribe.").also { stage = 1000 } //Warrior Trial diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/YrsaDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/YrsaDialogue.kt index ef174fa42..a515d5dde 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/YrsaDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/YrsaDialogue.kt @@ -7,6 +7,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable class YrsaDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -38,7 +39,7 @@ class YrsaDialogue(player: Player? = null) : DialoguePlugin(player) { stage = 1 return true } - else if(player.questRepository.isComplete("Fremennik Trials")){ + else if(player.questRepository.isComplete(Quests.THE_FREMENNIK_TRIALS)){ npcl(FacialExpression.HAPPY,"Welcome to my clothes shop. I can change your shoes, or I've got a fine selection of clothes for sale.") stage = 30 //Uncomment this out when we got the shoe shop up and running diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt index 7cba51211..75c806a89 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt @@ -7,13 +7,14 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class KilronDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getQuest("Plague City").isCompleted(player)){ + if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)){ npcl(FacialExpression.FRIENDLY, "Looks like you won't be needing the rope ladder any more, adventurer. I heard it was you who started the revolution and freed West Ardougne!").also { stage = END_DIALOGUE } } else { playerl(FacialExpression.FRIENDLY, "Hello there.") diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt index cd8c50d4f..c5bee2f92 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt @@ -9,13 +9,14 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") == 1) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 1) { playerl(FacialExpression.FRIENDLY, "Hello, Edmond has asked me to help find your daughter.").also { stage++ } } else { playerl(FacialExpression.FRIENDLY, "Hello Madam.").also { stage++ } @@ -24,7 +25,7 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 0 -> when (stage) { 1 -> npcl(FacialExpression.NEUTRAL, "Oh, hello there.").also { stage++ } @@ -49,7 +50,7 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { 7 -> { end() addItem(player!!, Items.GAS_MASK_1506) - setQuestStage(player!!, "Plague City", 2) + setQuestStage(player!!, Quests.PLAGUE_CITY, 2) setAttribute(player!!, PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) sendNPCDialogue(player!!, NPCs.ALRENA_710, "I'll make a spare mask. I'll hide it in the wardrobe in case the mourners come in.") } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt index bdee4777d..00b3d95e4 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt @@ -9,19 +9,20 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") == 0) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 0) { npcl(FacialExpression.ANGRY, "Go away, I'm busy! I'm... Um... In a meeting!").also { stage = END_DIALOGUE } - } else if (player.questRepository.getStage("Plague City") == 13) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 13) { npcl(FacialExpression.NEUTRAL, "My head hurts! I'll speak to you another day...").also { stage = 1 } - } else if (player.questRepository.getStage("Plague City") == 14) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 14) { npcl(FacialExpression.NEUTRAL, "Uurgh! My head still hurts too much to think straight. Oh for one of Trudi's hangover cures!").also { stage = 1 } - } else if (player.questRepository.getStage("Plague City") >= 16) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 16) { npcl(FacialExpression.NEUTRAL, "Thanks again for the hangover cure.").also { stage = 1 } } else { npcl(FacialExpression.ANGRY, "Go away, I'm busy! I'm... Um... In a meeting!").also { stage = END_DIALOGUE } @@ -30,7 +31,7 @@ class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 13 -> when (stage) { 1 -> playerl(FacialExpression.FRIENDLY, "This is really important though!").also { stage = 2 } @@ -55,7 +56,7 @@ class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { end() sendItemDialogue(player!!, Items.A_SCRUFFY_NOTE_1508, "Bravek hands you a tatty piece of paper.").also { stage++ } addItem(player!!, Items.A_SCRUFFY_NOTE_1508) - setQuestStage(player!!, "Plague City", 14) + setQuestStage(player!!, Quests.PLAGUE_CITY, 14) } } @@ -95,7 +96,7 @@ class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { end() sendItemDialogue(player!!, Items.WARRANT_1503, "Bravek hands you a warrant.").also { stage = END_DIALOGUE } addItem(player!!, Items.WARRANT_1503) - setQuestStage(player!!, "Plague City", 16) + setQuestStage(player!!, Quests.PLAGUE_CITY, 16) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt index 3f44c539e..485367c39 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt @@ -10,6 +10,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class ClerkDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -21,7 +22,7 @@ class ClerkDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 11 -> when (stage) { 0 -> options("Who is through that door?", "I'm just looking thanks.").also { stage++ } @@ -65,7 +66,7 @@ class ClerkDialogue(player: Player? = null) : DialoguePlugin(player) { 12 -> npcl(FacialExpression.HALF_GUILTY, "Mr Bravek, there's a man here who really needs to speak to you.").also { stage++ } 13 -> { end() - setQuestStage(player!!, "Plague City", 13) + setQuestStage(player!!, Quests.PLAGUE_CITY, 13) sendNPCDialogue(player!!, NPCs.BRAVEK_711, "I suppose they can come in then. If they keep it short.").also { stage++ } } 14 -> npcl(FacialExpression.HALF_GUILTY, "Oh I don't know, an hour or so maybe.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt index 9d77ce77b..eae81dfa8 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt @@ -9,15 +9,16 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if(inEquipmentOrInventory(player, Items.GAS_MASK_1506) && (player.questRepository.getStage("Plague City") == 2)) { + if(inEquipmentOrInventory(player, Items.GAS_MASK_1506) && (player.questRepository.getStage(Quests.PLAGUE_CITY) == 2)) { playerl(FacialExpression.FRIENDLY, "Hi Edmond, I've got the gas mask now.").also { stage++ } - } else if(player.questRepository.getStage("Plague City") > 2) { + } else if(player.questRepository.getStage(Quests.PLAGUE_CITY) > 2) { playerl(FacialExpression.FRIENDLY, "Hello Edmond.").also { stage++ } } else { playerl(FacialExpression.FRIENDLY, "Hello old man.").also { stage++ } @@ -26,7 +27,7 @@ class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 0 -> when (stage) { 1 -> npcl(FacialExpression.NEUTRAL, "Sorry, I can't stop to talk...").also { stage++ } @@ -56,7 +57,7 @@ class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { 19 -> npcl(FacialExpression.NEUTRAL, "The foresters keep a close eye on it, but there is a back way in.").also { stage++ } 20 -> { end() - setQuestStage(player!!, PlagueCity.PlagueCityQuest, 1) + setQuestStage(player!!, Quests.PLAGUE_CITY, 1) } } @@ -78,7 +79,7 @@ class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { 2 -> npcl(FacialExpression.NEUTRAL, "The problem is the soil is rock hard. You'll need to pour on several buckets of water to soften it up. I'll keep an eye out for the mourners.").also { stage++ } 3 -> { end() - setQuestStage(player!!, "Plague City", 3) + setQuestStage(player!!, Quests.PLAGUE_CITY, 3) } } @@ -137,7 +138,7 @@ class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { 3 -> npcl(FacialExpression.NEUTRAL, "Here take this magic scroll, I have little use for it but it may help you.").also { stage++ } 4 -> { end() - player!!.questRepository.getQuest("Plague City").finish(player) + player!!.questRepository.getQuest(Quests.PLAGUE_CITY).finish(player) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt index 223bf156b..01f40dc88 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt @@ -8,13 +8,14 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class ElenaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") >= 16) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 16) { playerl(FacialExpression.FRIENDLY, "Hi, you're free to go! Your kidnappers don't seem to be about right now.").also { stage = 1 } } else { npcl(FacialExpression.FRIENDLY, "Go and see my father, I'll make sure he adequately rewards you. Now I'd better leave while I still can.").also { stage = END_DIALOGUE } @@ -29,7 +30,7 @@ class ElenaDialogue(player: Player? = null) : DialoguePlugin(player) { 3 -> npcl(FacialExpression.FRIENDLY, "Go and see my father, I'll make sure he adequately rewards you. Now I'd better leave while I still can.").also { stage++ } 4 -> { end() - setQuestStage(player!!, "Plague City", 99) + setQuestStage(player!!, Quests.PLAGUE_CITY, 99) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt index d3e8c6d48..778b5f947 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt @@ -8,12 +8,13 @@ import core.game.node.entity.npc.NPC import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class HeadMournerDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.HEAD_MOURNER_716) - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { in 8..10 -> when (stage) { 0 -> npcl(FacialExpression.FRIENDLY, "Hmmm, how did you get over here? You're not one of this rabble. Ah well, you'll have to stay. Can't risk you going back now.").also { stage++ } @@ -48,7 +49,7 @@ class HeadMournerDialogue : DialogueFile() { 8 -> npcl(FacialExpression.NEUTRAL, "I wouldn't get your hopes up though.").also { stage++ } 9 -> { end() - setQuestStage(player!!, "Plague City", 12) + setQuestStage(player!!, Quests.PLAGUE_CITY, 12) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt index 598354db4..4674daa6f 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt @@ -9,22 +9,23 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable class JethickDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") in 0..11) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) in 0..11) { npcl(FacialExpression.FRIENDLY, "Hello I don't recognise you. We don't get many newcomers around here.").also { stage++ } - } else if (player.questRepository.getStage("Plague City") >= 12) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 12) { npcl(FacialExpression.FRIENDLY,"Hello. We don't get many newcomers around here.").also { stage = END_DIALOGUE } } return true } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { in 0..1 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Well King Tyras has wandered off into the west kingdom. He doesn't care about the mess he's left here. The city warder Bravek is in charge at the moment... He's not much better.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt index 79a130c2d..8893f9c3d 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt @@ -8,13 +8,14 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class MarthaRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") == 9) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 9) { playerl(FacialExpression.NEUTRAL, "Hi, I hear a woman called Elena is staying here.").also { stage++ } } else { npcl(FacialExpression.FRIENDLY, "Any luck finding Elena yet?").also { stage++ } @@ -23,7 +24,7 @@ class MarthaRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 9 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Yes she was staying here, but slightly over a week ago she was getting ready to go back.").also { stage++ } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt index 811f069d7..649a922f1 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt @@ -9,13 +9,14 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") == 9) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 9) { playerl(FacialExpression.FRIENDLY, "Hello. Your parents say you saw what happened to Elena...").also { stage++ } } else { npcl(FacialExpression.FRIENDLY, "Any luck finding Elena yet?").also { stage++ } @@ -24,7 +25,7 @@ class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 9 -> when(stage) { 1 -> npcl(FacialExpression.NEUTRAL, "*sniff* Yes I was near the south east corner when I saw Elena walking by. I was about to run to greet her when some men jumped out. They shoved a sack over her head and dragged her into a building.").also { stage++ } @@ -32,7 +33,7 @@ class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { 3 -> npcl(FacialExpression.NEUTRAL, "It was the boarded up building with no windows in the south east corner of West Ardougne.").also { stage++ } 4 -> { end() - setQuestStage(player!!, "Plague City", 11) + setQuestStage(player!!, Quests.PLAGUE_CITY, 11) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt index 7dc148c27..450e37ae5 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt @@ -9,12 +9,13 @@ import core.game.world.map.RegionManager.getObject import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class MournerDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.MOURNER_3216) - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { in 0..6 -> when (stage) { 0 -> playerl(FacialExpression.FRIENDLY, "Hello.").also { stage++ } @@ -70,7 +71,7 @@ class MournerDialogue : DialogueFile() { findLocalNPC(player!!, NPCs.MOURNER_3216)!!.sendChat("Well you can't let them in...", 1) }.also { end() - setQuestStage(player!!, "Plague City", 17) + setQuestStage(player!!, Quests.PLAGUE_CITY, 17) DoorActionHandler.handleAutowalkDoor(player, getObject(location(2540, 3273, 0))!!.asScenery()) sendDialogue(player!!, "You wait until the mourner's back is turned and sneak into the building.") } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt index 47585fbd1..b3ae7dbaf 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.plaguecity.quest.elena -import core.api.addItem import core.api.addItemOrDrop import core.api.removeAttributes import core.api.rewardXP @@ -9,11 +8,11 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class PlagueCity : Quest("Plague City", 98, 97, 1, 165, 0, 1, 29) { +class PlagueCity : Quest(Quests.PLAGUE_CITY, 98, 97, 1, 165, 0, 1, 29) { override fun newInstance(`object`: Any?): Quest { return this } - companion object { const val PlagueCityQuest = "Plague City" } override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 11 diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt index 469f9302a..d7f508651 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt @@ -17,6 +17,7 @@ import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs import org.rs09.consts.Scenery +import content.data.Quests class PlagueCityListeners : InteractionListener { companion object { @@ -99,7 +100,7 @@ class PlagueCityListeners : InteractionListener { } on(LEFT_DOOR, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getQuest("Plague City").isCompleted(player)) { + if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else if(inBorders(player, 2556, 3298, 2557, 3301)){ lock(player,2) @@ -115,7 +116,7 @@ class PlagueCityListeners : InteractionListener { } on(RIGHT_DOOR, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getQuest("Plague City").isCompleted(player)) { + if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else if(inBorders(player, 2556, 3298, 2557, 3301)){ lock(player,2) @@ -151,7 +152,7 @@ class PlagueCityListeners : InteractionListener { } on(BRAVEK_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage("Plague City") >= 13) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 13) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendNPCDialogue(player,BRAVEK,"Go away, I'm busy! I'm... Umm... In a meeting!") @@ -182,11 +183,11 @@ class PlagueCityListeners : InteractionListener { } on(HEAD_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage("Plague City") == 11) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 11) { openDialogue(player, HeadMournerDialogue()) - } else if (player.questRepository.getStage("Plague City") == 16) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 16) { openDialogue(player, MournerDialogue()) - } else if (player.questRepository.getStage("Plague City") > 16) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) > 16) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { openDialogue(player, MournerDialogue()) @@ -199,7 +200,7 @@ class PlagueCityListeners : InteractionListener { sendItemDialogue(player, GAS_MASK, "You find a protective mask but you don't have enough room to take it.") } else if (inEquipmentOrInventory(player, GAS_MASK)) { sendMessage(player, "You search the wardrobe but you find nothing.") - } else if (player.questRepository.getStage("Plague City") >= 2) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 2) { sendItemDialogue(player, GAS_MASK, "You find a protective mask.") addItem(player, GAS_MASK) } @@ -240,7 +241,7 @@ class PlagueCityListeners : InteractionListener { 1 -> animate(player, DIG_WITH_SPADE) 3 -> { teleport(player, Location(2518, 9759)) - setQuestStage(player, "Plague City", 4) + setQuestStage(player, Quests.PLAGUE_CITY, 4) player.dialogueInterpreter.sendDialogue( "You fall through...", "...you land in the sewer.", @@ -259,10 +260,10 @@ class PlagueCityListeners : InteractionListener { } on(GRILL, IntType.SCENERY, "open") { player, _ -> - if (player.questRepository.getStage("Plague City") == 4) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 4) { sendDialogue(player, "The grill is too secure. You can't pull it off alone.") animate(player, TRYING_TO_OPEN_GRILL) - setQuestStage(player, "Plague City", 5) + setQuestStage(player, Quests.PLAGUE_CITY, 5) } else { sendDialogue(player, "There is a grill blocking your way") } @@ -270,14 +271,14 @@ class PlagueCityListeners : InteractionListener { } on(PIPE, IntType.SCENERY, "climb-up") { player, _ -> - if (player.questRepository.getStage("Plague City") >= 7 && inEquipment(player, GAS_MASK)) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 7 && inEquipment(player, GAS_MASK)) { animate(player, GO_INTO_PIPE,true) forceMove(player, Location(2514, 9739, 0), Location(2514, 9734, 0), 0, 4,Direction.SOUTH) runTask(player, 3) { teleport(player, Location(2529, 3304, 0)) sendDialogue(player, "You climb up through the sewer pipe.") } - } else if (player.questRepository.getStage("Plague City") >= 7 && !inEquipment(player, GAS_MASK)) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 7 && !inEquipment(player, GAS_MASK)) { sendNPCDialogue(player, NPCs.EDMOND_714, "I can't let you enter the city without your gasmask on.") } else { sendDialogue(player, "There is a grill blocking your way") @@ -303,7 +304,7 @@ class PlagueCityListeners : InteractionListener { setVarbit(player, 1787, 5, true) // Tied rope to the grill. } 4 -> { - setQuestStage(player, "Plague City", 6) + setQuestStage(player, Quests.PLAGUE_CITY, 6) sendItemDialogue(player, ROPE, "You tie the end of the rope to the sewer pipe's grill.") } } @@ -331,14 +332,14 @@ class PlagueCityListeners : InteractionListener { 4 -> { end() DoorActionHandler.handleAutowalkDoor(player, getScenery(2531, 3328, 0)) - setQuestStage(player!!, "Plague City", 9) + setQuestStage(player!!, Quests.PLAGUE_CITY, 9) } } } } on(PLAGUE_TED_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage("Plague City") >= 9) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 9) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { openDialogue(player, TedRehnisonDoors()) @@ -357,7 +358,7 @@ class PlagueCityListeners : InteractionListener { } onUseWith(IntType.ITEM, CHOCOLATE_DUST, BUCKET_OF_MILK) { player, _, _ -> - if (player.questRepository.hasStarted("Plague City") && removeItem(player, CHOCOLATE_DUST) && removeItem(player, BUCKET_OF_MILK)) { + if (player.questRepository.hasStarted(Quests.PLAGUE_CITY) && removeItem(player, CHOCOLATE_DUST) && removeItem(player, BUCKET_OF_MILK)) { sendItemDialogue(player, CHOCOLATE_MILK, "You mix the chocolate into the bucket.") addItem(player, CHOCOLATE_MILK) } else { @@ -367,7 +368,7 @@ class PlagueCityListeners : InteractionListener { } onUseWith(IntType.ITEM, SNAPE_GRASS, CHOCOLATE_MILK) { player, _, _ -> - if (player.questRepository.hasStarted("Plague City") && removeItem(player, SNAPE_GRASS) && removeItem(player, CHOCOLATE_MILK)) { + if (player.questRepository.hasStarted(Quests.PLAGUE_CITY) && removeItem(player, SNAPE_GRASS) && removeItem(player, CHOCOLATE_MILK)) { sendItemDialogue(player, HANGOVER_CURE, "You mix the snape grass into the bucket.") addItem(player, HANGOVER_CURE) } else { @@ -409,7 +410,7 @@ class PlagueCityListeners : InteractionListener { } onUseWith(IntType.SCENERY, SMALL_KEY, PRISON_DOORS) { player, _, _ -> - if (player.questRepository.getStage("Plague City") >= 16) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 16) { DoorActionHandler.handleAutowalkDoor(player, core.game.world.map.RegionManager.getObject(Location(2539, 9672, 0))!!.asScenery()) sendDialogue(player, "You unlock the door.") } else { @@ -419,7 +420,7 @@ class PlagueCityListeners : InteractionListener { } on(PRISON_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage("Plague City") >= 99) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 99) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { openDialogue(player, ElenaDoorDialogue()) diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt index f7534526d..9eadacf27 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt @@ -8,15 +8,16 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class TedRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Plague City") == 9) { + if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 9) { playerl(FacialExpression.NEUTRAL, "Hi, I hear a woman called Elena is staying here.").also { stage++ } - } else if (player.questRepository.getStage("Plague City") > 9) { + } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) > 9) { npcl(FacialExpression.FRIENDLY, "Any luck finding Elena yet?").also { stage++ } } else { npcl(FacialExpression.FRIENDLY, "Go away. We don't want any.").also { stage = END_DIALOGUE } @@ -25,7 +26,7 @@ class TedRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, PlagueCity.PlagueCityQuest)) { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 9 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Yes she was staying here, but slightly over a week ago she was getting ready to go back. However she never managed to leave. My daughter Milli was playing near the west wall when she saw some shadowy figures jump").also { stage++ } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt index c924cc595..27869f495 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt +++ b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt @@ -6,6 +6,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.game.world.map.Direction import core.game.world.map.Location +import content.data.Quests class UndergroundCutscene(player: Player) : Cutscene(player) { @@ -102,7 +103,7 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { 14 -> { end { - setQuestStage(player, "Plague City", 7) + setQuestStage(player, Quests.PLAGUE_CITY, 7) } } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArena.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArena.kt index 20ac88e15..9c97b7110 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArena.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArena.kt @@ -6,13 +6,12 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable -import org.rs09.consts.Items import org.rs09.consts.Items.COINS_995 +import content.data.Quests @Initializable -class FightArena : Quest("Fight Arena", 61, 60, 2, 17, 0, 1, 14) { +class FightArena : Quest(Quests.FIGHT_ARENA, 61, 60, 2, 17, 0, 1, 14) { override fun newInstance(`object`: Any?): Quest { return this } - companion object { const val FightArenaQuest = "Fight Arena" } override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 11 diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArenaListeners.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArenaListeners.kt index 1150597ca..8e4526390 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArenaListeners.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/FightArenaListeners.kt @@ -13,6 +13,7 @@ import core.game.world.map.Location import org.rs09.consts.Items import org.rs09.consts.NPCs import org.rs09.consts.Scenery +import content.data.Quests class FightArenaListeners : InteractionListener { companion object { @@ -100,7 +101,7 @@ class FightArenaListeners : InteractionListener { } on(FULL_ARMOR_STAND, IntType.SCENERY, "borrow") { player, _ -> - if (player.questRepository.getStage("Fight Arena") >= 10 && !inEquipmentOrInventory(player, HELMET) && !inEquipmentOrInventory(player, ARMOR) && freeSlots(player) >= 2) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) >= 10 && !inEquipmentOrInventory(player, HELMET) && !inEquipmentOrInventory(player, ARMOR) && freeSlots(player) >= 2) { replaceScenery(FULL_ARMOR_STAND_1!!.asScenery(), EMPTY_STAND, 10,location(2619, 3196, 0)) sendMessage(player, "You borrow the suit of armour. It looks like it's just your size.") addItem(player, ARMOR, 1) @@ -162,7 +163,7 @@ class FightArenaListeners : InteractionListener { } onUseWith(IntType.SCENERY, CELL_KEY, CELL_DOOR_1) { player, _, _ -> - if (player.questRepository.getStage("Fight Arena") >= 68){ + if (player.questRepository.getStage(Quests.FIGHT_ARENA) >= 68){ sendDialogue(player, "I don't want to attract too much attention by freeing all the prisoners. I need to find Jeremy and he's not in this cell.") } else { sendMessage(player, "The cell gate is securely locked.") @@ -181,9 +182,9 @@ class FightArenaListeners : InteractionListener { } on(CENTER_DOOR, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage("Fight Arena") >= 91) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) >= 91) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else if (player.questRepository.getStage("Fight Arena") < 91) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) < 91) { sendNPCDialogue(player, NPCs.KHAZARD_GUARD_255, "And where do you think you're going? Only General Khazard decides who fights in the arena. Get out of here.", FacialExpression.ANNOYED) } else { sendMessage(player, "The gate is locked.") @@ -254,7 +255,7 @@ class FightArenaListeners : InteractionListener { 2 -> { end() lock(player!!, 2) - setQuestStage(player!!, FightArena.FightArenaQuest, 20) + setQuestStage(player!!, Quests.FIGHT_ARENA, 20) DoorActionHandler.handleAutowalkDoor(player, getScenery(2617, 3172, 0)) } } @@ -276,7 +277,7 @@ class FightArenaListeners : InteractionListener { 2 -> { end() lock(player!!, 2) - setQuestStage(player!!, FightArena.FightArenaQuest, 20) + setQuestStage(player!!, Quests.FIGHT_ARENA, 20) DoorActionHandler.handleAutowalkDoor(player, getScenery(2584, 3141, 0)) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/ALazyGuardDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/ALazyGuardDialogue.kt index 945a4826b..2a4ffa5a8 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/ALazyGuardDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/ALazyGuardDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -15,7 +15,7 @@ import org.rs09.consts.NPCs class ALazyGuardDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.A_LAZY_KHAZARD_GUARD_8498) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 40..49 -> when (stage) { 0 -> { @@ -27,7 +27,7 @@ class ALazyGuardDialogue : DialogueFile() { 3 -> npcl(FacialExpression.FRIENDLY, "Now I just want a decent drink. Mind you, too much Khali brew and I'll fall asleep.").also { stage++ } 4 -> { end() - setQuestStage(player!!, FightArena.FightArenaQuest, 50) + setQuestStage(player!!, Quests.FIGHT_ARENA, 50) } } @@ -71,7 +71,7 @@ class ALazyGuardDialogue : DialogueFile() { 14 -> { end() setVarbit(player!!, 5627, 2) - setQuestStage(player!!, FightArena.FightArenaQuest, 68) + setQuestStage(player!!, Quests.FIGHT_ARENA, 68) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GeneralKhazardDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GeneralKhazardDialogue.kt index a7eb7248f..11b516bbc 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GeneralKhazardDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GeneralKhazardDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import content.region.kandarin.ardougne.quest.arena.FightArenaListeners.Companion.General import content.region.kandarin.ardougne.quest.arena.cutscenes.JailCutscene import content.region.kandarin.ardougne.quest.arena.cutscenes.ThirdFightCutscene @@ -16,7 +16,7 @@ import org.rs09.consts.NPCs class GeneralKhazardDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.GENERAL_KHAZARD_258) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 68..70 -> when(stage){ 0 -> npcl(FacialExpression.FRIENDLY, "Out of the way, guard! I don't tolerate disruption when I'm watching slaves being slaughtered.").also { stage = END_DIALOGUE } @@ -109,7 +109,7 @@ class GeneralKhazardDialogue : DialogueFile() { 4 -> npcl(FacialExpression.OLD_EVIL_LAUGH, "You however have coused me much trouble today. You must remain here so that I may at least have the pleasure of killing you myself.").also { stage++ } 5 -> { end() - setQuestStage(player!!, FightArena.FightArenaQuest, 97) + setQuestStage(player!!, Quests.FIGHT_ARENA, 97) RegionManager.getNpc(player!!.location, NPCs.GENERAL_KHAZARD_258, 15) General.attack(player!!) } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GuardsDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GuardsDialogue.kt index 5d830e076..77fd6c123 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GuardsDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/GuardsDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable @@ -16,7 +17,7 @@ class GuardsDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Fight Arena") == 100) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 100) { npcl(FacialExpression.FRIENDLY, "It's you! I don't believe it. You beat the General! You are a traitor to the uniform!").also { stage = END_DIALOGUE } } else if (allInEquipment(player, Items.KHAZARD_HELMET_74, Items.KHAZARD_ARMOUR_75)) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } @@ -51,7 +52,7 @@ class GuardsDialogue(player: Player? = null) : DialoguePlugin(player) { class KhazardGuard254Dialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Fight Arena") == 100) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 100) { npcl(FacialExpression.FRIENDLY, "It's you! I don't believe it. You beat the General! You are a traitor to the uniform!").also { stage = END_DIALOGUE } } else if (allInEquipment(player, Items.KHAZARD_HELMET_74, Items.KHAZARD_ARMOUR_75)) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } @@ -95,7 +96,7 @@ class KhazardGuard254Dialogue(player: Player? = null) : DialoguePlugin(player) { class KhazardGuard255Dialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Fight Arena") == 100) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 100) { npcl(FacialExpression.FRIENDLY, "It's you! I don't believe it. You beat the General! You are a traitor to the uniform!").also { stage = END_DIALOGUE } } else if (allInEquipment(player, Items.KHAZARD_HELMET_74, Items.KHAZARD_ARMOUR_75)) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } @@ -130,7 +131,7 @@ class KhazardGuard256Dialogue(player: Player? = null) : DialoguePlugin(player) { npc = args[0] as NPC if (allInEquipment(player, Items.KHAZARD_HELMET_74, Items.KHAZARD_ARMOUR_75)) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } - } else if (player.questRepository.getStage("Fight Arena") == 100) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 100) { npcl(FacialExpression.FRIENDLY, "It's you! I don't believe it. You beat the General! You are a traitor to the uniform!").also { stage = END_DIALOGUE } } else { playerl(FacialExpression.FRIENDLY, "Hi.").also { stage = 3 } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/HengradDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/HengradDialogue.kt index 8d6eccb01..bd31acf9f 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/HengradDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/HengradDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import content.region.kandarin.ardougne.quest.arena.cutscenes.SecondFightCutscene import core.api.* import core.game.dialogue.DialogueFile @@ -11,7 +11,7 @@ import org.rs09.consts.NPCs class HengradDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.HENGRAD_263) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 72..87 -> when (stage) { 0 -> { @@ -34,7 +34,7 @@ class HengradDialogue : DialogueFile() { 10 -> { end() SecondFightCutscene(player!!).start() - setQuestStage(player!!, FightArena.FightArenaQuest, 88) + setQuestStage(player!!, Quests.FIGHT_ARENA, 88) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilADialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilADialogue.kt index 026f61151..e92454d6f 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilADialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilADialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import content.region.kandarin.ardougne.quest.arena.cutscenes.EscapeCutscene import core.api.* import core.game.dialogue.DialogueFile @@ -13,7 +13,7 @@ class JeremyServilADialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.JEREMY_SERVIL_265) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { 20 -> when (stage) { 0 -> { @@ -29,7 +29,7 @@ class JeremyServilADialogue : DialogueFile() { 4 -> playerl(FacialExpression.FRIENDLY, "Don't lose heart, I'll be back.").also { stage++ } 5 -> { end() - setQuestStage(player!!, FightArena.FightArenaQuest, 40) + setQuestStage(player!!, Quests.FIGHT_ARENA, 40) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilBDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilBDialogue.kt index 7e4260779..7f87687c2 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilBDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JeremyServilBDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -12,7 +12,7 @@ class JeremyServilBDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.JEREMY_SERVIL_266) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 1..84 -> when (stage) { 0 -> { @@ -31,7 +31,7 @@ class JeremyServilBDialogue : DialogueFile() { 1 -> npcl(FacialExpression.FRIENDLY, "Thank you, we are truly indebted to you.").also { stage++ } 2 -> { end() - setQuestStage(player!!, FightArena.FightArenaQuest, 99) + setQuestStage(player!!, Quests.FIGHT_ARENA, 99) } } @@ -47,7 +47,7 @@ class JeremyServilBDialogue : DialogueFile() { } 2 -> { end() - setQuestStage(player!!, FightArena.FightArenaQuest, 99) + setQuestStage(player!!, Quests.FIGHT_ARENA, 99) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JustinServilDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JustinServilDialogue.kt index a761d2b1e..3244d30f0 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JustinServilDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/JustinServilDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import core.api.face import core.api.findNPC import core.api.getQuestStage @@ -14,7 +14,7 @@ import org.rs09.consts.NPCs class JustinServilDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.JUSTIN_SERVIL_267) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 1..68 -> when (stage) { 0 -> playerl(FacialExpression.FRIENDLY, "Hello.").also { stage++ } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/KhazardBarmanDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/KhazardBarmanDialogue.kt index d10c13e6a..48ff869ac 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/KhazardBarmanDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/KhazardBarmanDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena +import content.data.Quests import core.api.addItem import core.api.getQuestStage import core.api.removeItem @@ -17,7 +17,7 @@ import org.rs09.consts.NPCs class KhazardBarmanDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { npc = NPC(NPCs.KHAZARD_BARMAN_259) - when (getQuestStage(player!!, FightArena.FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { in 0..49 -> { when (stage) { 0 -> playerl(FacialExpression.HAPPY, "Hello. I'll have a beer please.").also { stage = 1 } @@ -58,7 +58,7 @@ class KhazardBarmanDialogue : DialogueFile() { 9 -> if (removeItem(player!!, Item(COINS_995, 5))){ end() addItem(player!!, Items.KHALI_BREW_77, 1) - setQuestStage(player!!, FightArena.FightArenaQuest, 60) + setQuestStage(player!!, Quests.FIGHT_ARENA, 60) stage = END_DIALOGUE } else { end() diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LadyServilDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LadyServilDialogue.kt index afaadc7fe..fc30c1ca1 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LadyServilDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LadyServilDialogue.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.quest.arena.dialogue -import content.region.kandarin.ardougne.quest.arena.FightArena.Companion.FightArenaQuest import core.api.getQuestStage import core.api.setQuestStage import core.game.dialogue.DialoguePlugin @@ -10,17 +9,18 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class LadyServilDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC playerl(FacialExpression.FRIENDLY, "Hi there, looks like you're in some trouble.") - if (player.questRepository.getStage("Fight Arena") == 10) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 10) { playerl(FacialExpression.FRIENDLY, "Hello Lady Servil.") - } else if (player.questRepository.getStage("Fight Arena") == 30) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 30) { playerl(FacialExpression.FRIENDLY, "Lady Servil, I have managed to infiltrate General Khazard's arena.") - } else if (player.questRepository.getStage("Fight Arena") == 70) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 70) { playerl(FacialExpression.FRIENDLY, "Lady Servil. I freed your son, however he has returned to the arena to help your husband.").also { stage++ } } else { playerl(FacialExpression.FRIENDLY, "Hello Lady Servil.") @@ -29,7 +29,7 @@ class LadyServilDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, FightArenaQuest)) { + when (getQuestStage(player!!, Quests.FIGHT_ARENA)) { 0 -> when (stage) { 0 -> npcl(FacialExpression.SAD, "Oh I wish this broken cart was my only problem. *sob* I've got to find my family.. **sob**").also { stage++ } @@ -46,7 +46,7 @@ class LadyServilDialogue(player: Player? = null) : DialoguePlugin(player) { 8 -> playerl(FacialExpression.FRIENDLY, "I'll try my best to return your family.").also { stage++ } 9 -> { end() - setQuestStage(player!!, FightArenaQuest, 10) + setQuestStage(player!!, Quests.FIGHT_ARENA, 10) npcl(FacialExpression.SAD, "Please do. My family is wealthy and can reward you handsomely. I'll be waiting here for you.").also { stage = END_DIALOGUE } } } @@ -81,7 +81,7 @@ class LadyServilDialogue(player: Player? = null) : DialoguePlugin(player) { 2 -> npcl(FacialExpression.FRIENDLY, "All I can offer in return is material wealth. Please take these coins as a sign of my gratitude.").also { stage++ } 3 -> { end() - player!!.questRepository.getQuest("Fight Arena").finish(player) + player!!.questRepository.getQuest(Quests.FIGHT_ARENA).finish(player) } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LocalDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LocalDialogue.kt index d43e5589a..84382f980 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LocalDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/dialogue/LocalDialogue.kt @@ -7,16 +7,17 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class LocalDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (player.questRepository.getStage("Fight Arena") == 100) { + if (player.questRepository.getStage(Quests.FIGHT_ARENA) == 100) { npcl(FacialExpression.FRIENDLY, "Hey, you're the guy from the arena! How'd you get out?").also { stage = END_DIALOGUE } - } else if (player.questRepository.getStage("Fight Arena") in 91..99) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) in 91..99) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 9 } - } else if (player.questRepository.getStage("Fight Arena") >= 10) { + } else if (player.questRepository.getStage(Quests.FIGHT_ARENA) >= 10) { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 0 } } else { playerl(FacialExpression.FRIENDLY, "Hello.").also { stage = 7 } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/BouncerNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/BouncerNPC.kt index f61475d19..f79aefcb1 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/BouncerNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/BouncerNPC.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.quest.arena.npc -import content.region.kandarin.ardougne.quest.arena.FightArena import content.region.kandarin.ardougne.quest.arena.dialogue.GeneralKhazardDialogue import core.api.* import core.game.node.entity.Entity @@ -11,6 +10,7 @@ import core.game.world.GameWorld import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class BouncerNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) { @@ -52,9 +52,8 @@ class BouncerNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, loca override fun finalizeDeath(killer: Entity?) { if (killer is Player) { - val quest = "Fight Arena" - if (getQuestStage(killer, quest) >= 89) { - setQuestStage(killer, FightArena.FightArenaQuest, 91) + if (getQuestStage(killer, Quests.FIGHT_ARENA) >= 89) { + setQuestStage(killer, Quests.FIGHT_ARENA, 91) } removeAttribute(killer, "spawn-bouncer") openDialogue(killer, GeneralKhazardDialogue()) diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/GeneralNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/GeneralNPC.kt index 20e75588a..700876e14 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/GeneralNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/GeneralNPC.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.quest.arena.npc -import content.region.kandarin.ardougne.quest.arena.FightArena import content.region.kandarin.ardougne.quest.arena.FightArenaListeners.Companion.General import content.region.kandarin.ardougne.quest.arena.dialogue.JeremyServilBDialogue import core.api.openDialogue @@ -12,6 +11,7 @@ import core.game.node.entity.player.Player import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class GeneralNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) { @@ -31,9 +31,8 @@ class GeneralNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, loca override fun finalizeDeath(killer: Entity?) { if (killer is Player) { - val quest = "Fight Arena" - if (getQuestStage(killer, quest) == 97) { - setQuestStage(killer, FightArena.FightArenaQuest, 98) + if (getQuestStage(killer, Quests.FIGHT_ARENA) == 97) { + setQuestStage(killer, Quests.FIGHT_ARENA, 98) } openDialogue(killer, JeremyServilBDialogue()) } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/OgreNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/OgreNPC.kt index 51010d3e4..67e2ae7fd 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/OgreNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/OgreNPC.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.quest.arena.npc -import content.region.kandarin.ardougne.quest.arena.FightArena import content.region.kandarin.ardougne.quest.arena.dialogue.GeneralKhazardDialogue import core.api.* import core.game.node.entity.Entity @@ -11,6 +10,7 @@ import core.game.world.GameWorld import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class OgreNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) { @@ -53,9 +53,8 @@ class OgreNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, locatio override fun finalizeDeath(killer: Entity?) { if (killer is Player) { - val quest = "Fight Arena" - if (getQuestStage(killer, quest) == 68 || getQuestStage(killer, quest) == 88) { - setQuestStage(killer, FightArena.FightArenaQuest, 72) + if (getQuestStage(killer, Quests.FIGHT_ARENA) == 68 || getQuestStage(killer, Quests.FIGHT_ARENA) == 88) { + setQuestStage(killer, Quests.FIGHT_ARENA, 72) } clearHintIcon(killer) removeAttribute(killer, "spawn-ogre") diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/ScorpionNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/ScorpionNPC.kt index 17910e77b..164464901 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/ScorpionNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/arena/npc/ScorpionNPC.kt @@ -1,6 +1,5 @@ package content.region.kandarin.ardougne.quest.arena.npc -import content.region.kandarin.ardougne.quest.arena.FightArena import content.region.kandarin.ardougne.quest.arena.dialogue.GeneralKhazardDialogue import core.api.* import core.game.node.entity.Entity @@ -11,6 +10,7 @@ import core.game.world.GameWorld import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class ScorpionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) { @@ -52,9 +52,8 @@ class ScorpionNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, loc override fun finalizeDeath(killer: Entity?) { if (killer is Player) { - val quest = "Fight Arena" - if (getQuestStage(killer, quest) == 88) { - setQuestStage(killer, FightArena.FightArenaQuest, 89) + if (getQuestStage(killer, Quests.FIGHT_ARENA) == 88) { + setQuestStage(killer, Quests.FIGHT_ARENA, 89) } removeAttribute(killer, "spawn-scorpion") openDialogue(killer, GeneralKhazardDialogue()) diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/BrotherKojoDialogueFile.kt b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/BrotherKojoDialogueFile.kt index 5d4a0dba2..c06a15558 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/BrotherKojoDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/BrotherKojoDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.kandarin.ardougne.quest.clocktower +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -22,7 +23,7 @@ class BrotherKojoDialogueFile : DialogueFile() { } return } - when (getQuestStage(player!!, ClockTower.questName)) { + when (getQuestStage(player!!, Quests.CLOCK_TOWER)) { 0 -> { when (stage) { START_DIALOGUE -> player(FacialExpression.FRIENDLY, "Hello monk.").also { stage++ } @@ -49,7 +50,7 @@ class BrotherKojoDialogueFile : DialogueFile() { 32 -> player(FacialExpression.FRIENDLY, "Well, I'll do my best.").also { stage++ } 33 -> npcl(FacialExpression.HAPPY, "Thank you again! And remember to be careful, the cellar is full of strange beasts!").also { stage = END_DIALOGUE - setQuestStage(player!!, ClockTower.questName, 1) + setQuestStage(player!!, Quests.CLOCK_TOWER, 1) } } } @@ -93,7 +94,7 @@ class BrotherKojoDialogueFile : DialogueFile() { 2 -> npcl(FacialExpression.FRIENDLY, "The townsfolk will all be able to know the correct time now! Thank you so much for all of your help! And as promised, here is your reward!").also { stage++ } 3 -> { end() - finishQuest(player!!, ClockTower.questName) + finishQuest(player!!, Quests.CLOCK_TOWER) } } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTower.kt b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTower.kt index f5e284234..2be89b1be 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTower.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTower.kt @@ -6,14 +6,14 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * https://www.youtube.com/watch?v=Cl68Z0bsRq4 */ @Initializable -class ClockTower : Quest("Clock Tower",38, 37, 1, 10, 0, 1, 8) { +class ClockTower : Quest(Quests.CLOCK_TOWER,38, 37, 1, 10, 0, 1, 8) { companion object { - const val questName = "Clock Tower" const val attributeBlueCog = "/save:quest:clocktower-bluecogplaced" const val attributeBlackCog = "/save:quest:clocktower-blackcogplaced" const val attributeWhiteCog = "/save:quest:clocktower-whitecogplaced" diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTowerListeners.kt b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTowerListeners.kt index 1daa7e3ed..a769bac13 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTowerListeners.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/clocktower/ClockTowerListeners.kt @@ -1,5 +1,6 @@ package content.region.kandarin.ardougne.quest.clocktower +import content.data.Quests import core.api.* import core.game.global.action.DoorActionHandler import core.game.interaction.IntType @@ -47,8 +48,12 @@ class ClockTowerListener : InteractionListener { if (removeItem(player, Items.WHITE_COG_20)) { sendMessage(player, "The cog fits perfectly.") setAttribute(player, ClockTower.attributeWhiteCog, true) - if (!isQuestComplete(player, ClockTower.questName)) { - setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1) + if (!isQuestComplete(player, Quests.CLOCK_TOWER)) { + setQuestStage( + player, + Quests.CLOCK_TOWER, + getQuestStage(player, Quests.CLOCK_TOWER) + 1 + ) } } } else { @@ -62,8 +67,12 @@ class ClockTowerListener : InteractionListener { if (removeItem(player, Items.BLACK_COG_21)) { sendMessage(player, "The cog fits perfectly.") setAttribute(player, ClockTower.attributeBlackCog, true) - if (!isQuestComplete(player, ClockTower.questName)) { - setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1) + if (!isQuestComplete(player, Quests.CLOCK_TOWER)) { + setQuestStage( + player, + Quests.CLOCK_TOWER, + getQuestStage(player, Quests.CLOCK_TOWER) + 1 + ) } } } else { @@ -77,8 +86,12 @@ class ClockTowerListener : InteractionListener { if (removeItem(player, Items.BLUE_COG_22)) { sendMessage(player, "The cog fits perfectly.") setAttribute(player, ClockTower.attributeBlueCog, true) - if (!isQuestComplete(player, ClockTower.questName)) { - setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1) + if (!isQuestComplete(player, Quests.CLOCK_TOWER)) { + setQuestStage( + player, + Quests.CLOCK_TOWER, + getQuestStage(player, Quests.CLOCK_TOWER) + 1 + ) } } } else { @@ -92,8 +105,12 @@ class ClockTowerListener : InteractionListener { if (removeItem(player, Items.RED_COG_23)) { sendMessage(player, "The cog fits perfectly.") setAttribute(player, ClockTower.attributeRedCog, true) - if (!isQuestComplete(player, ClockTower.questName)) { - setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1) + if (!isQuestComplete(player, Quests.CLOCK_TOWER)) { + setQuestStage( + player, + Quests.CLOCK_TOWER, + getQuestStage(player, Quests.CLOCK_TOWER) + 1 + ) } } } else { diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherCedricNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherCedricNPC.kt index 3ae7c7dc4..64d4a7fa9 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherCedricNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherCedricNPC.kt @@ -11,6 +11,7 @@ import core.game.dialogue.DialogueFile import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.tools.END_DIALOGUE +import content.data.Quests /** * Handles BrotherCedricDialogue Dialogue @@ -18,8 +19,7 @@ import core.tools.END_DIALOGUE */ class BrotherCedricDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - val questName = "Monk's Friend" - val questStage = getQuestStage(player!!, questName) + val questStage = getQuestStage(player!!, Quests.MONKS_FRIEND) when { questStage < 30 -> { when(stage) { @@ -36,7 +36,7 @@ class BrotherCedricDialogue : DialogueFile() { 0 -> playerl(core.game.dialogue.FacialExpression.HAPPY, "Brother Cedric are you okay?").also{stage++} 1 -> npcl(core.game.dialogue.FacialExpression.DRUNK, "Yeesshhh, I'm very, very drunk..hic..up..").also{stage++} 2 -> playerl(core.game.dialogue.FacialExpression.NEUTRAL, "Brother Omad needs the wine for the party.").also{stage++} - 3 -> npcl(core.game.dialogue.FacialExpression.SAD, "Oh dear, oh dear, I knew I had to do something!").also{stage = END_DIALOGUE }.also{ setQuestStage(player!!, questName, 40) } + 3 -> npcl(core.game.dialogue.FacialExpression.SAD, "Oh dear, oh dear, I knew I had to do something!").also{stage = END_DIALOGUE }.also{ setQuestStage(player!!, Quests.MONKS_FRIEND, 40) } } } questStage == 40 -> { @@ -54,7 +54,7 @@ class BrotherCedricDialogue : DialogueFile() { sendItemDialogue(player!!, Items.JUG_OF_WATER_1937, "You hand the monk a jug of water.") stage=0 player!!.inventory.remove(Item(Items.JUG_OF_WATER_1937)) - setQuestStage(player!!, questName, 41) + setQuestStage(player!!, Quests.MONKS_FRIEND, 41) } } } @@ -72,7 +72,7 @@ class BrotherCedricDialogue : DialogueFile() { } 5 -> npcl(core.game.dialogue.FacialExpression.HAPPY, "In that case I'd better drink more wine! It helps me think.").also {stage= END_DIALOGUE } 10 -> npcl(core.game.dialogue.FacialExpression.HAPPY, "Excellent, I just need some wood.").also{stage++} - 11 -> playerl(core.game.dialogue.FacialExpression.NEUTRAL, "Ok, I'll see what I can find.").also{stage = END_DIALOGUE }.also{setQuestStage(player!!, questName, 42)} + 11 -> playerl(core.game.dialogue.FacialExpression.NEUTRAL, "Ok, I'll see what I can find.").also{stage = END_DIALOGUE }.also{setQuestStage(player!!, Quests.MONKS_FRIEND, 42)} } } questStage == 42 -> { @@ -89,7 +89,7 @@ class BrotherCedricDialogue : DialogueFile() { 4 -> playerl(core.game.dialogue.FacialExpression.HAPPY, "Ok! I'll see you later!").also{ stage= END_DIALOGUE player!!.inventory.remove(Item(Items.LOGS_1511)) - setQuestStage(player!!, questName, 50) + setQuestStage(player!!, Quests.MONKS_FRIEND, 50) } } } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherOmadNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherOmadNPC.kt index 74b322344..bea3883cc 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherOmadNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/BrotherOmadNPC.kt @@ -14,6 +14,7 @@ import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.game.world.GameWorld.Pulser import core.tools.END_DIALOGUE +import content.data.Quests /** @@ -22,8 +23,7 @@ import core.tools.END_DIALOGUE */ class BrotherOmadDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - val questName = "Monk's Friend" - val questStage = getQuestStage(player!!, questName) + val questStage = getQuestStage(player!!, Quests.MONKS_FRIEND) when (questStage) { 0 -> { when(stage) { @@ -50,7 +50,7 @@ class BrotherOmadDialogue : DialogueFile() { } 10 -> npcl(core.game.dialogue.FacialExpression.HALF_WORRIED, "Please do. We won't be able to help you as we are peaceful men but we would be grateful for your help!").also { stage++ } 11 -> playerl(core.game.dialogue.FacialExpression.HALF_ASKING, "Where are they?").also { stage++ } - 12 -> npcl(core.game.dialogue.FacialExpression.SAD, "They hide in a secret cave in the forest. It's hidden under a ring of stones. Please, bring back the blanket!").also { stage = END_DIALOGUE }.also { player!!.questRepository.getQuest("Monk's Friend").start(player) }.also { player!!.questRepository.syncronizeTab(player) } + 12 -> npcl(core.game.dialogue.FacialExpression.SAD, "They hide in a secret cave in the forest. It's hidden under a ring of stones. Please, bring back the blanket!").also { stage = END_DIALOGUE }.also { player!!.questRepository.getQuest(Quests.MONKS_FRIEND).start(player) }.also { player!!.questRepository.syncronizeTab(player) } } } 10 -> { @@ -70,7 +70,7 @@ class BrotherOmadDialogue : DialogueFile() { } 31 -> npcl(core.game.dialogue.FacialExpression.HAPPY, "Really, that's excellent, well done! Maybe now I will be able to get some rest.").also{stage++} 32 -> npcl(core.game.dialogue.FacialExpression.SAD, "*yawn*..I'm off to bed! Farewell brave traveller!").also{player!!.inventory.remove(Item(Items.CHILDS_BLANKET_90)) - setQuestStage(player!!, questName, 20); stage = END_DIALOGUE + setQuestStage(player!!, Quests.MONKS_FRIEND, 20); stage = END_DIALOGUE } } } @@ -105,7 +105,12 @@ class BrotherOmadDialogue : DialogueFile() { 996 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Okay traveller, take care.").also{stage = END_DIALOGUE } 997 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Of course, but we need the wine first.").also{stage = END_DIALOGUE } 42 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Oh, he won't be far. Probably out in the forest.").also{stage++} - 43 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Ok, I'll go and find him.").also { stage = END_DIALOGUE }.also{ setQuestStage(player!!, questName, 30)} + 43 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Ok, I'll go and find him.").also { stage = END_DIALOGUE }.also{ + setQuestStage( + player!!, + Quests.MONKS_FRIEND, + 30 + )} } } 30 -> { @@ -192,7 +197,7 @@ class BrotherOmadDialogue : DialogueFile() { monk.animator.animate(Animation(2109)) // Jump for joy } 25 -> if (questComplete) { - player!!.questRepository.getQuest("Monk's Friend").finish(player) + player!!.questRepository.getQuest(Quests.MONKS_FRIEND).finish(player) } } count++ diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonasteryMonkNPC.kt b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonasteryMonkNPC.kt index 8279ba5ce..cfe48d058 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonasteryMonkNPC.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonasteryMonkNPC.kt @@ -6,6 +6,7 @@ import core.game.dialogue.DialogueFile import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.tools.END_DIALOGUE +import content.data.Quests /** * Handles MonasteryMonkDialogue Dialogue @@ -13,7 +14,7 @@ import core.tools.END_DIALOGUE */ class MonasteryMonkDialogue : DialogueFile() { override fun handle(interfaceId: Int, buttonId: Int) { - var questStage = player!!.questRepository.getStage("Monk's Friend") + var questStage = player!!.questRepository.getStage(Quests.MONKS_FRIEND) if (questStage == 0){ when(stage) { 0 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL,"Peace brother.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonksFriend.kt b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonksFriend.kt index cf38a3a18..c559c6a85 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonksFriend.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/monksfriend/MonksFriend.kt @@ -8,6 +8,7 @@ import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Represents the "Monk's Friend" quest. @@ -15,7 +16,7 @@ import org.rs09.consts.Items */ @Initializable -class MonksFriend: Quest("Monk's Friend", 89, 88, 1, 30, 0, 1, 80) { +class MonksFriend: Quest(Quests.MONKS_FRIEND, 89, 88, 1, 30, 0, 1, 80) { override fun newInstance(`object`: Any?): Quest { return this diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/HalgriveDialogue.java b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/HalgriveDialogue.java index a7b3ccf2c..4f3dee3c2 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/HalgriveDialogue.java +++ b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/HalgriveDialogue.java @@ -5,6 +5,7 @@ import core.plugin.Initializable; import core.game.dialogue.DialoguePlugin; import core.api.*; import org.rs09.consts.Items; +import content.data.Quests; @Initializable public class HalgriveDialogue extends DialoguePlugin { @@ -21,7 +22,7 @@ public class HalgriveDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - if(player.getQuestRepository().getStage("Sheep Herder") < 10) { + if(player.getQuestRepository().getStage(Quests.SHEEP_HERDER) < 10) { player("Hello. How are you?"); stage = 0; return true; @@ -116,7 +117,7 @@ public class HalgriveDialogue extends DialoguePlugin { stage++; break; case 105: - player.getQuestRepository().getQuest("Sheep Herder").start(player); + player.getQuestRepository().getQuest(Quests.SHEEP_HERDER).start(player); player.getDialogueInterpreter().sendDialogue("The councillor gives you some poisoned sheep feed."); player.getInventory().add(SheepHerder.POISON); stage++; @@ -168,7 +169,7 @@ public class HalgriveDialogue extends DialoguePlugin { stage++; break; case 207: - player.getQuestRepository().getQuest("Sheep Herder").finish(player); + player.getQuestRepository().getQuest(Quests.SHEEP_HERDER).finish(player); end(); break; } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/OrbonDialogue.java b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/OrbonDialogue.java index ec371b44a..55efedcf1 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/OrbonDialogue.java +++ b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/OrbonDialogue.java @@ -5,6 +5,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.dialogue.DialoguePlugin; +import content.data.Quests; @Initializable public class OrbonDialogue extends DialoguePlugin { @@ -21,7 +22,7 @@ public class OrbonDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - if(player.getQuestRepository().getStage("Sheep Herder") == 10){ + if(player.getQuestRepository().getStage(Quests.SHEEP_HERDER) == 10){ player("Hello doctor. I need to acquire some protective clothing","so that I can dispose of some escaped sheep infected","with the plague."); stage = 100; return true; diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java index 9562c3a4f..75ed87dbf 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java +++ b/Server/src/main/content/region/kandarin/ardougne/quest/sheepherder/SheepHerder.java @@ -10,6 +10,7 @@ import core.plugin.Initializable; import org.rs09.consts.Items; import java.util.HashMap; +import content.data.Quests; @Initializable public class SheepHerder extends Quest { @@ -35,7 +36,7 @@ public class SheepHerder extends Quest { boneMap.put(BLUE_SHEEP,BLUE_SHEEP_BONES); } - public SheepHerder(){super("Sheep Herder",113,112,4,60,0,1,3);} + public SheepHerder(){super(Quests.SHEEP_HERDER,113,112,4,60,0,1,3);} @Override public void drawJournal(Player player, int stage) { diff --git a/Server/src/main/content/region/kandarin/catherby/dialogue/ArheinDialogue.kt b/Server/src/main/content/region/kandarin/catherby/dialogue/ArheinDialogue.kt index ed8427af0..3300e43d5 100644 --- a/Server/src/main/content/region/kandarin/catherby/dialogue/ArheinDialogue.kt +++ b/Server/src/main/content/region/kandarin/catherby/dialogue/ArheinDialogue.kt @@ -11,6 +11,7 @@ import core.game.dialogue.Topic import core.tools.END_DIALOGUE import org.rs09.consts.Items import content.region.kandarin.seers.quest.merlinsquest.ArheinMCDialogue +import content.data.Quests /** @@ -113,7 +114,7 @@ class ArheinDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin 140 -> npcl(core.game.dialogue.FacialExpression.GUILTY,"Sorry pal, but I'm afraid I'm not quite ready to sail yet.").also { stage++ } 141 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL,"I'm waiting on a big delivery of candles which I need to deliver further along the coast.").also { stage = END_DIALOGUE } 500 -> npcl(core.game.dialogue.FacialExpression.HALF_THINKING, "Yes, I do have orders to deliver there from time to time. I think I may have some bits and pieces for them when I leave here next actually.").also { - val queststage = player.questRepository.getStage("Merlin's Crystal") + val queststage = player.questRepository.getStage(Quests.MERLINS_CRYSTAL) if(queststage == 30 || queststage == 40) { loadFile(ArheinMCDialogue(queststage)) } else { diff --git a/Server/src/main/content/region/kandarin/dialogue/ThormacDialogue.kt b/Server/src/main/content/region/kandarin/dialogue/ThormacDialogue.kt index 8593baf51..f21493f59 100644 --- a/Server/src/main/content/region/kandarin/dialogue/ThormacDialogue.kt +++ b/Server/src/main/content/region/kandarin/dialogue/ThormacDialogue.kt @@ -11,6 +11,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable class ThormacDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -25,11 +26,11 @@ class ThormacDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (isQuestComplete(player, "Scorpion Catcher")){ + if (isQuestComplete(player, Quests.SCORPION_CATCHER)){ npc(FacialExpression.HAPPY, "Thank you for rescuing my scorpions.").also {stage = COMPLETED_QUEST} } else{ - openDialogue(player, SCThormacDialogue(getQuestStage(player, "Scorpion Catcher")), npc) + openDialogue(player, SCThormacDialogue(getQuestStage(player, Quests.SCORPION_CATCHER)), npc) } return true } diff --git a/Server/src/main/content/region/kandarin/feldip/ooglog/dialogue/BalneaDialogue.kt b/Server/src/main/content/region/kandarin/feldip/ooglog/dialogue/BalneaDialogue.kt index 34b967093..2df29fe88 100644 --- a/Server/src/main/content/region/kandarin/feldip/ooglog/dialogue/BalneaDialogue.kt +++ b/Server/src/main/content/region/kandarin/feldip/ooglog/dialogue/BalneaDialogue.kt @@ -10,7 +10,7 @@ import core.tools.START_DIALOGUE /** * Provides dialogue tree for Balnea NPC involved in the - * "As a first resort..." quest. + * "As a First Resort..." quest. * * @author vddCore */ @@ -44,7 +44,7 @@ class BalneaDialogue(player: Player? = null) : DialoguePlugin(player) { ).also { stage = END_DIALOGUE } } - /* TODO: "As a First Resort..." quest dialogue file is required here. */ + /* TODO: "As a First Resort" quest dialogue file is required here. */ return true } diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt index 2865888b4..49a074680 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt @@ -17,6 +17,7 @@ import core.game.world.map.zone.ZoneBorders import core.game.world.map.RegionManager import core.game.world.map.Location import core.tools.RandomFunction +import content.data.Quests @Initializable class BloatedToadNPC : AbstractNPC { @@ -122,7 +123,7 @@ class BloatedToadListeners : InteractionListener, StartupListener, Commands { override fun defineListeners() { on(Items.BLOATED_TOAD_2875, IntType.ITEM, "drop") { player, used -> - val quest = player.questRepository.getQuest("Big Chompy Bird Hunting") + val quest = player.questRepository.getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING) val inExtraBorder = extraBorders.filter { it.insideBorder(player) }.count() > 0 if (!borders.insideBorder(player) && !inExtraBorder) { diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt index 63df68706..73e8940d1 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt @@ -24,9 +24,10 @@ import core.game.world.GameWorld import kotlin.math.min import java.util.Random +import content.data.Quests @Initializable -class ChompyBird : Quest("Big Chompy Bird Hunting", 35, 34, 2, Vars.VARP_QUEST_CHOMPY, 0, 1, 65), InteractionListener { +class ChompyBird : Quest(Quests.BIG_CHOMPY_BIRD_HUNTING, 35, 34, 2, Vars.VARP_QUEST_CHOMPY, 0, 1, 65), InteractionListener { companion object { val CAVE_ENTRANCE = Location.create(2646, 9378, 0) val CAVE_EXIT = Location.create(2630, 2997, 0) diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdDialogues.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdDialogues.kt index be7387f17..054159fd3 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdDialogues.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdDialogues.kt @@ -18,6 +18,7 @@ import core.game.node.item.Item import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest +import content.data.Quests @Initializable class RantzDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -32,7 +33,7 @@ class RantzDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?) : Boolean { npc = args[0] as NPC - val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting") + val chompyBird = player.questRepository.getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING) val chompyStage = chompyBird.getStage(player) val hasOgreBow = inInventory(player, Items.OGRE_BOW_2883) || inEquipment(player, Items.OGRE_BOW_2883) || inBank(player, Items.OGRE_BOW_2883) @@ -142,7 +143,7 @@ class BugsDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?) : Boolean { npc = args[0] as NPC - val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting") + val chompyBird = player.questRepository.getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING) val chompyStage = chompyBird.getStage(player) when (chompyStage) { @@ -172,7 +173,7 @@ class FycieDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?) : Boolean { npc = args[0] as NPC - val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting") + val chompyBird = player.questRepository.getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING) val chompyStage = chompyBird.getStage(player) when (chompyStage) { diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/RantzNPC.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/RantzNPC.kt index 94173377d..f0f1ca4ff 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/RantzNPC.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/RantzNPC.kt @@ -8,6 +8,7 @@ import core.plugin.Initializable import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player import core.game.world.map.Location +import content.data.Quests @Initializable class RantzNPC : AbstractNPC { @@ -27,7 +28,7 @@ class RantzNPC : AbstractNPC { val chompy = findLocalNPC(this, NPCs.CHOMPY_BIRD_1550) as? ChompyBirdNPC ?: return val owner = getAttribute(chompy, "owner", null) ?: return - val quest = owner.questRepository.getQuest("Big Chompy Bird Hunting") + val quest = owner.questRepository.getQuest(Quests.BIG_CHOMPY_BIRD_HUNTING) if (quest.getStage(owner) !in 40..50 || chompy.getAttribute("attacked", false)) return diff --git a/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java b/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java index 7cec187ec..18e653c14 100644 --- a/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java +++ b/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java @@ -17,6 +17,7 @@ import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; import content.global.travel.EssenceTeleport; +import content.data.Quests; /** * Represents the wizard guild plugin. @@ -74,7 +75,7 @@ public final class WizardGuildPlugin extends OptionHandler { } break; case "teleport": - if (!player.getQuestRepository().isComplete("Rune Mysteries")) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES)) { player.getPacketDispatch().sendMessage("You need to have completed the Rune Mysteries Quest to use this feature."); return true; } @@ -133,7 +134,7 @@ public final class WizardGuildPlugin extends OptionHandler { stage = 2; break; case 2: - if (!player.getQuestRepository().isComplete("Rune Mysteries")) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES)) { player("Nothing thanks, I'm just looking around."); stage = 4; return true; diff --git a/Server/src/main/content/region/kandarin/pisc/handlers/SeaweedNetHandler.kt b/Server/src/main/content/region/kandarin/pisc/handlers/SeaweedNetHandler.kt index b33c40068..4ae4df149 100644 --- a/Server/src/main/content/region/kandarin/pisc/handlers/SeaweedNetHandler.kt +++ b/Server/src/main/content/region/kandarin/pisc/handlers/SeaweedNetHandler.kt @@ -9,12 +9,13 @@ import org.rs09.consts.Animations import org.rs09.consts.Items import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests class SeaweedNetHandler : InteractionListener { override fun defineListeners() { on(NET, IntType.SCENERY, "Take-from"){ player, node -> - if (!isQuestComplete(player, "Swan Song")) + if (!isQuestComplete(player, Quests.SWAN_SONG)) { sendMessage(player, "You must complete Swan Song first.") } diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/CaptainLawgofDialogue.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/CaptainLawgofDialogue.java index a43f229ad..ae586a3f3 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/CaptainLawgofDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/CaptainLawgofDialogue.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.dwarfcannon; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -44,7 +45,7 @@ public class CaptainLawgofDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(DwarfCannon.NAME); + quest = player.getQuestRepository().getQuest(Quests.DWARF_CANNON); switch (quest.getStage(player)) { case 80: player("Hi."); diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannon.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannon.java index 37af05ec3..8268ced31 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannon.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannon.java @@ -8,6 +8,7 @@ import core.plugin.ClassScanner; import core.game.node.entity.skill.Skills; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the dwarf cannon quest. @@ -15,12 +16,6 @@ import static core.api.ContentAPIKt.*; */ @Initializable public class DwarfCannon extends Quest { - - /** - * The name of this quest. - */ - public static final String NAME = "Dwarf Cannon"; - /** * The dwarf remain item. */ @@ -40,13 +35,13 @@ public class DwarfCannon extends Quest { * The mould item. */ public static final Item MOULD = new Item(4); - public static int[] railVarbits = new int[] { 2240, 2241, 2242, 2243, 2244, 2245 }; + public static int[] railVarbits = new int[] { 2240, 2241, 2242, 2243, 2244, 2245 }; /** * Constructs a new {@Code DwarfCannon} {@Code Object} */ public DwarfCannon() { - super(NAME, 49, 48, 1); + super(Quests.DWARF_CANNON, 49, 48, 1); } @Override diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannonPlugin.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannonPlugin.java index 7739d88cf..309895c76 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannonPlugin.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/DwarfCannonPlugin.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.dwarfcannon; +import content.data.Quests; import core.cache.def.impl.SceneryDefinition; import core.game.component.Component; import core.game.component.ComponentDefinition; @@ -17,7 +18,6 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.tools.Log; -import core.tools.SystemLogger; import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; @@ -61,14 +61,14 @@ public class DwarfCannonPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(DwarfCannon.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.DWARF_CANNON); if (quest.getStage(player) > 50) { player.getDialogueInterpreter().sendDialogues(player, null, "This should work nicely now that I've fixed it."); return true; } //setVarp(player, 1, 2041, true); setVarp(player, 0, 8, true); - player.getQuestRepository().getQuest(DwarfCannon.NAME).setStage(player, 60); + player.getQuestRepository().getQuest(Quests.DWARF_CANNON).setStage(player, 60); player.sendMessage("Well done! You've fixed the cannon! Better go and tell Captain Lawgof."); /* * Component component = new Component(409); @@ -85,7 +85,7 @@ public class DwarfCannonPlugin extends OptionHandler { @Override public boolean handle(final Player player, final Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(DwarfCannon.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.DWARF_CANNON); switch (node.getId()) { case 3: if (!node.getLocation().equals(new Location(3015, 3453, 0))) { @@ -309,7 +309,7 @@ public class DwarfCannonPlugin extends OptionHandler { //setVarp(player, 1, 2041, true); //setVarp(player, 0, 8, true); - player.getQuestRepository().getQuest(DwarfCannon.NAME).setStage(player, 60); + player.getQuestRepository().getQuest(Quests.DWARF_CANNON).setStage(player, 60); player.sendMessage("Well done! You've fixed the cannon! Better go and tell Captain Lawgof."); GameWorld.getPulser().submit(new Pulse(5, player) { @Override diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/LollkDialogue.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/LollkDialogue.java index 11cc1886d..08cedded9 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/LollkDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/LollkDialogue.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.dwarfcannon; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -41,7 +42,7 @@ public class LollkDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(DwarfCannon.NAME); + quest = player.getQuestRepository().getQuest(Quests.DWARF_CANNON); switch (quest.getStage(player)) { case 40: npc("Thank the heavens, you saved me!", "I thought I'd be goblin lunch for sure!"); diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/NulodionDialogue.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/NulodionDialogue.java index be7fa1847..05ac29b60 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/NulodionDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/NulodionDialogue.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.dwarfcannon; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -49,7 +50,7 @@ public class NulodionDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(DwarfCannon.NAME); + quest = player.getQuestRepository().getQuest(Quests.DWARF_CANNON); switch (quest.getStage(player)) { case 70: player("Hello there."); diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DwarfMultiCannonPlugin.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DwarfMultiCannonPlugin.java index 736bb57eb..0fbe40125 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DwarfMultiCannonPlugin.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DwarfMultiCannonPlugin.java @@ -12,6 +12,7 @@ import core.game.node.item.Item; import core.plugin.Plugin; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Handles the Dwarf multi-cannon. @@ -73,7 +74,7 @@ public final class DwarfMultiCannonPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("You don't have all the cannon components!"); return true; } - if (!player.getQuestRepository().isComplete("Dwarf Cannon") && player.getDetails().getRights() != Rights.ADMINISTRATOR) { + if (!player.getQuestRepository().isComplete(Quests.DWARF_CANNON) && player.getDetails().getRights() != Rights.ADMINISTRATOR) { player.getPacketDispatch().sendMessage("You have to complete the Dwarf Cannon to know how to use this."); return true; } diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/BonzoDialogue.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/BonzoDialogue.java index 9a62eb53b..8ed55ae9e 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/BonzoDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/BonzoDialogue.java @@ -6,6 +6,7 @@ import core.plugin.Initializable; import core.game.node.entity.player.Player; import core.game.activity.ActivityManager; import core.game.dialogue.DialoguePlugin; +import content.data.Quests; @Initializable @@ -126,7 +127,7 @@ public final class BonzoDialogue extends DialoguePlugin { player.getDialogueInterpreter().sendDialogue("You are given the Hemenester fishing trophy!"); player.getInventory().add(FishingContest.FISHING_TROPHY); player.getInventory().remove(FishingContest.RAW_GIANT_CARP); - player.getQuestRepository().setStage(QuestRepository.getQuests().get("Fishing Contest"),20); + player.getQuestRepository().setStage(QuestRepository.getQuests().get(Quests.FISHING_CONTEST),20); stage = 100; break; } diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java index a48682faa..0fa32ac49 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java @@ -6,6 +6,7 @@ import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; +import content.data.Quests; @Initializable public class DwarfDialogue extends DialoguePlugin { @@ -22,7 +23,7 @@ public class DwarfDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - int questStage = player.getQuestRepository().getStage("Fishing Contest"); + int questStage = player.getQuestRepository().getStage(Quests.FISHING_CONTEST); if((questStage < 20 && questStage > 0) && !player.getInventory().containsItem(FishingContest.FISHING_PASS)){ player("I lost my fishing pass..."); stage = 1000; @@ -33,12 +34,12 @@ public class DwarfDialogue extends DialoguePlugin { stage = 2000; return true; } - if(player.getQuestRepository().getStage("Fishing Contest") >= 10 && !player.getAttribute("fishing_contest:won",false)){ + if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) >= 10 && !player.getAttribute("fishing_contest:won",false)){ npc(FacialExpression.OLD_NORMAL,"Have you won yet?"); stage = 1500; return true; } - if(player.getQuestRepository().getStage("Fishing Contest") == 100){ + if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) == 100){ npc(FacialExpression.OLD_NORMAL,"Welcome, oh great fishing champion!","Feel free to pop by and use","our tunnel any time!"); stage = 2500; return true; @@ -172,7 +173,7 @@ public class DwarfDialogue extends DialoguePlugin { if(!player.getInventory().add(FishingContest.FISHING_PASS)){ GroundItemManager.create(FishingContest.FISHING_PASS,player.getLocation()); } - player.getQuestRepository().getQuest("Fishing Contest").start(player); + player.getQuestRepository().getQuest(Quests.FISHING_CONTEST).start(player); stage++; break; case 58: @@ -220,7 +221,7 @@ public class DwarfDialogue extends DialoguePlugin { stage++; break; case 2004: - player.getQuestRepository().getQuest("Fishing Contest").finish(player); + player.getQuestRepository().getQuest(Quests.FISHING_CONTEST).finish(player); player.getInventory().remove(FishingContest.FISHING_TROPHY); end(); break; diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java index 1e87b8df7..f713482ae 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java @@ -5,10 +5,11 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.node.entity.skill.Skills; +import content.data.Quests; @Initializable public class FishingContest extends Quest { - public FishingContest(){super("Fishing Contest",62,61,1,11,0,1,5);} + public FishingContest(){super(Quests.FISHING_CONTEST,62,61,1,11,0,1,5);} public static final Item FISHING_ROD = new Item(307); public static final Item FISHING_PASS = new Item(27); public static final Item RED_VINE_WORM = new Item(25); diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/GarlicPipeInteraction.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/GarlicPipeInteraction.java index ec13a470a..5771f2dab 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/GarlicPipeInteraction.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/GarlicPipeInteraction.java @@ -13,6 +13,7 @@ import core.plugin.Plugin; import org.rs09.consts.Items; import core.game.interaction.PluginInteraction; import core.game.interaction.PluginInteractionManager; +import content.data.Quests; @Initializable public class GarlicPipeInteraction extends PluginInteraction { @@ -31,7 +32,7 @@ public class GarlicPipeInteraction extends PluginInteraction { Scenery usedWith = event.getUsedWith().asScenery(); Item used = event.getUsedItem(); - if(used.getId() == Items.GARLIC_1550 && usedWith.getId() == 41 && usedWith.getLocation().equals(Location.create(2638, 3446, 0)) && player.getQuestRepository().getStage("Fishing Contest") > 0){ + if(used.getId() == Items.GARLIC_1550 && usedWith.getId() == 41 && usedWith.getLocation().equals(Location.create(2638, 3446, 0)) && player.getQuestRepository().getStage(Quests.FISHING_CONTEST) > 0){ player.getPulseManager().run(new MovementPulse(player, usedWith.getLocation().transform(0, -1, 0)) { @Override public boolean pulse() { diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/GateInteraction.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/GateInteraction.java index 96829b11d..7a79ca976 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/GateInteraction.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/GateInteraction.java @@ -9,6 +9,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import core.game.interaction.PluginInteraction; import core.game.interaction.PluginInteractionManager; +import content.data.Quests; @Initializable public class GateInteraction extends PluginInteraction { @@ -27,11 +28,11 @@ public class GateInteraction extends PluginInteraction { } public boolean handleGate(Player player, Node node){ - if(!player.getAttribute("fishing_contest:pass-shown",false) || player.getQuestRepository().getStage("Fishing Contest") < 10) { + if(!player.getAttribute("fishing_contest:pass-shown",false) || player.getQuestRepository().getStage(Quests.FISHING_CONTEST) < 10) { player.getPulseManager().run(new MovementPulse(player, node.asScenery().getLocation().transform(1, 0, 0)) { @Override public boolean pulse() { - if(player.getQuestRepository().getStage("Fishing Contest") >= 10){ + if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) >= 10){ player.sendMessage("You should give your pass to Morris."); } else { player.sendMessage("You need a fishing pass to fish here."); diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/StairInteraction.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/StairInteraction.java index c4ca0001b..97daa72b1 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/StairInteraction.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/StairInteraction.java @@ -11,12 +11,13 @@ import core.plugin.Plugin; import core.game.interaction.PluginInteraction; import core.game.interaction.PluginInteractionManager; import core.game.world.repository.Repository; +import content.data.Quests; @Initializable public class StairInteraction extends PluginInteraction { @Override public boolean handle(Player player, Node node) { - if(!player.getQuestRepository().isComplete("Fishing Contest")) { + if(!player.getQuestRepository().isComplete(Quests.FISHING_CONTEST)) { Scenery object = node.asScenery(); switch (object.getId()) { case 57: diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/VineInteraction.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/VineInteraction.java index 50d7e4a53..17ceb597a 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/VineInteraction.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/VineInteraction.java @@ -10,6 +10,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import core.game.interaction.PluginInteraction; import core.game.interaction.PluginInteractionManager; +import content.data.Quests; @Initializable public class VineInteraction extends PluginInteraction { @@ -24,7 +25,7 @@ public class VineInteraction extends PluginInteraction { @Override public boolean handle(Player player, Node node) { if(node instanceof Scenery){ - if(player.getQuestRepository().getStage("Fishing Contest") > 0 && player.getQuestRepository().getStage("Fishing Contest") < 100){ + if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) > 0 && player.getQuestRepository().getStage(Quests.FISHING_CONTEST) < 100){ player.getPulseManager().run(new MovementPulse(player, node.asScenery().getLocation().transform(0, 0, 0)) { @Override public boolean pulse() { diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/AnitaDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/AnitaDialogue.kt index 00aa223ea..4d9c58b1c 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/AnitaDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/AnitaDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.grandtree +import content.data.Quests import core.api.addItemOrDrop import core.api.getQuestStage import core.api.sendDialogue @@ -10,7 +11,7 @@ import org.rs09.consts.Items class AnitaDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - when(getQuestStage(player!!, TheGrandTree.questName)){ + when(getQuestStage(player!!, Quests.THE_GRAND_TREE)){ 60 -> { if(player!!.hasItem(Item(Items.GLOUGHS_KEY_788)) && stage < 12){ when(stage){ diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/BlackDemonNPC.kt b/Server/src/main/content/region/kandarin/quest/grandtree/BlackDemonNPC.kt index cdefc97de..112321405 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/BlackDemonNPC.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/BlackDemonNPC.kt @@ -1,13 +1,11 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName +import content.data.Quests import core.api.* import core.game.node.entity.Entity import core.game.node.entity.npc.AbstractNPC -import core.game.node.entity.player.Player import core.game.world.map.Location import core.plugin.Initializable -import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.interaction.InteractionListener @@ -28,7 +26,7 @@ class BlackDemonNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id,lo override fun finalizeDeath(killer: Entity?) { // In the event that this npcID is used somewhere else... if(killer!!.asPlayer().location.regionId == 9882) { - setQuestStage(killer!!.asPlayer(), questName, 98) + setQuestStage(killer!!.asPlayer(), Quests.THE_GRAND_TREE, 98) this.isRespawn = false } super.finalizeDeath(killer) diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/CaptainErrdoDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/CaptainErrdoDialogue.kt index 1460a7399..2b225bb47 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/CaptainErrdoDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/CaptainErrdoDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.grandtree +import content.data.Quests import content.global.travel.glider.Gliders import core.api.getQuestStage import core.api.teleport @@ -10,7 +11,7 @@ import core.tools.END_DIALOGUE class CaptainErrdoDialogue: DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - when(getQuestStage(player!!, TheGrandTree.questName)){ + when(getQuestStage(player!!, Quests.THE_GRAND_TREE)){ 55 -> { if(player!!.location.regionId == 11567){ when(stage){ diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/CharlieDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/CharlieDialogue.kt index 24feddcd1..d4af65825 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/CharlieDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/CharlieDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName +import content.data.Quests import core.ServerConstants import core.api.* import core.game.dialogue.DialogueFile @@ -18,7 +18,7 @@ import org.rs09.consts.NPCs class CharlieDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, questName)) { + when (getQuestStage(player!!, Quests.THE_GRAND_TREE)) { 46 -> { when (stage) { 0 -> playerl("Tell me. Why would you want to kill the Grand Tree?").also { stage++ } @@ -32,7 +32,7 @@ class CharlieDialogue : DialogueFile() { 8 -> npcl("I don't know what he's up to. If you want to find out, you'd better search his home.").also { stage++ } 9 -> playerl("OK. Thanks Charlie.").also { stage++ } 10 -> npcl("Good luck!").also { - setQuestStage(player!!, questName, 47) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 47) stage = END_DIALOGUE } } @@ -79,7 +79,7 @@ class CharlieDialogue : DialogueFile() { 8 -> { unlock(player!!) npc.clear() - setQuestStage(player!!, questName, 55) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 55) return true } } @@ -102,7 +102,7 @@ class CharlieDialogue : DialogueFile() { 6 -> playerl("Where does she live?").also { stage++ } 7 -> npcl("Just west of the toad swamp.").also { stage++ } 8 -> playerl("OK, I'll see what I can find.").also { - setQuestStage(player!!, questName, 60) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 60) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/ForemanNPC.kt b/Server/src/main/content/region/kandarin/quest/grandtree/ForemanNPC.kt index 56381b09e..1977a47b8 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/ForemanNPC.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/ForemanNPC.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.grandtree +import content.data.Quests import core.ServerConstants import core.api.* import core.game.component.Component @@ -38,7 +39,7 @@ class ForemanNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id,locat } override fun finalizeDeath(killer: Entity?) { - if(getQuestStage(killer as Player, TheGrandTree.questName) == 55) { + if(getQuestStage(killer as Player, Quests.THE_GRAND_TREE) == 55) { sendMessage(killer,"The foreman drops a piece of paper as he dies.") produceGroundItem(killer, Items.LUMBER_ORDER_787, 1, this.location) } diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/GloughDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/GloughDialogue.kt index 5b538b8d4..496184c70 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/GloughDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/GloughDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -15,7 +15,7 @@ import core.tools.END_DIALOGUE class GloughDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, questName)) { + when (getQuestStage(player!!, Quests.THE_GRAND_TREE)) { 40 -> { when (stage) { 0 -> playerl("Hello.").also { stage++ } @@ -28,7 +28,7 @@ class GloughDialogue : DialogueFile() { 7 -> npcl("I should've known! The humans are going to invade!").also { stage++ } 8 -> playerl("Never!").also { stage++ } 9 -> npcl("Your type can't be trusted! I'll take care of this! Go back to the King.").also { - setQuestStage(player!!, questName, 45) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 45) stage = END_DIALOGUE } } @@ -70,7 +70,7 @@ class GloughDialogue : DialogueFile() { } 8 -> { npc.clear() - setQuestStage(player!!, questName, 50) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 50) teleport(player!!, cell) player!!.unlock() return true diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/GrandTreeListeners.kt b/Server/src/main/content/region/kandarin/quest/grandtree/GrandTreeListeners.kt index 4c969c234..8548efe96 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/GrandTreeListeners.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/GrandTreeListeners.kt @@ -1,6 +1,5 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -15,6 +14,7 @@ import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import org.rs09.consts.NPCs import org.rs09.consts.Sounds +import content.data.Quests class GrandTreeListeners: InteractionListener { @@ -90,7 +90,7 @@ class GrandTreeListeners: InteractionListener { } on(2444, IntType.SCENERY, "open"){ player, node -> - if(node.location == Location(2487,3464,2) && !isQuestComplete(player, questName)){ + if(node.location == Location(2487,3464,2) && !isQuestComplete(player, Quests.THE_GRAND_TREE)){ if(getAttribute(player, "/save:grandtree:twig1", false) && getAttribute(player, "/save:grandtree:twig2", false) && getAttribute(player, "/save:grandtree:twig3", false) && @@ -103,7 +103,10 @@ class GrandTreeListeners: InteractionListener { } on(2446, IntType.SCENERY, "open"){ player, node -> - if(node.location == Location(2463, 3497, 0) && isQuestComplete(player!!, questName)){ + if(node.location == Location(2463, 3497, 0) && isQuestComplete( + player!!, + Quests.THE_GRAND_TREE + )){ player.animator.animate(Animation(828)) // Go to tunnels teleport(player, Location(2464, 9897, 0)) @@ -115,8 +118,8 @@ class GrandTreeListeners: InteractionListener { SceneryBuilder.replace(Scenery(2436, Location(2482,3462,1)),Scenery(2437, Location(2482,3462,1)),2) sendDialogue(player,"You found a scroll!") addItemOrDrop(player, Items.INVASION_PLANS_794) - if(getQuestStage(player!!, questName) < 60) - setQuestStage(player!!, questName, 60) + if(getQuestStage(player!!, Quests.THE_GRAND_TREE) < 60) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 60) return@onUseWith true } onUseWith(IntType.SCENERY, Items.TWIGS_789, 2440){ player, used, with -> @@ -165,7 +168,7 @@ class GrandTreeListeners: InteractionListener { return@on true } on(2435, IntType.SCENERY, "search"){ player, _ -> - if(getQuestStage(player, questName) == 47){ + if(getQuestStage(player, Quests.THE_GRAND_TREE) == 47){ sendItemDialogue(player, Items.GLOUGHS_JOURNAL_785,"You've found Glough's Journal!") addItemOrDrop(player, Items.GLOUGHS_JOURNAL_785) } @@ -174,7 +177,7 @@ class GrandTreeListeners: InteractionListener { // Roots for Daconia rock on(32319, IntType.SCENERY, "search"){ player, node -> - if(getQuestStage(player, questName) < 99 || player.hasItem(Item(Items.DACONIA_ROCK_793))){ return@on true; } + if(getQuestStage(player, Quests.THE_GRAND_TREE) < 99 || player.hasItem(Item(Items.DACONIA_ROCK_793))){ return@on true; } // RNG for which root the rock is under if(node.location == roots[getAttribute(player,"grandtree:rock",1)]){ sendItemDialogue(player, Item(Items.DACONIA_ROCK_793), "You've found a Daconia rock!") @@ -192,7 +195,7 @@ class GrandTreeListeners: InteractionListener { return@on true } on(2451, IntType.SCENERY, "push"){ player, roots -> - if (hasRequirement(player, "The Grand Tree")) { + if (hasRequirement(player, Quests.THE_GRAND_TREE)) { val outsideMine = player.location == Location.create(2467, 9903, 0) || player.location == Location.create(2468, 9903, 0) if(outsideMine) { forceMove(player, player.location, player.location.transform(0, 2, 0), 25, 60, null, 819) diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/HazelmereDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/HazelmereDialogue.kt index 9edb39423..ab59a6ba6 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/HazelmereDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/HazelmereDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.node.item.Item @@ -10,7 +10,7 @@ import org.rs09.consts.Items class HazelmereDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, questName)) { + when (getQuestStage(player!!, Quests.THE_GRAND_TREE)) { 10 -> { if(player!!.hasItem(Item(Items.BARK_SAMPLE_783))){ when (stage) { @@ -24,7 +24,7 @@ class HazelmereDialogue : DialogueFile() { if(removeItem(player!!, Items.BARK_SAMPLE_783)){ addItemOrDrop(player!!, Items.HAZELMERES_SCROLL_786) } - setQuestStage(player!!, questName, 20) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 20) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/KingNarnodeDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/KingNarnodeDialogue.kt index 1725f0117..5cbf67861 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/KingNarnodeDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/KingNarnodeDialogue.kt @@ -1,6 +1,6 @@ package content.region.kandarin.quest.grandtree -import content.region.kandarin.quest.grandtree.TheGrandTree.Companion.questName +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.interaction.MovementPulse @@ -67,7 +67,7 @@ class KingNarnodeDialogue : DialogueFile() { }) } override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, questName)) { + when (getQuestStage(player!!, Quests.THE_GRAND_TREE)) { 0 -> { when (stage) { 0 -> npcl("Welcome Traveller. I am King Narnode. It's nice to see an outsider.").also { stage++ } @@ -222,7 +222,7 @@ class KingNarnodeDialogue : DialogueFile() { 64 -> npcl("First, I must warn the tree guardians. Please, could you tell the chief tree guardian, Glough. He lives in a tree house just in front of the Grand Tree.").also { stage++ } 65 -> npcl("If he's not there he will be at his girlfriend Anita's place. Meet me back here once you've told him.").also { stage++ } 66 -> playerl("Ok! I'll be back soon.").also { - setQuestStage(player!!, questName, 40) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 40) stage = END_DIALOGUE } } @@ -242,7 +242,7 @@ class KingNarnodeDialogue : DialogueFile() { 3 -> npcl("Yes Glough really knows what he's doing. The human has been detained until we know who else is involved. Maybe Glough was right, maybe humans are invading!").also { stage++ } 4 -> playerl("I doubt it, can I speak to the prisoner?").also { stage++ } 5 -> npcl("Certainly. He's on the top level of the tree. Be careful, it's a long way down!").also { - setQuestStage(player!!, questName, 46) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 46) stage = END_DIALOGUE } } @@ -281,7 +281,7 @@ class KingNarnodeDialogue : DialogueFile() { } 7 -> npcl("On the other hand, if Glough's right about the humans we will need an army of gnomes to protect ourselves. ").also { stage++ } 8 -> npcl("So I've decided to allow Glough to raise a mighty gnome army. The Grand Tree's still slowly dying. If it is human sabotage we must respond!").also{ - setQuestStage(player!!, questName, 70) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 70) removeItem(player!!, Item(Items.INVASION_PLANS_794), Container.INVENTORY) stage = END_DIALOGUE } @@ -383,7 +383,7 @@ class KingNarnodeUnderGroundDialogue : DialogueFile() { }) } override fun handle(componentID: Int, buttonID: Int) { - when(getQuestStage(player!!, questName)) { + when(getQuestStage(player!!, Quests.THE_GRAND_TREE)) { 98 -> when (stage) { 0 -> npcl("Traveller, you're wounded! What happened?").also { stage++ } 1 -> playerl("It's Glough! He set a demon on me!").also { stage++ } @@ -398,7 +398,7 @@ class KingNarnodeUnderGroundDialogue : DialogueFile() { 10 -> sendNPCDialogue(player!!, NPCs.GNOME_GUARD_163,"Yes sir!").also{ stage++ } 11 -> npcl("You have my full apologies Traveller! And my gratitude! A reward will have to wait though, the tree is still dying!").also {stage++} 12 -> npcl("The guards are clearing Glough's rock supply now but there must be more Daconia hidden somewhere in the roots! Help us search, we have little time!").also { - setQuestStage(player!!, questName, 99) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 99) // position of the daconia rock if(getAttribute(player!!,"treegnome:rock",0) == 0){ val answer = (1..5).random() @@ -425,7 +425,7 @@ class KingNarnodeUnderGroundDialogue : DialogueFile() { 11 -> playerl("Strange!").also { stage++ } 12 -> npcl("That's magic trees for you! All the best Traveller and thanks again!").also { stage++ } 13 -> playerl("You too, Your Highness!").also { - finishQuest(player!!, questName) + finishQuest(player!!, Quests.THE_GRAND_TREE) removeItem(player!!, Items.DACONIA_ROCK_793) stage = END_DIALOGUE } @@ -494,7 +494,7 @@ class KingNarnodeUnderGroundDialogue : DialogueFile() { 31 -> if (player!!.inventory.freeSlots() >= 2) { npcl("Up here.") stage = END_DIALOGUE - setQuestStage(player!!, questName, 10) + setQuestStage(player!!, Quests.THE_GRAND_TREE, 10) addItemOrDrop(player!!, Items.BARK_SAMPLE_783) addItemOrDrop(player!!, Items.TRANSLATION_BOOK_784) leadUpLadder() diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/ShipyardWorkerDialogue.kt b/Server/src/main/content/region/kandarin/quest/grandtree/ShipyardWorkerDialogue.kt index a2a1fa0ea..1487b306c 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/ShipyardWorkerDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/ShipyardWorkerDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.grandtree +import content.data.Quests import core.api.getAttribute import core.api.getQuestStage import core.api.setAttribute @@ -13,7 +14,7 @@ class ShipyardWorkerDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { when(stage){ 0 -> npcl("Hey you! What are you up to?").also { - if(getQuestStage(player!!, TheGrandTree.questName) == 55) { + if(getQuestStage(player!!, Quests.THE_GRAND_TREE) == 55) { setAttribute(player!!, "/save:grandtree:opt1", false) setAttribute(player!!, "/save:grandtree:opt2", false) setAttribute(player!!, "/save:grandtree:opt3", false) diff --git a/Server/src/main/content/region/kandarin/quest/grandtree/TheGrandTree.kt b/Server/src/main/content/region/kandarin/quest/grandtree/TheGrandTree.kt index e8bff2b27..c1b74008f 100644 --- a/Server/src/main/content/region/kandarin/quest/grandtree/TheGrandTree.kt +++ b/Server/src/main/content/region/kandarin/quest/grandtree/TheGrandTree.kt @@ -1,15 +1,15 @@ package content.region.kandarin.quest.grandtree -import core.api.addItemOrDrop import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class TheGrandTree: Quest("The Grand Tree", 71, 70, 5, 150, 0, 1, 160) { +class TheGrandTree: Quest(Quests.THE_GRAND_TREE, 71, 70, 5, 150, 0, 1, 160) { override fun newInstance(`object`: Any?): Quest { return this } @@ -96,7 +96,4 @@ class TheGrandTree: Quest("The Grand Tree", 71, 70, 5, 150, 0, 1, 160) { } } - companion object { - const val questName = "The Grand Tree" - } } diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCPeksaDialogue.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCPeksaDialogue.kt index c3ab84300..79df6ceac 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCPeksaDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCPeksaDialogue.kt @@ -5,6 +5,7 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.Topic import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests class SCPeksaDialogue(val questStage: Int) : DialogueFile() { @@ -32,7 +33,7 @@ class SCPeksaDialogue(val questStage: Int) : DialogueFile() { THANK_YOU -> { playerl("Thanks for the information").also { stage++ } - setQuestStage(player!!, "Scorpion Catcher", ScorpionCatcher.QUEST_STATE_PEKSA_HELP) + setQuestStage(player!!, Quests.SCORPION_CATCHER, ScorpionCatcher.QUEST_STATE_PEKSA_HELP) } THANK_YOU + 1 -> npcl ("No problems! Tell Ivor I said hi!").also { stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCSeerDialogue.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCSeerDialogue.kt index 5be607e56..a15b267c2 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCSeerDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCSeerDialogue.kt @@ -7,6 +7,7 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests class SCSeerDialogue(val questStage: Int, private val dialogueEntry: Int) : DialogueFile() { @@ -62,7 +63,7 @@ class SCSeerDialogue(val questStage: Int, private val dialogueEntry: Int) : Dial FIRST_SCORPION_GUIDE + 4 -> npcl("I can see a scorpion that you seek. It would appear to be near some nasty spiders. I can see two coffins there as well.").also { stage++ } FIRST_SCORPION_GUIDE + 5 -> npcl("The scorpion seems to be going through some crack in the wall. Its gone into some sort of secret room.").also { stage++ } FIRST_SCORPION_GUIDE + 6 -> npcl("Well see if you can find the scorpion then, and I'll try and get you some information on the others.").also { - setQuestStage(player!!, "Scorpion Catcher", ScorpionCatcher.QUEST_STATE_DARK_PLACE) + setQuestStage(player!!, Quests.SCORPION_CATCHER, ScorpionCatcher.QUEST_STATE_DARK_PLACE) stage = END_DIALOGUE } @@ -70,7 +71,7 @@ class SCSeerDialogue(val questStage: Int, private val dialogueEntry: Int) : Dial OTHER_SCORPIONS + 1 -> playerl("Any more scorpions?").also { stage++ } OTHER_SCORPIONS + 2 -> npcl ("It's good that you should ask. I have information on the last scorpion for you.").also { stage++ } OTHER_SCORPIONS + 3 -> npcl ("It seems to be in some sort of upstairs room. There seems to be some sort of brown clothing lying on a table.").also { - setQuestStage(player!!, "Scorpion Catcher", ScorpionCatcher.QUEST_STATE_OTHER_SCORPIONS) + setQuestStage(player!!, Quests.SCORPION_CATCHER, ScorpionCatcher.QUEST_STATE_OTHER_SCORPIONS) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt index d144c7650..bd4b91b78 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCThormacDialogue.kt @@ -9,6 +9,7 @@ import core.api.* import core.game.dialogue.Topic import core.game.node.item.Item import org.rs09.consts.Items +import content.data.Quests class SCThormacDialogue(val questStage: Int) : DialogueFile() { @@ -60,7 +61,7 @@ class SCThormacDialogue(val questStage: Int) : DialogueFile() { WHY_SHOULD_I_START -> npcl(FacialExpression.WORRIED, "Well I suppose I can aid you with my skills as a staff sorcerer. " + "Most battlestaffs around here are a bit puny. I can beef them up for you a bit.").also { // Need to recheck the quest stage since it may have been changed in this dialogue - if(getQuestStage(player!!, "Scorpion Catcher") == 0) stage++ + if(getQuestStage(player!!, Quests.SCORPION_CATCHER) == 0) stage++ else stage = END_DIALOGUE } WHY_SHOULD_I_START+1 -> showTopics( @@ -75,7 +76,7 @@ class SCThormacDialogue(val questStage: Int) : DialogueFile() { } HOW_TO_CATCH+1 -> { sendItemDialogue(player!!, Items.SCORPION_CAGE_456, "Thormac gives you a cage.").also { stage++ } - startQuest(player!!, "Scorpion Catcher") + startQuest(player!!, Quests.SCORPION_CATCHER) addItem(player!!, Items.SCORPION_CAGE_456) } HOW_TO_CATCH+2 -> npcl(FacialExpression.WORRIED, "If you go up to the village of Seers, to the North of " + @@ -122,7 +123,7 @@ class SCThormacDialogue(val questStage: Int) : DialogueFile() { player!!.removeAttribute("scorpion_catcher:caught_monk") } GOT_THEM_ALL+2 ->{ - end().also { finishQuest(player!!, "Scorpion Catcher") } + end().also { finishQuest(player!!, Quests.SCORPION_CATCHER) } } diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCWallListener.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCWallListener.kt index 858f1650c..864f2ce08 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCWallListener.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/SCWallListener.kt @@ -7,6 +7,7 @@ import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.world.map.Location import org.rs09.consts.Scenery +import content.data.Quests class SCWallListener : InteractionListener { @@ -16,7 +17,7 @@ class SCWallListener : InteractionListener { //https://youtu.be/crc-47rwjvE?feature=shared&t=841 // Otherwise the crack reverts back to normal // Doesn't make any sense but that's authentic... - if ((ScorpionCatcher.QUEST_STATE_DARK_PLACE .. 99).contains(getQuestStage(player, "Scorpion Catcher"))) { + if ((ScorpionCatcher.QUEST_STATE_DARK_PLACE .. 99).contains(getQuestStage(player, Quests.SCORPION_CATCHER))) { // Check what side the player is on and teleport them to the other if (player.location == Location(2875, 9799, 0)){ sendMessage(player, "You've found a secret door") diff --git a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt index a2692b439..ba9cc4046 100644 --- a/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt +++ b/Server/src/main/content/region/kandarin/quest/scorpioncatcher/ScorpionCatcher.kt @@ -5,9 +5,10 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class ScorpionCatcher : Quest("Scorpion Catcher", 108, 107, 1, 76, 0, 1, 6) { +class ScorpionCatcher : Quest(Quests.SCORPION_CATCHER, 108, 107, 1, 76, 0, 1, 6) { companion object { const val QUEST_STATE_NOT_STARTED = 0 const val QUEST_STATE_TALK_SEERS = 10 diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/FireWarriorOfLesarkusNPC.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/FireWarriorOfLesarkusNPC.kt index 0b700a2d3..5dbcbb4e5 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/FireWarriorOfLesarkusNPC.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/FireWarriorOfLesarkusNPC.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.FacialExpression import core.game.node.entity.Entity @@ -7,7 +8,6 @@ import core.game.node.entity.combat.BattleState import core.game.node.entity.combat.CombatStyle import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player -import core.game.system.task.Pulse import core.game.world.map.Location import org.rs09.consts.NPCs @@ -64,8 +64,8 @@ class FireWarriorOfLesarkusNPC(id: Int = 0, val player: Player?, location: Locat if (entity is Player) { val player = entity.asPlayer() removeAttribute(player, TempleOfIkov.attributeWarriorInstance) - if(getQuestStage(player, TempleOfIkov.questName) == 3) { - setQuestStage(player, TempleOfIkov.questName, 4) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 3) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 4) } super.finalizeDeath(player) } diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylBehavior.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylBehavior.kt index 6101484c1..846c5204f 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylBehavior.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylBehavior.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.isQuestComplete import core.game.node.entity.Entity import core.game.node.entity.npc.NPC @@ -21,7 +22,7 @@ class GuardianOfArmadylBehavior : NPCBehavior(*guardianOfArmadylIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops Pendant of Armadyl after quest complete when killed. - if (killer is Player && isQuestComplete(killer, TempleOfIkov.questName)) { + if (killer is Player && isQuestComplete(killer, Quests.TEMPLE_OF_IKOV)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.ARMADYL_PENDANT_87)) } diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylDialogue.kt index 50a9293e4..c8900621f 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/GuardianOfArmadylDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -143,8 +144,8 @@ class GuardianOfArmadylDialogueFile : DialogueBuilderFile() { .item(Items.ARMADYL_PENDANT_87, "The guardian has given you a pendant.") .endWith { _, player -> setAttribute(player, TempleOfIkov.attributeChosenEnding, 1) - if (getQuestStage(player, TempleOfIkov.questName) == 5) { - setQuestStage(player, TempleOfIkov.questName, 6) + if (getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 5) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 6) } addItemOrDrop(player, Items.ARMADYL_PENDANT_87) } diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt index d751c08a7..c093d134e 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -26,7 +27,7 @@ class LucienDialogue (player: Player? = null) : DialoguePlugin(player) { class LucienDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TempleOfIkov.questName, 100) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 100) .playerl("I thought I killed you?!") .npcl("Ha! Ha! Ha!") .npcl("You can not kill me human!") @@ -44,7 +45,7 @@ class LucienDialogueFile : DialogueBuilderFile() { .item(Items.PENDANT_OF_LUCIEN_86, "Lucien has given you another pendant!") .end() } - b.onQuestStages(TempleOfIkov.questName, 1,2,3,4,5,6,7) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 1, 2, 3, 4, 5, 6, 7) .npcl("I told you not to meet me here again!") .branch { player -> return@branch if (inInventory(player, Items.PENDANT_OF_LUCIEN_86)) { 1 } else { 0 } @@ -65,7 +66,7 @@ class LucienDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(TempleOfIkov.questName, 0) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 0) .npcl("I seek a hero to go on an important mission!") .options().let { optionBuilder -> val returnJoin = b.placeholder() @@ -100,8 +101,8 @@ class LucienDialogueFile : DialogueBuilderFile() { .npcl("I cannot stay here much longer. ") .npcl("I will be west of the Grand Exchange in Varrock. I have a small holding up there.") .endWith { _, player -> - if(getQuestStage(player, TempleOfIkov.questName) == 0) { - setQuestStage(player, TempleOfIkov.questName, 1) + if (getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 0) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 1) } } optionBuilder.option_playerl("Oh no! Sounds far too dangerous!") diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt index c2d974bc5..2ba1dd6b7 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.* import core.game.node.entity.player.Player @@ -23,13 +24,13 @@ class LucienEndingDialogue (player: Player? = null) : DialoguePlugin(player) { class LucienEndingDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TempleOfIkov.questName, 100) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 100) .endWith { _, player -> // After quest is over: https://www.youtube.com/watch?v=81DXjfsFcMM sendMessage(player, "You feel that fighting this individual will be of little practical use.") sendMessage(player, "You have completed the Temple of Ikov quest.") } - b.onQuestStages(TempleOfIkov.questName, 1,2,3,4,5,6,7) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 1, 2, 3, 4, 5, 6, 7) .npcl(FacialExpression.FRIENDLY, "Have you got the Staff of Armadyl yet?") .branch { player -> return@branch if (inInventory(player, Items.STAFF_OF_ARMADYL_84)) { 1 } else { 0 } @@ -46,8 +47,8 @@ class LucienEndingDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.FRIENDLY, "I can feel the power of the staff running through me! I will be more powerful and they shall bow down to me!") .npcl(FacialExpression.FRIENDLY, "I suppose you want your reward? I shall grant you much power!") .endWith { _, player -> - if(getQuestStage(player, TempleOfIkov.questName) == 6) { - finishQuest(player, TempleOfIkov.questName) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 6) { + finishQuest(player, Quests.TEMPLE_OF_IKOV) } } optionBuilder.option_playerl("No, not yet.") diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingNPC.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingNPC.kt index c4d7a4319..18e8e429b 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingNPC.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/LucienEndingNPC.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.node.entity.Entity @@ -40,8 +41,8 @@ class LucienEndingNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, when(stage){ 0 -> npcl("You have defeated me for now! I shall reappear in the North!").also { stage++ } 1 -> end().also { - if(getQuestStage(player, TempleOfIkov.questName) == 6) { - finishQuest(player, TempleOfIkov.questName) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 6) { + finishQuest(player, Quests.TEMPLE_OF_IKOV) } } } diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt index 632710b24..ebfc4773b 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkov.kt @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Temple of Ikov Quest @@ -28,10 +29,9 @@ import org.rs09.consts.Items * D - Found ice arrows */ @Initializable -class TempleOfIkov : Quest("Temple of Ikov", 121, 120, 1,26, 0, 1, 80 /* 80 or 90 since there's 2 endings */) { +class TempleOfIkov : Quest(Quests.TEMPLE_OF_IKOV, 121, 120, 1,26, 0, 1, 80 /* 80 or 90 since there's 2 endings */) { companion object { - const val questName = "Temple of Ikov" const val attributeChosenEnding = "/save:quest:templeofikov-chosenending" const val attributeDisabledTrap = "/save:quest:templeofikov-disabledtrap" @@ -49,7 +49,7 @@ class TempleOfIkov : Quest("Temple of Ikov", 121, 120, 1,26, 0, 1, 80 /* 80 or 9 var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.TEMPLE_OF_IKOV) > 0 if (!started) { line(player, "I can start this quest at the !!Flying Horse Inn?? in !!Ardougne??", line++, false) diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkovListeners.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkovListeners.kt index 6a832b230..f513997e3 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkovListeners.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/TempleOfIkovListeners.kt @@ -1,7 +1,6 @@ package content.region.kandarin.quest.templeofikov -import content.global.ame.events.drilldemon.DrillDemonUtils -import content.global.ame.events.drilldemon.SeargentDamienDialogue +import content.data.Quests import content.global.skill.agility.AgilityHandler import core.api.* import core.game.global.action.DoorActionHandler @@ -9,7 +8,6 @@ import core.game.global.action.PickupHandler import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.interaction.QueueStrength -import core.game.node.entity.Entity import core.game.node.entity.skill.Skills import core.game.node.item.GroundItem import core.game.node.item.Item @@ -20,7 +18,6 @@ import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import org.rs09.consts.NPCs import org.rs09.consts.Scenery -import org.rs09.consts.Sounds class TempleOfIkovListeners : InteractionListener { @@ -63,8 +60,8 @@ class TempleOfIkovListeners : InteractionListener { // 1 - 2 Walk past the gate. You must always wear the pendant to get past this gate. on(intArrayOf(Scenery.GATE_94, Scenery.GATE_95), SCENERY, "open") { player, node -> if (inEquipment(player, Items.PENDANT_OF_LUCIEN_86)){ - if(getQuestStage(player, TempleOfIkov.questName) == 1) { - setQuestStage(player, TempleOfIkov.questName, 2) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 1) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 2) } DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { @@ -87,8 +84,8 @@ class TempleOfIkovListeners : InteractionListener { replaceScenery(node.asScenery(), 88, 3) animate(player, Animation(2140)) if (getAttribute(player, TempleOfIkov.attributeDisabledTrap, false)) { - if(getQuestStage(player, TempleOfIkov.questName) == 2) { - setQuestStage(player, TempleOfIkov.questName, 3) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 2) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 3) } } else { AgilityHandler.fail(player, 2, Location.create(2682, 9855, 0), Animation(770), 20, "You slip and fall to the pit below.") @@ -142,7 +139,10 @@ class TempleOfIkovListeners : InteractionListener { // C: Gate opens after attached lever on(intArrayOf(Scenery.GATE_89, Scenery.GATE_90), SCENERY, "open") { player, node -> - if (getAttribute(player, TempleOfIkov.attributeIceChamberAccess, false) || getQuestStage(player, TempleOfIkov.questName) >= 4){ + if (getAttribute(player, TempleOfIkov.attributeIceChamberAccess, false) || getQuestStage( + player, + Quests.TEMPLE_OF_IKOV + ) >= 4){ // To be nice, you can "reset" the chest location by opening the gate. // This is a failsafe if the attribute gets "stuck", although I doubt it will happen. setAttribute(player, TempleOfIkov.attributeRandomChest, chestLocations.random()) @@ -189,7 +189,7 @@ class TempleOfIkovListeners : InteractionListener { // 3: Allow access to Fire Warrior Door after pulling the lever on(Scenery.DOOR_92, SCENERY, "open") { player, node -> removeAttribute(player, TempleOfIkov.attributeWarriorInstance) - if (getQuestStage(player, TempleOfIkov.questName) >= 3){ + if (getQuestStage(player, Quests.TEMPLE_OF_IKOV) >= 3){ DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendMessage(player, "The door won't open.") @@ -200,7 +200,7 @@ class TempleOfIkovListeners : InteractionListener { // 3 - 4: Calls for the Fire Warrior, allows passing when Fire Warrior is defeated. on(Scenery.DOOR_93, SCENERY, "open") { player, node -> - if (getQuestStage(player, TempleOfIkov.questName) >= 4){ + if (getQuestStage(player, Quests.TEMPLE_OF_IKOV) >= 4){ DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { if (getAttribute(player, TempleOfIkov.attributeWarriorInstance, null) == null) { @@ -240,7 +240,7 @@ class TempleOfIkovListeners : InteractionListener { } on(Items.STAFF_OF_ARMADYL_84, IntType.GROUNDITEM,"take") { player, node -> - if (getQuestStage(player, TempleOfIkov.questName) >= 6 && getAttribute(player, TempleOfIkov.attributeChosenEnding, 0) == 1){ + if (getQuestStage(player, Quests.TEMPLE_OF_IKOV) >= 6 && getAttribute(player, TempleOfIkov.attributeChosenEnding, 0) == 1){ sendMessage(player, "You decide not to steal the staff as you have agreed to help the Guardians") } val npcs = findLocalNPCs(player, intArrayOf(NPCs.GUARDIAN_OF_ARMADYL_274, NPCs.GUARDIAN_OF_ARMADYL_275), 4) @@ -248,8 +248,8 @@ class TempleOfIkovListeners : InteractionListener { sendChat(npcs[0], "That is not thine to take!") npcs[0].attack(player) } else { - if(getQuestStage(player, TempleOfIkov.questName) == 5) { - setQuestStage(player, TempleOfIkov.questName, 6) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 5) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 6) setAttribute(player, TempleOfIkov.attributeChosenEnding, 2) } PickupHandler.take(player, node as GroundItem) diff --git a/Server/src/main/content/region/kandarin/quest/templeofikov/WineldaDialogue.kt b/Server/src/main/content/region/kandarin/quest/templeofikov/WineldaDialogue.kt index d525d1eb3..aa34d7d76 100644 --- a/Server/src/main/content/region/kandarin/quest/templeofikov/WineldaDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/templeofikov/WineldaDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.templeofikov +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -28,7 +29,7 @@ class WineldaDialogue (player: Player? = null) : DialoguePlugin(player) { class WineldaDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TempleOfIkov.questName, 5,6,7,100) + b.onQuestStages(Quests.TEMPLE_OF_IKOV, 5, 6, 7, 100) .playerl(FacialExpression.FRIENDLY, "Hi again. Could you do the honours again please?") .npcl(FacialExpression.FRIENDLY, "Certainly! We helps those that helps poor Winelda!") .endWith { _, player -> @@ -56,8 +57,8 @@ class WineldaDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.FRIENDLY, "Good! Good! My potion is nearly ready! Bubble, bubble, toil and trouble!") .npcl(FacialExpression.FRIENDLY, "Now we shows them ours magic! Hold on tight!") .endWith { _, player -> - if(getQuestStage(player, TempleOfIkov.questName) == 4) { - setQuestStage(player, TempleOfIkov.questName, 5) + if(getQuestStage(player, Quests.TEMPLE_OF_IKOV) == 4) { + setQuestStage(player, Quests.TEMPLE_OF_IKOV, 5) } // There's a cutscene, but I'm lazy man. teleport(player, Location(2664, 9876, 0)) diff --git a/Server/src/main/content/region/kandarin/quest/tree/BallistaDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/BallistaDialogue.kt index eb707dbf5..afc028e55 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/BallistaDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/BallistaDialogue.kt @@ -1,12 +1,13 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE class BallistaDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) if (questStage > 30) { when (stage) { 0 -> sendDialogue(player!!, "The Khazard stronghold has already been breached.").also { stage = END_DIALOGUE } @@ -28,7 +29,7 @@ class BallistaDialogue : DialogueFile(){ when (buttonID) { answer -> { sendDialogue(player!!, "The huge spear flies through the air and screams down directly into the Khazard stronghold. A deafening crash echoes over the battlefield as the front entrance is reduced to rubble.") - setQuestStage(player!!, TreeGnomeVillage.questName, 31) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 31) } else -> sendDialogue(player!!, "The huge spear completely misses the Khazard stronghold!") } diff --git a/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt index 083066d20..cc79075df 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile @@ -7,7 +8,7 @@ import core.tools.END_DIALOGUE class CommanderMontaiDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) if (questStage == 10) { when(stage) { 0 -> playerl("Hello.").also { stage++ } @@ -24,7 +25,7 @@ class CommanderMontaiDialogue : DialogueFile(){ } 9 -> npcl("That's a shame, we could have done with your help.").also { stage = END_DIALOGUE } 10 -> npcl("Please be as quick as you can, I don't know how much longer we can hold out.").also { - setQuestStage(player!!, TreeGnomeVillage.questName, 20) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 20) stage = END_DIALOGUE } } @@ -37,7 +38,7 @@ class CommanderMontaiDialogue : DialogueFile(){ 3 -> { // Remove the 6 normal logs for(i in 1..6) { removeItem(player!!,Items.LOGS_1511) } - setQuestStage(player!!, TreeGnomeVillage.questName, 25) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 25) npcl("That's excellent, now we can make more defensive battlements. Give me a moment to organize the troops and then come speak to me. I'll inform you of our next phase of attack.") stage = END_DIALOGUE } @@ -69,7 +70,7 @@ class CommanderMontaiDialogue : DialogueFile(){ 11 -> npcl("Thank you, you're braver than most.").also { stage++ } 12 -> npcl("I don't know how long I will be able to hold out. Once you have the coordinates come back and fire the ballista right into those monsters.").also { stage++ } 13 -> npcl("If you can retrieve the orb and bring safety back to my people, none of the blood spilled on this field will be in vain.").also { - setQuestStage(player!!, TreeGnomeVillage.questName, 30) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 30) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt index 61636b90f..135624829 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import core.game.component.Component import core.game.node.entity.player.Player @@ -10,7 +11,6 @@ import org.rs09.consts.Items import core.game.dialogue.DialogueFile import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeEntrance import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeVillage -import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.questName import core.game.world.GameWorld.Pulser import core.tools.END_DIALOGUE @@ -38,7 +38,7 @@ class ElkoyDialogue : DialogueFile(){ }) } override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) val locY = player!!.location.y val followLocation = if(locY > 3161) "village" else "exit" when { diff --git a/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordDialogue.kt index a4d3df749..b70b6449b 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordDialogue.kt @@ -1,12 +1,13 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.getQuestStage import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE class KhazardWarlordDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) if(questStage == 31){ when(stage) { 0 -> playerl("Hello there.").also { stage++ } diff --git a/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordNPC.kt b/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordNPC.kt index f1a246287..736612730 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordNPC.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/KhazardWarlordNPC.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.addItemOrDrop import core.api.getQuestStage import core.api.sendDialogue @@ -27,7 +28,7 @@ class KhazardWarlordNPC(id: Int = 0, location: Location? = null) : AbstractNPC(i } override fun finalizeDeath(killer: Entity?) { - if(getQuestStage(killer as Player, TreeGnomeVillage.questName) == 40) { + if(getQuestStage(killer as Player, Quests.TREE_GNOME_VILLAGE) == 40) { sendDialogue(killer,"As the warlord falls to the ground, a ghostly vapour floats upwards from his battle-worn armour. You search his satchel and find the orbs of protection.") addItemOrDrop(killer, Items.ORBS_OF_PROTECTION_588) } diff --git a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt index a84f22118..73c26fc14 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import core.game.system.task.Pulse import core.game.world.map.Location @@ -9,13 +10,12 @@ import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.dialogue.DialogueFile import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeEntrance -import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.questName import core.game.world.GameWorld import core.tools.END_DIALOGUE class KingBolrenDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) when { questStage < 10 -> { when (stage) { @@ -51,7 +51,7 @@ class KingBolrenDialogue : DialogueFile() { 21 -> { teleport(player!!, mazeEntrance) sendNPCDialogue(player!!, NPCs.ELKOY_5179, "We're out of the maze now. Please hurry, we must have the orb if we are to survive.") - setQuestStage(player!!, questName, 10) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 10) stage = END_DIALOGUE } } @@ -91,7 +91,7 @@ class KingBolrenDialogue : DialogueFile() { 17 -> { if(removeItem(player!!,Items.ORB_OF_PROTECTION_587)){ teleport(player!!,mazeEntrance) - setQuestStage(player!!, questName,40) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 40) sendNPCDialogue(player!!, NPCs.ELKOY_5179, "Good luck friend.") } stage = END_DIALOGUE @@ -158,7 +158,7 @@ class KingBolrenDialogue : DialogueFile() { }) // This loops back to the start of the handle.. if(removeItem(player!!,Items.ORBS_OF_PROTECTION_588)){ - setQuestStage(player!!,questName,99) + setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 99) } stage = 0 } @@ -180,12 +180,12 @@ class KingBolrenDialogue : DialogueFile() { 3 -> npcl("Please, for your efforts take this amulet. It's made from the same sacred stone as the orbs of protection. It will help keep you safe on your journeys.").also { stage++ } 4 -> playerl("Thank you King Bolren.").also { stage++ } 5 -> npcl("The tree has many other powers, some of which I cannot reveal. As a friend of the gnome people, I can now allow you to use the tree's magic to teleport to other trees grown from related seeds.").also { - finishQuest(player!!,questName) + finishQuest(player!!, Quests.TREE_GNOME_VILLAGE) stage = END_DIALOGUE } } } - isQuestComplete(player!!, questName) -> { + isQuestComplete(player!!, Quests.TREE_GNOME_VILLAGE) -> { when(stage) { 0 -> playerl("Hello again Bolren.").also { stage++ } 1 -> npcl("Well hello, it's good to see you again.").also { stage = if (hasAnItem(player!!, Items.GNOME_AMULET_589).container != null) END_DIALOGUE else 2 } diff --git a/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt index f8cfde14e..79b70b806 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.inInventory import core.api.getQuestStage import org.rs09.consts.Items @@ -8,7 +9,7 @@ import core.tools.END_DIALOGUE class RemsaiDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) when { inInventory(player!!,Items.ORBS_OF_PROTECTION_588) -> { when(stage) { diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt index b9b22bd34..6ad5e3028 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile @@ -7,7 +8,7 @@ import core.tools.END_DIALOGUE class TrackerGnomeOneDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) when { questStage >= 40 -> { when (stage) { diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt index 607e087d5..30070138b 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE @@ -13,7 +14,7 @@ class TrackerGnomeThreeDialogue : DialogueFile(){ 4 to "My legs and your legs.") override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) when { questStage == 30 -> { when(stage) { diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt index f17211fd2..6a845937d 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile @@ -7,7 +8,7 @@ import core.tools.END_DIALOGUE class TrackerGnomeTwoDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - val questStage = getQuestStage(player!!, TreeGnomeVillage.questName) + val questStage = getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) when { questStage == 30 -> { when (stage) { diff --git a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillage.kt b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillage.kt index a87e2ca96..14f04896f 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillage.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillage.kt @@ -8,9 +8,10 @@ import core.game.node.entity.skill.Skills import core.game.world.map.Location import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class TreeGnomeVillage: Quest("Tree Gnome Village", 125, 124, 2, 111, 0, 1, 9) { +class TreeGnomeVillage: Quest(Quests.TREE_GNOME_VILLAGE, 125, 124, 2, 111, 0, 1, 9) { override fun newInstance(`object`: Any?): Quest { return this } @@ -91,6 +92,5 @@ class TreeGnomeVillage: Quest("Tree Gnome Village", 125, 124, 2, 111, 0, 1, 9) companion object { val mazeVillage = Location(2515,3159,0) val mazeEntrance = Location(2504,3192,0) - const val questName = "Tree Gnome Village" } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt index f57509046..26daeac81 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.tree +import content.data.Quests import core.api.* import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player @@ -132,7 +133,7 @@ class TreeGnomeVillageListeners : InteractionListener { val climbAnimation = Animation(839) val wallLoc = Location(2509,3253,0) override fun handle(componentID: Int, buttonID: Int) { - if(getQuestStage(player!!, TreeGnomeVillage.questName) > 30){ + if(getQuestStage(player!!, Quests.TREE_GNOME_VILLAGE) > 30){ val northSouth = if (player!!.location.y <= wallLoc.y) Direction.NORTH else Direction.SOUTH when(stage){ 0 -> sendDialogue(player!!,"The wall has been reduced to rubble. It should be possible to climb over the remains").also{ stage++ } diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java index 91285e36d..6d3f2bee6 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.waterfall; +import content.data.Quests; import core.game.dialogue.DialogueInterpreter; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -27,7 +28,7 @@ public class AlmeraDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); switch (stage) { /* Main dialogue sequence */ case 0: @@ -136,7 +137,7 @@ public class AlmeraDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); if (quest.getStage(player) == 100) { interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello Almera."); stage = 7; @@ -146,4 +147,4 @@ public class AlmeraDialogue extends DialoguePlugin { } return true; } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt b/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt index c3f1bf63f..fe92e9136 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt +++ b/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt @@ -1,5 +1,6 @@ package content.region.kandarin.quest.waterfall +import content.data.Quests import content.global.handlers.iface.BookInterface import content.global.handlers.iface.BookLine import content.global.handlers.iface.Page @@ -143,8 +144,8 @@ class BaxtorianBook : InteractionListener { ) private fun display(player: Player, pageNum: Int, buttonID: Int) : Boolean { BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS) - if (player.questRepository.getQuest(WaterFall.NAME).getStage(player) == 20) { - player.questRepository.getQuest(WaterFall.NAME).setStage(player, 30) + if (player.questRepository.getQuest(Quests.WATERFALL_QUEST).getStage(player) == 20) { + player.questRepository.getQuest(Quests.WATERFALL_QUEST).setStage(player, 30) } return true } diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java index 5e59576fe..e8c3262ad 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.waterfall; +import content.data.Quests; import core.game.dialogue.DialogueInterpreter; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -27,7 +28,7 @@ public class HudonDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); switch (stage) { case 100: // Generic end to the dlg @@ -109,7 +110,7 @@ public class HudonDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); if (quest.getStage(player) >= 20) { interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "So you're still here."); stage = 20; @@ -119,4 +120,4 @@ public class HudonDialogue extends DialoguePlugin { } return true; } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/WaterFall.java b/Server/src/main/content/region/kandarin/quest/waterfall/WaterFall.java index 467bef439..33030e29a 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/WaterFall.java +++ b/Server/src/main/content/region/kandarin/quest/waterfall/WaterFall.java @@ -1,5 +1,6 @@ package content.region.kandarin.quest.waterfall; +import content.data.Quests; import core.plugin.Initializable; import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; @@ -13,17 +14,11 @@ import core.plugin.ClassScanner; */ @Initializable public class WaterFall extends Quest { - - /** - * The name of this quest. - */ - public static final String NAME = "Waterfall"; - /** * Constructs a new {@code WaterFall} {@code Object}. */ public WaterFall() { - super("Waterfall", 65, 64, 1, 65, 0, 1, 10); + super(Quests.WATERFALL_QUEST, 65, 64, 1, 65, 0, 1, 10); } @Override diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java b/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java index 5bcac3376..2a10ebe5c 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java +++ b/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java @@ -3,6 +3,7 @@ package content.region.kandarin.quest.waterfall; import java.util.ArrayList; import java.util.List; +import content.data.Quests; import core.cache.def.impl.ItemDefinition; import core.cache.def.impl.NPCDefinition; import core.cache.def.impl.SceneryDefinition; @@ -130,7 +131,7 @@ public final class WaterfallPlugin extends OptionHandler { @Override public boolean handle(final Player player, Node node, String option) { final int id = node.getId(); - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); if (quest == null) { player.sendMessage("Error! Waterfall quest cannot be found."); return true; @@ -141,7 +142,7 @@ public final class WaterfallPlugin extends OptionHandler { player.getPulseManager().run(new Pulse(2, player) { @Override public boolean pulse() { - if ((player.getEquipment().containsAtLeastOneItem(295) || player.getInventory().contains(295, 1)) || player.getQuestRepository().isComplete("Waterfall")) { + if ((player.getEquipment().containsAtLeastOneItem(295) || player.getInventory().contains(295, 1)) || player.getQuestRepository().isComplete(Quests.WATERFALL_QUEST)) { player.getPacketDispatch().sendMessage("You walk through the door."); player.teleport(new Location(2575, 9861)); } else { @@ -425,7 +426,7 @@ public final class WaterfallPlugin extends OptionHandler { public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); Item useditem = event.getUsedItem(); - final Quest quest = player.getQuestRepository().getQuest(WaterFall.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); final Scenery object = (Scenery) event.getUsedWith(); if (useditem.getId() == ROPE.getId() && object.getId() == 1996 || object.getId() == 1997) { diff --git a/Server/src/main/content/region/kandarin/quest/whileguthixsleeps/WhileGuthixSleeps.kt b/Server/src/main/content/region/kandarin/quest/whileguthixsleeps/WhileGuthixSleeps.kt index ca348787d..10ea45b99 100644 --- a/Server/src/main/content/region/kandarin/quest/whileguthixsleeps/WhileGuthixSleeps.kt +++ b/Server/src/main/content/region/kandarin/quest/whileguthixsleeps/WhileGuthixSleeps.kt @@ -3,12 +3,11 @@ package content.region.kandarin.quest.whileguthixsleeps import core.api.getQuestStage import core.api.hasLevelStat import core.api.isQuestComplete -import core.api.rewardXP import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills -import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * While Guthix Sleeps Quest @@ -18,17 +17,14 @@ import org.rs09.consts.Items * */ //@Initializable -class WhileGuthixSleeps : Quest("While Guthix Sleeps", 161, 160, 5,5491, 0, 1, 900) { +class WhileGuthixSleeps : Quest(Quests.WHILE_GUTHIX_SLEEPS, 161, 160, 5, 5491, 0, 1, 900) { - companion object { - const val questName = "While Guthix Sleeps" - } override fun drawJournal(player: Player, stage: Int) { super.drawJournal(player, stage) var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.WHILE_GUTHIX_SLEEPS) > 0 if (!started) { line(player, "I can start this quest by speaking to !!Radimus Erkle?? in the", line++, false) @@ -44,18 +40,43 @@ class WhileGuthixSleeps : Quest("While Guthix Sleeps", 161, 160, 5,5491, 0, 1, 9 line(player, "!!Level 65 Farming??", line++, hasLevelStat(player, Skills.FARMING, 65)) line(player, "!!Level 23 Summoning??", line++, hasLevelStat(player, Skills.SUMMONING, 23)) line(player, "I also need to have completed the following quests:", line++, false) - line(player, "!!Recipe for Disaster??", line++, isQuestComplete(player, "Recipe for Disaster")) - line(player, "!!Mourning's Ends Part II - The Temple of Light??", line++, isQuestComplete(player, "Mourning's End Part II")) - line(player, "!!Swan Song??", line++, isQuestComplete(player, "Swan Song")) - line(player, "!!Zogre Flesh Eaters??", line++, isQuestComplete(player, "Zogre Flesh Eaters")) - line(player, "!!Path of Glouphrie??", line++, isQuestComplete(player, "Path of Glouphrie")) - line(player, "!!Summer's End??", line++, isQuestComplete(player, "Summer's End")) - line(player, "!!Legends' Quest??", line++, isQuestComplete(player, "Legends' Quest")) - line(player, "!!Dream Mentor??", line++, isQuestComplete(player, "Dream Mentor")) - line(player, "!!Hand in the Sand??", line++, isQuestComplete(player, "The Hand in the Sand")) - line(player, "!!Tears of Guthix??", line++, isQuestComplete(player, "Tears of Guthix")) - line(player, "!!King's Ransom??", line++, isQuestComplete(player, "King's Ransom")) - line(player, "!!Defender of Varrock??", line++, isQuestComplete(player, "Defender of Varrock")) + line( + player, + "!!Recipe for Disaster??", + line++, + isQuestComplete(player, Quests.RECIPE_FOR_DISASTER) + ) + line( + player, + "!!Mourning's Ends Part II - The Temple of Light??", + line++, + isQuestComplete(player, Quests.MOURNINGS_END_PART_II) + ) + line(player, "!!Swan Song??", line++, isQuestComplete(player, Quests.SWAN_SONG)) + line( + player, + "!!Zogre Flesh Eaters??", + line++, + isQuestComplete(player, Quests.ZOGRE_FLESH_EATERS) + ) + line(player, "!!Path of Glouphrie??", line++, isQuestComplete(player, Quests.THE_PATH_OF_GLOUPHRIE)) + line(player, "!!Summer's End??", line++, isQuestComplete(player, Quests.SUMMERS_END)) + line(player, "!!Legends' Quest??", line++, isQuestComplete(player, Quests.LEGENDS_QUEST)) + line(player, "!!Dream Mentor??", line++, isQuestComplete(player, Quests.DREAM_MENTOR)) + line( + player, + "!!Hand in the Sand??", + line++, + isQuestComplete(player, Quests.THE_HAND_IN_THE_SAND) + ) + line(player, "!!Tears of Guthix??", line++, isQuestComplete(player, Quests.TEARS_OF_GUTHIX)) + line(player, "!!King's Ransom??", line++, isQuestComplete(player, Quests.KINGS_RANSOM)) + line( + player, + "!!Defender of Varrock??", + line++, + isQuestComplete(player, Quests.DEFENDER_OF_VARROCK) + ) line(player, "!!Be eligible for entry to the Warriors' Guild??", line++) line(player, "!!Defeated Bork in the Chaos Tunnels??", line++) line(player, "!!And gain a total of 270 quest points.??", line++) @@ -68,7 +89,7 @@ class WhileGuthixSleeps : Quest("While Guthix Sleeps", 161, 160, 5,5491, 0, 1, 9 var ln = 10 super.finish(player) player.packetDispatch.sendString("You have completed While Guthix Sleeps!", 277, 4) - player.packetDispatch.sendItemZoomOnInterface(Items.LONGBOW_839,230,277,5) + player.packetDispatch.sendItemZoomOnInterface(Items.LONGBOW_839, 230, 277, 5) drawReward(player, "5 Quest Points", ln++) drawReward(player, "Lump of dragon metal.", ln++) diff --git a/Server/src/main/content/region/kandarin/seers/dialogue/SeerDialogue.kt b/Server/src/main/content/region/kandarin/seers/dialogue/SeerDialogue.kt index 7219b3e9f..c4d8a4e93 100644 --- a/Server/src/main/content/region/kandarin/seers/dialogue/SeerDialogue.kt +++ b/Server/src/main/content/region/kandarin/seers/dialogue/SeerDialogue.kt @@ -9,7 +9,6 @@ import core.api.isQuestInProgress import core.api.openDialogue import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.dialogue.IfTopic import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable @@ -17,6 +16,7 @@ import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs import core.game.dialogue.Topic +import content.data.Quests @@ -47,12 +47,12 @@ class SeerDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - val scorpionCatcherQuestStage = getQuestStage(player, "Scorpion Catcher") + val scorpionCatcherQuestStage = getQuestStage(player, Quests.SCORPION_CATCHER) when (stage) { START_DIALOGUE -> npcl(FacialExpression.NEUTRAL, "Anyway, sorry about that.").also { stage++ } START_DIALOGUE+1 -> { - if (isQuestInProgress(player, "Scorpion Catcher", 1, 99)) { + if (isQuestInProgress(player, Quests.SCORPION_CATCHER, 1, 99)) { showTopics( Topic("Talk about Scorpion Catcher.", SC_QUEST, true), Topic("Talk about Achievement Diary.", DIARY, true) diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/BatteredBookHandler.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/BatteredBookHandler.kt index 4e3854225..f46fcfd97 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/BatteredBookHandler.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/BatteredBookHandler.kt @@ -1,12 +1,12 @@ package content.region.kandarin.seers.quest.elementalworkshop import content.global.handlers.iface.BookInterface -import core.api.setAttribute import core.api.setQuestStage import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.player.Player import org.rs09.consts.Items +import content.data.Quests /** * Battered book handler for the Elemental Workshop I quest @@ -23,7 +23,7 @@ class BatteredBookHandler : InteractionListener { BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS) if (BookInterface.isLastPage(pageNum, CONTENTS.size)) { if (EWUtils.currentStage(player) == 0) { - setQuestStage(player, "Elemental Workshop I", 1) + setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_I, 1) } } return true diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt index f742d5a21..f992cb72e 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt @@ -16,6 +16,7 @@ import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.currentStag import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.tools.Log +import content.data.Quests /** * Listeners for the Elemental Workshop I quest @@ -140,7 +141,7 @@ class EWListeners : InteractionListener { sendMessage(player, "Inside you find a small, old, battered key.") replaceSlot(player, with.asItem().slot, slashedBook) addItemOrDrop(player, Items.BATTERED_KEY_2887) - setQuestStage(player, "Elemental Workshop I", 3) + setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_I, 3) return true } } @@ -177,8 +178,8 @@ class EWListeners : InteractionListener { return@on true } // Increment quest stage - if (getQuestStage(player, "Elemental Workshop I") < 5) { - setQuestStage(player, "Elemental Workshop I", 5) + if (getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_I) < 5) { + setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_I, 5) } // Allow player through the wall sendMessage(player, "You use the battered key to open the doors.") @@ -200,7 +201,7 @@ class EWListeners : InteractionListener { sendPlayerDialogue(player, "Now to explore this area thoroughly, to find what " + "forgotten secrets it contains.", core.game.dialogue.FacialExpression.NEUTRAL) - setQuestStage(player, "Elemental Workshop I", 7) + setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_I, 7) } return@on true } @@ -289,8 +290,8 @@ class EWListeners : InteractionListener { sendMessage(player, "Following the instructions in the book you make an elemental shield.") } // Check to see if the quest is completed, if not, complete the quest - if (!player.questRepository.getQuest("Elemental Workshop I").isCompleted(player)) { - player.questRepository.getQuest("Elemental Workshop I").finish(player) + if (!player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).isCompleted(player)) { + player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).finish(player) } return@onUseWith true } diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWUtils.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWUtils.kt index 142f10c69..a2629fcb1 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWUtils.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWUtils.kt @@ -4,8 +4,8 @@ import content.global.handlers.iface.BookLine import content.global.handlers.iface.Page import content.global.handlers.iface.PageSet import core.game.node.entity.player.Player -import org.rs09.consts.Vars import core.api.* +import content.data.Quests /** * Utils for the Elemental Workshop I quest @@ -102,6 +102,6 @@ object EWUtils { } fun currentStage(player: Player): Int { - return player.questRepository.getStage("Elemental Workshop I") + return player.questRepository.getStage(Quests.ELEMENTAL_WORKSHOP_I) } } diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/ElementalWorkshopQuest.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/ElementalWorkshopQuest.kt index 397faad13..cb7ea7803 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/ElementalWorkshopQuest.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/ElementalWorkshopQuest.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import org.rs09.consts.Items import org.rs09.consts.Vars import core.game.system.command.Privilege +import content.data.Quests /** * Elemental Workshop I @@ -29,7 +30,7 @@ import core.game.system.command.Privilege * @author Woah, with love */ @Initializable -class ElementalWorkshopQuest : Quest("Elemental Workshop I", 52, 51, 1), Commands { +class ElementalWorkshopQuest : Quest(Quests.ELEMENTAL_WORKSHOP_I, 52, 51, 1), Commands { override fun newInstance(`object`: Any?): Quest { return this diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ArheinMCDialogue.kt b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ArheinMCDialogue.kt index c59014ec4..1309b550f 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ArheinMCDialogue.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ArheinMCDialogue.kt @@ -4,6 +4,7 @@ import core.game.dialogue.FacialExpression import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests /** * @author lila @@ -19,7 +20,7 @@ class ArheinMCDialogue (val questStage: Int) : DialogueFile() { START_DIALOGUE -> playerl(FacialExpression.NEUTRAL, "Can you drop me off on the way down please?").also { stage++ } 1 -> { npcl(FacialExpression.ANNOYED,"I don't think Sir Mordred would like that. He wants as few outsiders visiting as possible. I wouldn't want to lose his business.") - val quest = player!!.questRepository.getQuest("Merlin's Crystal") + val quest = player!!.questRepository.getQuest(Quests.MERLINS_CRYSTAL) player!!.questRepository.setStage(quest, 40) stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/BeggarDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/BeggarDialogue.java index 0c422017d..286b845f1 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/BeggarDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/BeggarDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for king arthur. @@ -48,7 +49,7 @@ public final class BeggarDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); switch (stage) { case 1: if (quest.getStage(player) == 60 && player.getAttribute("beggar_npc") != null) { diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java index 003add8ff..46b402ed3 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java @@ -11,6 +11,7 @@ import core.game.node.item.Item; import core.plugin.Plugin; import core.game.shops.Shops; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the dialogue plugin used to handle the candle maker npc. @@ -56,7 +57,7 @@ public final class CandleMakerDialogue extends DialoguePlugin { @Override public boolean handle(Player player, Node node, String option) { NPC npc = node.asNpc(); - Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(player) > 60) { Shops.openId(player, 56); } else { @@ -78,7 +79,7 @@ public final class CandleMakerDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); switch (stage) { case 2: if (quest.getStage(player) == 50 || quest.getStage(player) == 60) {// the player has defeated mordred and learned about the black candles diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/KingArthurDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/KingArthurDialogue.java index 694cc4c04..ea84952e5 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/KingArthurDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/KingArthurDialogue.java @@ -8,6 +8,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the dialogue plugin used for king arthur. @@ -56,7 +57,7 @@ public final class KingArthurDialogue extends DialoguePlugin { stage = 80; return true; } else { - Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(player) == 99) { player("I have freed Merlin from his crystal!"); stage = 900; @@ -80,7 +81,7 @@ public final class KingArthurDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); switch (stage) { case 900: end(); diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystal.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystal.java index 1c2a16978..15a6c5ce4 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystal.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystal.java @@ -3,8 +3,8 @@ package content.region.kandarin.seers.quest.merlinsquest; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; -import content.region.kandarin.seers.quest.merlinsquest.TheLadyOfTheLake; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the merlin's crystal quest. @@ -17,7 +17,7 @@ public final class MerlinCrystal extends Quest { * Constructs a new {@code MerlinCrystal} {@code Object}. */ public MerlinCrystal() { - super("Merlin's Crystal", 87, 86, 6, 14, 0, 1, 7); + super(Quests.MERLINS_CRYSTAL, 87, 86, 6, 14, 0, 1, 7); } @Override diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalOptionPlugin.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalOptionPlugin.java index 66a51581b..82a53c48c 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalOptionPlugin.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalOptionPlugin.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.scenery.Scenery; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the quest node plugin handler. @@ -23,7 +24,7 @@ public class MerlinCrystalOptionPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); int id = node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); switch (id) { case 247: diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalPlugin.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalPlugin.java index ce2695d38..e90ecbfd1 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalPlugin.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinCrystalPlugin.java @@ -1,6 +1,5 @@ package content.region.kandarin.seers.quest.merlinsquest; -import core.cache.def.impl.ItemDefinition; import core.cache.def.impl.SceneryDefinition; import core.game.activity.ActivityManager; import core.game.activity.CutscenePlugin; @@ -9,13 +8,10 @@ import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; import core.game.global.action.ClimbActionHandler; import core.game.global.action.DoorActionHandler; -import core.game.global.action.DropListener; import core.game.interaction.NodeUsageEvent; import core.game.interaction.OptionHandler; import core.game.interaction.UseWithHandler; import core.game.node.Node; -import core.game.node.entity.Entity; -import core.game.node.entity.impl.ForceMovement; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -24,12 +20,12 @@ import core.game.node.scenery.Scenery; import core.game.node.scenery.SceneryBuilder; import core.game.system.task.Pulse; import core.game.world.GameWorld; -import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Plugin; import core.plugin.ClassScanner; +import content.data.Quests; /** * Handles the Merlin's Crystal Dialogue/Interactions. @@ -73,7 +69,7 @@ public final class MerlinCrystalPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); final int id = node instanceof Item ? ((Item) node).getId() : node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); switch (id) { case 62: @@ -178,7 +174,7 @@ public final class MerlinCrystalPlugin extends OptionHandler { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(player) == 99) { npc = (NPC) args[0]; npc("Thank you! Thank you! Thank you!"); @@ -328,8 +324,8 @@ public final class MerlinCrystalPlugin extends OptionHandler { if (p != null) { p.stop(false); } - if (player.getQuestRepository().getQuest("Merlin's Crystal").getStage(player) == 30) { - player.getQuestRepository().getQuest("Merlin's Crystal").setStage(player, 40); + if (player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL).getStage(player) == 30) { + player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL).setStage(player, 40); } player.unlock(); player.getProperties().setTeleportLocation(Location.create(2778, 3401, 0)); @@ -449,7 +445,7 @@ public final class MerlinCrystalPlugin extends OptionHandler { @Override public boolean isHidden(final Player player) { - if (player.getQuestRepository().getQuest("Merlin's Crystal").getStage(player) == 60 && this.getAttribute("beggar_owner", "").equals(player.getUsername())) { + if (player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL).getStage(player) == 60 && this.getAttribute("beggar_owner", "").equals(player.getUsername())) { return false; } return true; diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinListeners.kt b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinListeners.kt index f7a5e87ad..3a24ee325 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinListeners.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/MerlinListeners.kt @@ -8,13 +8,14 @@ import core.game.global.action.DropListener import core.game.node.entity.npc.NPC import core.game.node.entity.impl.ForceMovement import org.rs09.consts.Items +import content.data.Quests class MerlinListeners : InteractionListener { private val BONE_DROP_LOCATION = Location(2780, 3515, 0) override fun defineListeners() { on (Items.BAT_BONES_530, IntType.ITEM, "drop") { player, node -> - val merlinStage = getQuestStage(player, "Merlin's Crystal") + val merlinStage = getQuestStage(player, Quests.MERLINS_CRYSTAL) var doingQuest = player.location == BONE_DROP_LOCATION && merlinStage == 80 var hasAuxiliaryRequirements = inInventory(player, Items.LIT_BLACK_CANDLE_32) && getAttribute(player, "thrantax_npc", null) == null diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirGawainDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirGawainDialogue.java index c94ab7d0b..0f3d5b858 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirGawainDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirGawainDialogue.java @@ -4,6 +4,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the dialogue plugin used for Sir Gawain. @@ -40,7 +41,7 @@ public final class SirGawainDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); npc("Good day to you " + (player.isMale() ? "sir" : "madam") + "!"); stage = 0; diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirKayDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirKayDialogue.java index 14f4bd3ca..594645e0d 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirKayDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirKayDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the dialogue plugin used for Sir Kay. @@ -42,7 +43,7 @@ public final class SirKayDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); options("Hello.", "Talk about achievement diary."); stage = 0; diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLancelotDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLancelotDialogue.java index 09b3eb285..b8d5b8d8a 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLancelotDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLancelotDialogue.java @@ -4,6 +4,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the dialogue plugin used for king arthur. @@ -42,7 +43,7 @@ public final class SirLancelotDialogue extends DialoguePlugin { npc = (NPC) args[0]; npc("Greetings! I am Sir Lancelot, the greatest Knight in the", "land! What do you want?"); - quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); stage = 0; return true; } diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLucan.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLucan.java index 9ce08250b..2732d5667 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLucan.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirLucan.java @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Handles the dialogue for Sir Lucan @@ -42,7 +43,7 @@ public class SirLucan extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(player) == 100) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Congratulations on freeing Merlin!"); stage = 20; diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirMordredNPC.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirMordredNPC.java index c7ec62b1c..6065a1b2e 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirMordredNPC.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirMordredNPC.java @@ -9,6 +9,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.update.flag.context.Graphics; +import content.data.Quests; /** * Handles Sir Mordred @@ -50,7 +51,7 @@ public class SirMordredNPC extends AbstractNPC { super.getSkills().setLifepoints(50); if (killer != null && killer.isPlayer()) { final Player p = ((Player) killer); - Quest quest = p.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = p.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(p) == 40) { quest.setStage(p, 50); p.getQuestRepository().syncronizeTab(p); diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirPalomedes.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirPalomedes.java index 61420baa8..50b4e2de2 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirPalomedes.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/SirPalomedes.java @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Handles the SirPalomedes dialogue. @@ -41,7 +42,7 @@ public class SirPalomedes extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); if (quest.getStage(player) == 100) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Congratulations on freeing Merlin!"); stage = 20; diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/TheLadyOfTheLake.kt b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/TheLadyOfTheLake.kt index 625bf6a7a..e1ed69c03 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/TheLadyOfTheLake.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/TheLadyOfTheLake.kt @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.diary.DiaryType import core.game.node.item.Item import org.rs09.consts.Items +import content.data.Quests /** * Handles the LadyOfTheLake dialogue. @@ -35,7 +36,7 @@ class TheLadyOfTheLake(player: Player? = null) : DialoguePlugin(player) { } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - val quest = player.questRepository.getQuest("Merlin's Crystal") + val quest = player.questRepository.getQuest(Quests.MERLINS_CRYSTAL) when (stage) { 0 -> options("Who are you?", "I seek the sword Excalibur.", "Good day.").also { stage = 1 } 1 -> when (buttonId) { diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxDialogue.java index fd9b4a68e..d30d76d33 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxDialogue.java @@ -6,6 +6,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Handles the thrantax dialogue. @@ -41,7 +42,7 @@ public class ThrantaxDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); + final Quest quest = player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL); switch (stage) { case 0: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Now what were those magic words again?"); diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxNPC.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxNPC.java index d96b52f7c..16efc79b6 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxNPC.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/ThrantaxNPC.java @@ -4,6 +4,7 @@ import core.game.node.entity.Entity; import core.game.node.entity.player.Player; import core.game.node.entity.npc.NPC; import core.game.world.map.Location; +import content.data.Quests; /** * Handles the thrantax npc. @@ -28,7 +29,7 @@ public class ThrantaxNPC extends NPC { @Override public boolean isHidden(final Player player) { - if (player.getQuestRepository().getQuest("Merlin's Crystal").getStage(player) == 80 && this.getAttribute("thrantax_owner", "").equals(player.getUsername())) { + if (player.getQuestRepository().getQuest(Quests.MERLINS_CRYSTAL).getStage(player) == 80 && this.getAttribute("thrantax_owner", "").equals(player.getUsername())) { return false; } return true; diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt index baeaea137..9b6399d99 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/BaileyDialogueFile.kt @@ -1,20 +1,15 @@ package content.region.kandarin.witchhaven.quest.seaslug +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.world.map.Location -import core.plugin.Initializable import org.rs09.consts.Items -import org.rs09.consts.NPCs class BaileyDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0,1,2,3,4) + b.onQuestStages(Quests.SEA_SLUG, 0, 1, 2, 3, 4) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.SCARED, "What? Who are you? Come inside quickly!") .npcl(FacialExpression.SCARED, "What are you doing here?") @@ -32,7 +27,7 @@ class BaileyDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.SCARED, "That's okay. I just can't shake the feeling that this is the start of something... Terrible.") .end() - b.onQuestStages(SeaSlug.questName, 5) + b.onQuestStages(Quests.SEA_SLUG, 5) .playerl("Hello.") .npcl(FacialExpression.EXTREMELY_SHOCKED, "Oh, thank the gods it's you. They've all gone mad I tell you, one of the fishermen tried to throw me into the sea!") .playerl("They're all being controlled by the sea slugs.") @@ -46,13 +41,13 @@ class BaileyDialogueFile : DialogueBuilderFile() { .iteml(Items.UNLIT_TORCH_596, "Bailey gives you a torch.") .npcl("I doubt the fishermen will come near you if you can get this torch lit. The only problem is all the wood and flint are damp... I can't light a thing!") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 5) { - setQuestStage(player, SeaSlug.questName, 6) + if(getQuestStage(player, Quests.SEA_SLUG) == 5) { + setQuestStage(player, Quests.SEA_SLUG, 6) } } // We aren't going to give you a spare torch. Go get an unlit torch somewhere else. - b.onQuestStages(SeaSlug.questName, 6,7,8) + b.onQuestStages(Quests.SEA_SLUG, 6, 7, 8) .playerl("Hello.") .npcl("Oh, thank the gods it's you. They've all gone mad I tell you, one of the fishermen tried to throw me into the sea!") .playerl("They're all being controlled by the sea slugs.") @@ -62,7 +57,7 @@ class BaileyDialogueFile : DialogueBuilderFile() { .npcl("I doubt the fishermen will come near you if you can get this torch lit. The only problem is all the wood and flint are damp... I can't light a thing!") .end() - b.onQuestStages(SeaSlug.questName, 9,10,100) + b.onQuestStages(Quests.SEA_SLUG, 9, 10, 100) .playerl("I've managed to light the torch.") .npcl("Well done traveller, you'd better get Kennith out of here soon. The fishermen are becoming stranger by the minute, and they keep pulling up those blasted sea slugs.") .playerl("Don't worry I'm working on it.") diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt index 072778cb0..bd6892832 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/CarolineDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.kandarin.witchhaven.quest.seaslug +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -8,7 +9,7 @@ import core.game.node.entity.skill.Skills class CarolineDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0) + b.onQuestStages(Quests.SEA_SLUG, 0) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.SAD, "Is there any chance you could help me?") .playerl(FacialExpression.THINKING, "What's wrong?") @@ -32,8 +33,8 @@ class CarolineDialogueFile : DialogueBuilderFile() { .playerl("Ok, I'll go and see if they're ok.") .npcl("I'll reward you for your time. It'll give me peace of mind to know Kennith and my husband, Kent, are safe.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 0) { - setQuestStage(player, SeaSlug.questName, 1) + if(getQuestStage(player, Quests.SEA_SLUG) == 0) { + setQuestStage(player, Quests.SEA_SLUG, 1) } } optionBuilder.option_playerl("I'm sorry, I'm too busy.") @@ -43,7 +44,7 @@ class CarolineDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(SeaSlug.questName, 1,2,3,4,5,6,7,8,9,10) + b.onQuestStages(Quests.SEA_SLUG, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .playerl("Hello Caroline.") .npcl("Brave @name, have you any news about my son and his father?") .playerl("I'm working on it now Caroline.") @@ -51,7 +52,7 @@ class CarolineDialogueFile : DialogueBuilderFile() { .playerl("I'll do my best.") .end() - b.onQuestStages(SeaSlug.questName, 11) + b.onQuestStages(Quests.SEA_SLUG, 11) .playerl("Hello.") .npcl("Brave @name, you've returned!") .npcl("Kennith told me about the strange goings-on at the platform. I had no idea it was so serious.") @@ -62,8 +63,8 @@ class CarolineDialogueFile : DialogueBuilderFile() { .playerl(FacialExpression.FRIENDLY, "Thanks!") .npcl(FacialExpression.FRIENDLY, "Thank you. Take care of yourself @name.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 11) { - finishQuest(player, SeaSlug.questName) + if(getQuestStage(player, Quests.SEA_SLUG) == 11) { + finishQuest(player, Quests.SEA_SLUG) } } } diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt index 4706357fe..559ce7335 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartDialogueFile.kt @@ -1,22 +1,15 @@ package content.region.kandarin.witchhaven.quest.seaslug -import content.region.asgarnia.falador.quest.recruitmentdrive.RecruitmentDrive +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.world.map.Location -import core.plugin.Initializable -import org.rs09.consts.Components import org.rs09.consts.Items -import org.rs09.consts.NPCs class HolgartDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0) + b.onQuestStages(Quests.SEA_SLUG, 0) .playerl(FacialExpression.FRIENDLY, "Hello.") .npcl(FacialExpression.FRIENDLY, "Well hello @g[m'lad,m'laddy]. Beautiful day isn't it?") .playerl("Not bad I suppose.") @@ -24,7 +17,7 @@ class HolgartDialogueFile : DialogueBuilderFile() { .playerl(FacialExpression.THINKING, "Hmm... lovely...") .end() - b.onQuestStages(SeaSlug.questName, 1) + b.onQuestStages(Quests.SEA_SLUG, 1) .npcl(FacialExpression.FRIENDLY, "Hello, m'hearty.") .playerl("I would like a ride on your boat to the fishing platform.") .npcl(FacialExpression.SAD, "I'm afraid it isn't sea worthy, it's full of holes. To fill the holes I'll need some swamp paste.") @@ -39,8 +32,8 @@ class HolgartDialogueFile : DialogueBuilderFile() { .npcl("If you make me some swamp paste I'll give you a ride in my boat.") .playerl("I'll see what I can do.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 1) { - setQuestStage(player, SeaSlug.questName, 2) + if(getQuestStage(player, Quests.SEA_SLUG) == 1) { + setQuestStage(player, Quests.SEA_SLUG, 2) } } branch.onValue(1) @@ -53,13 +46,13 @@ class HolgartDialogueFile : DialogueBuilderFile() { .iteml(Items.SWAMP_PASTE_1941, "You give Holgart the swamp paste.") // Cutscene .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 1) { - setQuestStage(player, SeaSlug.questName, 3) + if(getQuestStage(player, Quests.SEA_SLUG) == 1) { + setQuestStage(player, Quests.SEA_SLUG, 3) } } } - b.onQuestStages(SeaSlug.questName, 2) + b.onQuestStages(Quests.SEA_SLUG, 2) .playerl(FacialExpression.FRIENDLY, "Hello.") .npcl("Hello, m'hearty. Did you manage to make some swamp paste?") .branch { player -> @@ -79,15 +72,15 @@ class HolgartDialogueFile : DialogueBuilderFile() { .iteml(Items.SWAMP_PASTE_1941, "You give Holgart the swamp paste.") // Cutscene .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 2) { - setQuestStage(player, SeaSlug.questName, 3) + if(getQuestStage(player, Quests.SEA_SLUG) == 2) { + setQuestStage(player, Quests.SEA_SLUG, 3) } } } - b.onQuestStages(SeaSlug.questName, 3,4,5,6,7,8,9,10,11,100) + b.onQuestStages(Quests.SEA_SLUG, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100) .playerl(FacialExpression.FRIENDLY, "Hello, Holgart.") .npcl("Hello again land lover. There's some strange goings on, on that platform, I tell you.") .options().let { optionBuilder -> diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt index 513c07456..49ab8c4ab 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartIslandDialogueFile.kt @@ -1,26 +1,19 @@ package content.region.kandarin.witchhaven.quest.seaslug -import core.api.* +import content.data.Quests import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.world.map.Location -import core.plugin.Initializable -import org.rs09.consts.Items -import org.rs09.consts.NPCs class HolgartIslandDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0,1,2,3,5,6,7,8,9,10,11,100) + b.onQuestStages(Quests.SEA_SLUG, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 100) .playerl("We'd better get back to the platform so we can see what's going on.") .npcl(FacialExpression.SUSPICIOUS, "You're right. It all sounds pretty creepy.") .endWith() { df, player -> SeaSlugListeners.seaslugBoatTravel(player, 3) } - b.onQuestStages(SeaSlug.questName, 4) + b.onQuestStages(Quests.SEA_SLUG, 4) .playerl("Where are we?") .npc("Someway off mainland still. You'd better see if me old", "matey's okay.") .end() diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt index 8bd93bfe9..f9678899d 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/HolgartPlatformDialogueFile.kt @@ -1,13 +1,13 @@ package content.region.kandarin.witchhaven.quest.seaslug -import core.api.* +import content.data.Quests import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile import core.game.dialogue.FacialExpression class HolgartPlatformDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0,1,2,3,5,6,7,8,9,10,100) + b.onQuestStages(Quests.SEA_SLUG, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 100) .playerl(FacialExpression.FRIENDLY, "Hey, Holgart.") .npcl("Have you had enough of this place yet? It's really starting to scare me.") .options().let { optionBuilder -> @@ -20,7 +20,7 @@ class HolgartPlatformDialogueFile : DialogueBuilderFile() { .end() } - b.onQuestStages(SeaSlug.questName, 4) + b.onQuestStages(Quests.SEA_SLUG, 4) .playerl("Holgart, something strange is going on here.") .npcl("You're telling me, none of the sailors seem to remember who I am.") .playerl("Apparently Kennith's father left for help a couple of days ago.") @@ -29,7 +29,7 @@ class HolgartPlatformDialogueFile : DialogueBuilderFile() { SeaSlugListeners.seaslugBoatTravel(player, 2) } - b.onQuestStages(SeaSlug.questName, 11) + b.onQuestStages(Quests.SEA_SLUG, 11) .playerl("Did you get the kid back to shore?") .npcl("Yes, he's safe and sound with his parents. Your turn to return to land now adventurer.") .playerl("Looking forward to it.") diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt index f67bfbe42..dc4b76631 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt @@ -1,20 +1,14 @@ package content.region.kandarin.witchhaven.quest.seaslug +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.world.map.Location -import core.plugin.Initializable -import org.rs09.consts.Items -import org.rs09.consts.NPCs class KennithDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0,1,2,3) + b.onQuestStages(Quests.SEA_SLUG, 0, 1, 2, 3) .playerl(FacialExpression.THINKING, "Are you okay young one?") .npcl(FacialExpression.CHILD_SAD, "No, I want daddy!") .playerl("Where is your father?") @@ -22,17 +16,17 @@ class KennithDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.CHILD_SAD, "The nasty fishermen tried to throw me and daddy into the sea. So he told me to hide here.") .playerl("That's good advice, you stay here and I'll go try and find your father.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 3) { - setQuestStage(player, SeaSlug.questName, 4) + if(getQuestStage(player, Quests.SEA_SLUG) == 3) { + setQuestStage(player, Quests.SEA_SLUG, 4) } } - b.onQuestStages(SeaSlug.questName, 4,5,6) + b.onQuestStages(Quests.SEA_SLUG, 4, 5, 6) .playerl(FacialExpression.THINKING, "Are you okay?") .npcl(FacialExpression.CHILD_SAD, "I want to see daddy!") .playerl("I'm working on it.") .end() - b.onQuestStages(SeaSlug.questName, 7) + b.onQuestStages(Quests.SEA_SLUG, 7) .playerl("Hello Kennith, are you okay?") .npcl(FacialExpression.CHILD_SAD, "No, I want my daddy.") .playerl("You'll be able to see him soon. First we need to get you back to land, come with me to the boat.") @@ -41,16 +35,16 @@ class KennithDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.CHILD_SHOCKED, "I'm scared of those nasty sea slugs. I won't go near them.") .playerl("Okay, you wait here and I'll go figure another way to get you out.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 7) { - setQuestStage(player, SeaSlug.questName, 8) + if(getQuestStage(player, Quests.SEA_SLUG) == 7) { + setQuestStage(player, Quests.SEA_SLUG, 8) } } - b.onQuestStages(SeaSlug.questName, 8) + b.onQuestStages(Quests.SEA_SLUG, 8) // This stage is unfortunately left out. You can't interact with Kennith authentically. .end() - b.onQuestStages(SeaSlug.questName, 9) + b.onQuestStages(Quests.SEA_SLUG, 9) .playerl("Kennith, I've made an opening in the wall. You can come out through there.") .npcl(FacialExpression.CHILD_THINKING, "Are there any sea slugs on the other side?") .playerl("Not one.") @@ -58,16 +52,16 @@ class KennithDialogueFile : DialogueBuilderFile() { .playerl("I'll figure that out in a moment.") .npcl(FacialExpression.CHILD_NORMAL, "Ok, when you have I'll come out.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 9) { - setQuestStage(player, SeaSlug.questName, 10) + if(getQuestStage(player, Quests.SEA_SLUG) == 9) { + setQuestStage(player, Quests.SEA_SLUG, 10) } } - b.onQuestStages(SeaSlug.questName, 10) + b.onQuestStages(Quests.SEA_SLUG, 10) // This stage is also unfortunately left out. You can't interact with Kennith authentically. .end() - b.onQuestStages(SeaSlug.questName, 11,100) + b.onQuestStages(Quests.SEA_SLUG, 11, 100) // Kennith is varp swapped out, so is no longer here. .end() diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt index 4c0174d2a..1e9fee52c 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KentDialogueFile.kt @@ -1,20 +1,14 @@ package content.region.kandarin.witchhaven.quest.seaslug +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills -import core.game.world.map.Location -import core.plugin.Initializable -import org.rs09.consts.Items -import org.rs09.consts.NPCs class KentDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(SeaSlug.questName, 0,1,2,3,4,5,6) + b.onQuestStages(Quests.SEA_SLUG, 0, 1, 2, 3, 4, 5, 6) .npcl("Oh thank Saradomin! I thought I'd be left out here forever.") .playerl("Your wife sent me out to find you and your boy. Kennith's fine by the way, he's on the platform.") .npcl("I knew the row boat wasn't sea worthy. I couldn't risk bringing him along but you must get him off that platform.") @@ -33,12 +27,12 @@ class KentDialogueFile : DialogueBuilderFile() { .npcl("A few more minutes and that thing would have full control of your body.") .playerl(FacialExpression.EXTREMELY_SHOCKED, "Yuck! Thanks Kent.") .endWith() { df, player -> - if(getQuestStage(player, SeaSlug.questName) == 4) { - setQuestStage(player, SeaSlug.questName, 5) + if(getQuestStage(player, Quests.SEA_SLUG) == 4) { + setQuestStage(player, Quests.SEA_SLUG, 5) } } - b.onQuestStages(SeaSlug.questName, 5,6,7,8,9,10,11,100) + b.onQuestStages(Quests.SEA_SLUG, 5, 6, 7, 8, 9, 10, 11, 100) .playerl("Hello.") .npcl("Oh my, I must get back to shore.") .end() diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt index 2bce4e52c..ef3424233 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlug.kt @@ -1,6 +1,6 @@ package content.region.kandarin.witchhaven.quest.seaslug -import content.region.morytania.quest.creatureoffenkenstrain.CreatureOfFenkenstrain +import content.data.Quests import core.api.* import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.player.Player @@ -22,10 +22,9 @@ import org.rs09.consts.Items * https://www.youtube.com/watch?v=VR91Rbyuou4 (This has many other unvisited paths) */ @Initializable -class SeaSlug : Quest("Sea Slug", 109, 108, 1,159, 0, 1, 12) { +class SeaSlug : Quest(Quests.SEA_SLUG, 109, 108, 1,159, 0, 1, 12) { companion object { - const val questName = "Sea Slug" const val questVarp = 159 } override fun drawJournal(player: Player, stage: Int) { @@ -33,7 +32,7 @@ class SeaSlug : Quest("Sea Slug", 109, 108, 1,159, 0, 1, 12) { var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.SEA_SLUG) > 0 if (!started) { line(player, "I can start this quest by speaking to !!Caroline?? who is !!East??", line++, false) @@ -174,10 +173,10 @@ class SeaSlug : Quest("Sea Slug", 109, 108, 1,159, 0, 1, 12) { override fun updateVarps(player: Player) { // The quest stages are perfectly aligned with the varp since the varp controls npcs and sceneries - if (getQuestStage(player, questName) >= 12) { + if (getQuestStage(player, Quests.SEA_SLUG) >= 12) { setVarp(player, questVarp, 12, true) // Except for stage 100 which is varp set to 12 obviously. } else { - setVarp(player, questVarp, getQuestStage(player, questName), true) + setVarp(player, questVarp, getQuestStage(player, Quests.SEA_SLUG), true) } } diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt index 85c2838ee..62d8ceb11 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt @@ -1,5 +1,6 @@ package content.region.kandarin.witchhaven.quest.seaslug +import content.data.Quests import core.api.* import core.game.global.action.ClimbActionHandler import core.game.interaction.IntType @@ -96,9 +97,9 @@ class SeaSlugListeners : InteractionListener { on(Scenery.LADDER_18324, IntType.SCENERY, "climb-up") { player, _ -> - if (getQuestStage(player, SeaSlug.questName) in 5..6) { - if (getQuestStage(player, SeaSlug.questName) == 6 && inInventory(player, Items.LIT_TORCH_594)) { - setQuestStage(player, SeaSlug.questName, 7) + if (getQuestStage(player, Quests.SEA_SLUG) in 5..6) { + if (getQuestStage(player, Quests.SEA_SLUG) == 6 && inInventory(player, Items.LIT_TORCH_594)) { + setQuestStage(player, Quests.SEA_SLUG, 7) ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location(2784, 3285, 1)) } else { animate(player, 4785) @@ -120,12 +121,12 @@ class SeaSlugListeners : InteractionListener { } on(Scenery.BADLY_REPAIRED_WALL_18381, IntType.SCENERY, "kick") { player, _ -> - if(getQuestStage(player, SeaSlug.questName) == 8) { + if(getQuestStage(player, Quests.SEA_SLUG) == 8) { animate(player, 4804) sendMessage(player, "You kick the loose panel.") sendMessage(player, "The wood is rotted and crumbles away...") sendMessage(player, "... leaving an opening big enough for Kennith to climb through.") - setQuestStage(player, SeaSlug.questName, 9) + setQuestStage(player, Quests.SEA_SLUG, 9) } else { // https://youtu.be/OM-akv7oIZ0 2:41 sendMessage(player, "You kick the loose panel...") @@ -135,13 +136,13 @@ class SeaSlugListeners : InteractionListener { } on(Scenery.CRANE_18327, IntType.SCENERY, "rotate") { player, node -> - if(getQuestStage(player, SeaSlug.questName) == 10) { + if(getQuestStage(player, Quests.SEA_SLUG) == 10) { // This is supposed to be a cutscene, but goddamn do I hate programming cutscenes. lock(player, 6) player.dialogueInterpreter.sendPlainMessage(true, "Kennith scrambles through the broken wall...") replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CRANE_18326, 6) animateScenery(node as core.game.node.scenery.Scenery, 4798) - setQuestStage(player, SeaSlug.questName, 11) + setQuestStage(player, Quests.SEA_SLUG, 11) queueScript(player, 6, QueueStrength.SOFT) { stage: Int -> sendDialogue(player, "Down below, you see Holgart collect the boy from the crane and lead him away to safety.") return@queueScript stopExecuting(player) diff --git a/Server/src/main/content/region/karamja/dialogue/CustomsOfficerDialogue.java b/Server/src/main/content/region/karamja/dialogue/CustomsOfficerDialogue.java index 164df698b..b32c1bfa0 100644 --- a/Server/src/main/content/region/karamja/dialogue/CustomsOfficerDialogue.java +++ b/Server/src/main/content/region/karamja/dialogue/CustomsOfficerDialogue.java @@ -10,6 +10,7 @@ import core.plugin.Initializable; import core.game.world.map.Location; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the dialogue plugin used to handle the customs officer. @@ -54,7 +55,7 @@ public final class CustomsOfficerDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; if (args.length > 1) { - if (player.getQuestRepository().isComplete("Pirate's Treasure")) { + if (player.getQuestRepository().isComplete(Quests.PIRATES_TREASURE)) { if (player.getInventory().containsItem(RUM)) { interpreter.sendDialogues(npc, null, "Aha, trying to smuggle rum are we?"); stage = 900; diff --git a/Server/src/main/content/region/karamja/handlers/CustomsOfficerPlugin.java b/Server/src/main/content/region/karamja/handlers/CustomsOfficerPlugin.java index 826467b8b..a29ad6b17 100644 --- a/Server/src/main/content/region/karamja/handlers/CustomsOfficerPlugin.java +++ b/Server/src/main/content/region/karamja/handlers/CustomsOfficerPlugin.java @@ -7,6 +7,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the customs officer plugin. @@ -25,7 +26,7 @@ public final class CustomsOfficerPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - if (!player.getQuestRepository().isComplete("Pirate's Treasure")) { + if (!player.getQuestRepository().isComplete(Quests.PIRATES_TREASURE)) { player.getDialogueInterpreter().open(((NPC) node).getId(), ((NPC) node)); player.getPacketDispatch().sendMessage("You may only use the Pay-fare option after completing Pirate's Treasure."); return true; diff --git a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java index 9263035b8..763b7656c 100644 --- a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java +++ b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java @@ -14,6 +14,7 @@ import core.tools.RandomFunction; import core.tools.StringUtils; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * The main type or the jungle potion quest. @@ -23,16 +24,11 @@ import static core.api.ContentAPIKt.*; @Initializable public final class JunglePotion extends Quest { - /** - * The name of the quest. - */ - public static final String NAME = "Jungle Potion"; - /** * Constructs a new {@code JunglePotion} {@code Object}. */ public JunglePotion() { - super(NAME, 81, 80, 1, 175, 0, 1, 12); + super(Quests.JUNGLE_POTION, 81, 80, 1, 175, 0, 1, 12); } @Override diff --git a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotionPlugin.java b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotionPlugin.java index d1ac8fcf9..5828060ba 100644 --- a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotionPlugin.java +++ b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotionPlugin.java @@ -1,5 +1,6 @@ package content.region.karamja.quest.junglepotion; +import content.data.Quests; import core.cache.def.impl.SceneryDefinition; import core.game.dialogue.DialogueInterpreter; import core.game.dialogue.DialoguePlugin; @@ -33,7 +34,7 @@ public final class JunglePotionPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(JunglePotion.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.JUNGLE_POTION); switch (node.getId()) { case 2584: player.getDialogueInterpreter().open("jogre_dialogue"); diff --git a/Server/src/main/content/region/karamja/quest/junglepotion/TrufitusDialogue.java b/Server/src/main/content/region/karamja/quest/junglepotion/TrufitusDialogue.java index df5e52885..267bef03c 100644 --- a/Server/src/main/content/region/karamja/quest/junglepotion/TrufitusDialogue.java +++ b/Server/src/main/content/region/karamja/quest/junglepotion/TrufitusDialogue.java @@ -1,5 +1,6 @@ package content.region.karamja.quest.junglepotion; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -48,7 +49,7 @@ public final class TrufitusDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(JunglePotion.NAME); + quest = player.getQuestRepository().getQuest(Quests.JUNGLE_POTION); switch (quest.getStage(player)) { case 0: npc("Greetings Bwana! I am Trufitus Shakaya of the Tai", "Bwo Wannai village."); diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/CrompertyDialogue.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/CrompertyDialogue.kt index a8d6ba8ea..54ec527f3 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/CrompertyDialogue.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/CrompertyDialogue.kt @@ -14,6 +14,7 @@ import core.ServerConstants import core.api.playAudio import core.game.world.GameWorld import org.rs09.consts.Sounds +import content.data.Quests @Initializable class CrompertyDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { @@ -32,7 +33,7 @@ class CrompertyDialogue(player: Player? = null) : core.game.dialogue.DialoguePlu 1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Two jobs? That's got to be tough.").also { stage = 5 } 2 -> playerl(core.game.dialogue.FacialExpression.ASKING,"So, what have you invented?").also { stage = 10 } 3 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Can you teleport me to the Rune Essence?").also { - if(player.questRepository.isComplete("Rune Mysteries")){ + if(player.questRepository.isComplete(Quests.RUNE_MYSTERIES)){ EssenceTeleport.teleport(npc,player) end() } @@ -73,7 +74,7 @@ class CrompertyDialogue(player: Player? = null) : core.game.dialogue.DialoguePlu 28 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"As you wish.").also { stage = 1000 } 30 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Okey dokey! Ready?").also { - stage = if(player.questRepository.hasStarted("Tribal Totem") && player.questRepository.getStage("Tribal Totem") < 50) { + stage = if(player.questRepository.hasStarted(Quests.TRIBAL_TOTEM) && player.questRepository.getStage(Quests.TRIBAL_TOTEM) < 50) { 35 } else 31 @@ -110,12 +111,12 @@ class CrompertyDialogue(player: Player? = null) : core.game.dialogue.DialoguePlu npc.sendChat("Dipsolum sententa sententi!") GameWorld.Pulser.submit(object : Pulse(1) { var counter = 0 - var delivered = player.questRepository.getStage("Tribal Totem") >= 25 + var delivered = player.questRepository.getStage(Quests.TRIBAL_TOTEM) >= 25 override fun pulse(): Boolean { when(counter++){ 2 -> { if(delivered) { - player.questRepository.getQuest("Tribal Totem").setStage(player,30) + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).setStage(player,30) player.properties.teleportLocation = LOCATIONS[1] } else player.properties.teleportLocation = LOCATIONS[0] diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/HoracioDialogue.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/HoracioDialogue.kt index da8cd274e..09cc8aea8 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/HoracioDialogue.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/HoracioDialogue.kt @@ -4,12 +4,13 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable class HoracioDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { - if(player.questRepository.hasStarted("Tribal Totem")){ + if(player.questRepository.hasStarted(Quests.TRIBAL_TOTEM)){ npcl(FacialExpression.HAPPY,"It's a fine day to be out in a garden, isn't it? ") stage = 5 } diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/KangaiMauDialogue.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/KangaiMauDialogue.kt index 9f35bc75f..1e72fbd22 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/KangaiMauDialogue.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/KangaiMauDialogue.kt @@ -7,15 +7,16 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class KangaiMauDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { - if(!player.questRepository.hasStarted("Tribal Totem")){ + if(!player.questRepository.hasStarted(Quests.TRIBAL_TOTEM)){ npcl(FacialExpression.HAPPY,"Hello. I'm Kangai Mau of the Rantuki Tribe.") stage = 0 - } else if(isQuestComplete(player, "Tribal Totem")) { + } else if(isQuestComplete(player, Quests.TRIBAL_TOTEM)) { npcl(FacialExpression.HAPPY, "Many greetings esteemed thief.") stage = 40 } @@ -23,7 +24,7 @@ class KangaiMauDialogue(player: Player? = null) : DialoguePlugin(player) { npcl(FacialExpression.ASKING,"Have you got our totem back?") stage = 35 } - else if(player.questRepository.hasStarted("Tribal Totem")){ + else if(player.questRepository.hasStarted(Quests.TRIBAL_TOTEM)){ npcl(FacialExpression.ASKING,"Have you got our totem back?") stage = 30 } @@ -55,8 +56,8 @@ class KangaiMauDialogue(player: Player? = null) : DialoguePlugin(player) { 20 -> playerl(FacialExpression.THINKING,"How can I find Handlemoret's house? Ardougne IS a big place...").also { stage++ } 21 -> npcl(FacialExpression.ANNOYED,"I don't know Ardougne. You tell me.").also { stage++ } 22 -> playerl(FacialExpression.HAPPY,"Ok, I will get it back.").also { - player.questRepository.getQuest("Tribal Totem").start(player) - player.questRepository.getQuest("Tribal Totem").setStage(player, 10) + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).start(player) + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).setStage(player, 10) stage++ } 23 -> npcl(FacialExpression.HAPPY,"Best of luck with that adventurer").also { stage = 1000 } @@ -66,8 +67,8 @@ class KangaiMauDialogue(player: Player? = null) : DialoguePlugin(player) { 35 -> playerl(FacialExpression.HAPPY,"Yes I have.").also { stage++ } 36 -> npcl(FacialExpression.HAPPY,"You have??? Many thanks brave adventurer! Here, have some freshly cooked Karamjan fish, caught specially by my tribe.").also { stage++ } 37 -> sendDialogue("You hand over the totem").also { - if(!isQuestComplete(player, "Tribal Totem") && removeItem(player, Items.TOTEM_1857)) { - player.questRepository.getQuest("Tribal Totem").finish(player) + if(!isQuestComplete(player, Quests.TRIBAL_TOTEM) && removeItem(player, Items.TOTEM_1857)) { + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).finish(player) stage = 1000 } else { stage = 1000 diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/RPDTEmployeeDialogue.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/RPDTEmployeeDialogue.kt index 6a4c0cbf2..2bd933011 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/RPDTEmployeeDialogue.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/RPDTEmployeeDialogue.kt @@ -5,12 +5,13 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests @Initializable class RPDTEmployeeDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npcl(FacialExpression.HAPPY,"Welcome to R.P.D.T.!") - stage = if(player.questRepository.getStage("Tribal Totem") == 20){ + stage = if(player.questRepository.getStage(Quests.TRIBAL_TOTEM) == 20){ 5 }else 0 return true @@ -22,7 +23,7 @@ class RPDTEmployeeDialogue(player: Player? = null) : DialoguePlugin(player) { 5 -> playerl(FacialExpression.ASKING,"So, when are you going to deliver this crate?").also { stage++ } 6 -> npcl(FacialExpression.THINKING,"Well... I guess we could do it now...").also { - player.questRepository.getQuest("Tribal Totem").setStage(player,25) + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).setStage(player,25) stage = 1000 } diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemListeners.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemListeners.kt index dbb4c6096..33ab1eb7e 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemListeners.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemListeners.kt @@ -8,6 +8,7 @@ import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests class TribalTotemListeners : InteractionListener { @@ -22,7 +23,7 @@ class TribalTotemListeners : InteractionListener { override fun defineListeners() { on(frontDoor, IntType.SCENERY, "Open"){ player, door -> - if(player.questRepository.getStage("Tribal Totem") >= 35){ + if(player.questRepository.getStage(Quests.TRIBAL_TOTEM) >= 35){ core.game.global.action.DoorActionHandler.handleAutowalkDoor(player,door.asScenery()) } sendMessage(player,"The door is locked shut.") @@ -30,11 +31,11 @@ class TribalTotemListeners : InteractionListener { } on(realCrate, IntType.SCENERY, "Investigate"){ player, node -> - if(player.questRepository.getStage("Tribal Totem") in 1..19 && !player.inventory.containsAtLeastOneItem(Items.ADDRESS_LABEL_1858)){ + if(player.questRepository.getStage(Quests.TRIBAL_TOTEM) in 1..19 && !player.inventory.containsAtLeastOneItem(Items.ADDRESS_LABEL_1858)){ sendDialogue(player,"There is a label on this crate. It says; To Lord Handelmort, Handelmort Mansion Ardogune.You carefully peel it off and take it.") addItem(player,Items.ADDRESS_LABEL_1858,1) } - else if(player.questRepository.getStage("Tribal Totem") in 1..19 && player.inventory.containsAtLeastOneItem(Items.ADDRESS_LABEL_1858)){ + else if(player.questRepository.getStage(Quests.TRIBAL_TOTEM) in 1..19 && player.inventory.containsAtLeastOneItem(Items.ADDRESS_LABEL_1858)){ sendDialogue(player,"There was a label on this crate, but it's gone now since you took it!") } return@on true @@ -48,7 +49,7 @@ class TribalTotemListeners : InteractionListener { onUseWith(IntType.SCENERY,label,wizCrate){ player, used, with -> sendDialogue(player,"You carefully place the delivery address label over the existing label, covering it completely.") removeItem(player,label) - player.questRepository.getQuest("Tribal Totem").setStage(player,20) + player.questRepository.getQuest(Quests.TRIBAL_TOTEM).setStage(player,20) return@onUseWith true } diff --git a/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemQuest.kt b/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemQuest.kt index ea707ce49..13c07751b 100644 --- a/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemQuest.kt +++ b/Server/src/main/content/region/karamja/quest/tribaltotem/TribalTotemQuest.kt @@ -1,7 +1,6 @@ package content.region.karamja.quest.tribaltotem import core.api.rewardXP -import core.game.content.quest.fremtrials.FremennikTrials import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills @@ -9,9 +8,10 @@ import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class TribalTotem : Quest("Tribal Totem",126,125,1,200,0,1,5){ +class TribalTotem : Quest(Quests.TRIBAL_TOTEM,126,125,1,200,0,1,5){ class SkillRequirement(val skill: Int?, val level: Int?) val requirements = arrayListOf() @@ -19,7 +19,7 @@ class TribalTotem : Quest("Tribal Totem",126,125,1,200,0,1,5){ override fun drawJournal(player: Player?, stage: Int) { super.drawJournal(player, stage) var line = 11 - val started = player?.questRepository?.getStage("Tribal Totem")!! > 0 + val started = player?.questRepository?.getStage(Quests.TRIBAL_TOTEM)!! > 0 if(!started){ line(player,"I can start this quest by speaking to !!Kangai Mau?? in",line++) diff --git a/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java b/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java index 5176ad97b..e06e1ad09 100644 --- a/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java +++ b/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java @@ -12,6 +12,7 @@ import core.plugin.Initializable; import core.plugin.Plugin; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** @@ -41,7 +42,7 @@ public class BrokenCartBypass extends OptionHandler { }); } public final boolean handle(Player player, Node node, String options){ - if (!hasRequirement(player, "Shilo Village")) + if (!hasRequirement(player, Quests.SHILO_VILLAGE)) return true; Location location = new Location(0,0); Location playerloc = new Location(player.getLocation().getX(),player.getLocation().getY()); diff --git a/Server/src/main/content/region/karamja/shilo/handlers/ShiloCart.kt b/Server/src/main/content/region/karamja/shilo/handlers/ShiloCart.kt index b432a0cf9..1b15bbcab 100644 --- a/Server/src/main/content/region/karamja/shilo/handlers/ShiloCart.kt +++ b/Server/src/main/content/region/karamja/shilo/handlers/ShiloCart.kt @@ -14,6 +14,7 @@ import core.tools.END_DIALOGUE import org.rs09.consts.Components import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests class ShiloCart : InteractionListener { @@ -67,7 +68,7 @@ class ShiloCart : InteractionListener { class CartQuickPay : DialogueFile(){ override fun handle(interfaceId: Int, buttonId: Int) { - if (!hasRequirement(player!!, "Shilo Village")) return; + if (!hasRequirement(player!!, Quests.SHILO_VILLAGE)) return; val shilo = npc?.id == 510; when (stage) { 0 -> if(inInventory(player!!,Items.COINS_995,10)){ @@ -103,7 +104,7 @@ class CartQuickPay : DialogueFile(){ class CartTravelDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { - if (!hasRequirement(player!!, "Shilo Village")) return; + if (!hasRequirement(player!!, Quests.SHILO_VILLAGE)) return; val shilo = npc?.id == 510; when (stage) { 0 -> npcl("I am offering a cart ride to " + (if (shilo) "Shilo Village" else "Brimhaven") + " if you're interested? It will cost 10 gold coins. Is that Ok?").also { stage++ } @@ -117,4 +118,4 @@ class CartTravelDialogue : DialogueFile(){ 4 -> openDialogue(player!!,CartQuickPay(),npc!!) } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/misc/entrana/dialogue/CaveMonk.java b/Server/src/main/content/region/misc/entrana/dialogue/CaveMonk.java index beaaccd03..15e7f8803 100644 --- a/Server/src/main/content/region/misc/entrana/dialogue/CaveMonk.java +++ b/Server/src/main/content/region/misc/entrana/dialogue/CaveMonk.java @@ -8,6 +8,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the dialogue plugin used for a cave monk. @@ -52,7 +53,7 @@ public final class CaveMonk extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Lost City"); + quest = player.getQuestRepository().getQuest(Quests.LOST_CITY); switch (quest.getStage(player)) { case 0: case 10: diff --git a/Server/src/main/content/region/misc/keldagrim/dialogue/KjutDialogue.kt b/Server/src/main/content/region/misc/keldagrim/dialogue/KjutDialogue.kt index d534f02fb..9cd9bdca0 100644 --- a/Server/src/main/content/region/misc/keldagrim/dialogue/KjutDialogue.kt +++ b/Server/src/main/content/region/misc/keldagrim/dialogue/KjutDialogue.kt @@ -1,5 +1,6 @@ package content.region.misc.keldagrim.dialogue +import content.data.Quests import core.api.addItemOrDrop import core.api.inInventory import core.api.isQuestComplete @@ -41,7 +42,7 @@ class KjutDialogue(player: Player? = null) : DialoguePlugin(player) { stage = END_DIALOGUE } 6 -> { - if (isQuestComplete(player, "Forgettable Tale of a Drunken Dwarf")) { + if (isQuestComplete(player, Quests.FORGETTABLE_TALE)) { npcl(FacialExpression.OLD_DEFAULT, "I thought you would know plenty!").also { stage = 14 } } else { npcl(FacialExpression.OLD_DEFAULT, "Just go out in the streets, they can't be hard to find!").also { stage = 7 } diff --git a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt index 94cd412b3..20d4d5771 100644 --- a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt +++ b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt @@ -9,18 +9,19 @@ import core.game.world.map.Location import org.rs09.consts.Components import core.game.world.GameWorld import core.api.* +import content.data.Quests object KeldagrimCartMethods { @JvmStatic fun goToKeldagrim(player: Player){ - if (!hasRequirement(player, "The Giant Dwarf")) + if (!hasRequirement(player, Quests.THE_GIANT_DWARF)) return GameWorld.Pulser.submit(TravelToKeldagrimPulse(player)) } @JvmStatic fun leaveKeldagrimTo(player: Player, dest: Location){ - if (!hasRequirement(player, "The Giant Dwarf")) + if (!hasRequirement(player, Quests.THE_GIANT_DWARF)) return GameWorld.Pulser.submit(TravelFromKeldagrimPulse(player,dest)) } diff --git a/Server/src/main/content/region/misc/miscellania/dialogue/FishmongerMiscDialogue.kt b/Server/src/main/content/region/misc/miscellania/dialogue/FishmongerMiscDialogue.kt index 9f2a60285..e2ece679c 100644 --- a/Server/src/main/content/region/misc/miscellania/dialogue/FishmongerMiscDialogue.kt +++ b/Server/src/main/content/region/misc/miscellania/dialogue/FishmongerMiscDialogue.kt @@ -7,6 +7,7 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs +import content.data.Quests /** * @author qmqz @@ -17,7 +18,7 @@ class FishmongerMiscDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Throne of Miscellania")) { + if (!isQuestComplete(player, Quests.THRONE_OF_MISCELLANIA)) { npcl(FacialExpression.FRIENDLY,"Greetings, Sir. Get your fresh fish here! I've heard that the Etceterian fish is stored in a cow shed.").also { stage = 0 } } else { npcl(FacialExpression.FRIENDLY,"Greetings, Your Highness. Have some fresh fish! I've heard that the Etceterian fish is stored in a cow shed.").also { stage = 0 } diff --git a/Server/src/main/content/region/misc/miscellania/dialogue/FlowerGirlDialogue.kt b/Server/src/main/content/region/misc/miscellania/dialogue/FlowerGirlDialogue.kt index c46e2f42e..6320d5ad1 100644 --- a/Server/src/main/content/region/misc/miscellania/dialogue/FlowerGirlDialogue.kt +++ b/Server/src/main/content/region/misc/miscellania/dialogue/FlowerGirlDialogue.kt @@ -22,7 +22,7 @@ class FlowerGirlDialogue(player: Player? = null) : DialoguePlugin(player){ //issues getting throne of miscellania status /* - when (player.questRepository.getQuest("Throne of Miscellania").isCompleted(player)) { + when (player.questRepository.getQuest(Quests.THRONE_OF_MISCELLANIA).isCompleted(player)) { true -> npc(FacialExpression.HAPPY, "Good day, Your Royal Highness.").also { stage = 1 } false -> npc(FacialExpression.NEUTRAL, "Hello.").also { stage = 1 } } @@ -39,7 +39,7 @@ class FlowerGirlDialogue(player: Player? = null) : DialoguePlugin(player){ 2 -> { /* - when (player.questRepository.getQuest("Throne of Miscellania").isCompleted(player)) { + when (player.questRepository.getQuest(Quests.THRONE_OF_MISCELLANIA).isCompleted(player)) { true -> npc(FacialExpression.HAPPY, "I'm selling flowers, 15gp for three. Would you like some, Your Highness?").also { stage++ } false -> npc(FacialExpression.NEUTRAL, "I'm selling flowers, 15gp for three. Would you like some?").also { stage++ } } diff --git a/Server/src/main/content/region/misc/tutisland/handlers/RatTutorialNPC.java b/Server/src/main/content/region/misc/tutisland/handlers/RatTutorialNPC.java index 6d7b8a5b1..56845ac8b 100644 --- a/Server/src/main/content/region/misc/tutisland/handlers/RatTutorialNPC.java +++ b/Server/src/main/content/region/misc/tutisland/handlers/RatTutorialNPC.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.game.world.map.Location; +import content.data.Quests; /** * Handles the tutorial rat npc. @@ -65,7 +66,7 @@ public class RatTutorialNPC extends AbstractNPC { } final Player p = ((Player) killer); if (killer instanceof Player) { - if (p.getQuestRepository().getQuest("Witch's Potion").isStarted(p)) { + if (p.getQuestRepository().getQuest(Quests.WITCHS_POTION).isStarted(p)) { GroundItemManager.create(new Item(300), getLocation(), p); } } diff --git a/Server/src/main/content/region/misc/zanaris/dialogue/FairyQueenDialogue.kt b/Server/src/main/content/region/misc/zanaris/dialogue/FairyQueenDialogue.kt index 0f79e6733..7154caa96 100644 --- a/Server/src/main/content/region/misc/zanaris/dialogue/FairyQueenDialogue.kt +++ b/Server/src/main/content/region/misc/zanaris/dialogue/FairyQueenDialogue.kt @@ -9,6 +9,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class FairyQueenDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -20,7 +21,7 @@ class FairyQueenDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if (!isQuestComplete(player, "Fairytale II - Cure a Queen")) { + if (!isQuestComplete(player, Quests.FAIRYTALE_II_CURE_A_QUEEN)) { options( "How do crops and such survive down here?", "What's so good about this place?" ).also { stage = START_DIALOGUE } diff --git a/Server/src/main/content/region/misc/zanaris/handlers/EvilChickenLairListener.kt b/Server/src/main/content/region/misc/zanaris/handlers/EvilChickenLairListener.kt index 319fcb7ca..bdc56980b 100644 --- a/Server/src/main/content/region/misc/zanaris/handlers/EvilChickenLairListener.kt +++ b/Server/src/main/content/region/misc/zanaris/handlers/EvilChickenLairListener.kt @@ -9,6 +9,7 @@ import core.game.world.map.Location import core.game.world.update.flag.context.Animation import org.rs09.consts.Items import org.rs09.consts.Scenery +import content.data.Quests class EvilChickenLairListener: InteractionListener { override fun defineListeners() { @@ -17,7 +18,7 @@ class EvilChickenLairListener: InteractionListener { addClimbDest(Location.create(2455, 4380, 0), Location.create(2441, 4381, 0)) onUseWith(IntType.SCENERY, Items.RAW_CHICKEN_2138, Scenery.CHICKEN_SHRINE_12093) { player, _, _ -> - if (!hasRequirement(player, "Legend's Quest")) + if (!hasRequirement(player, Quests.LEGENDS_QUEST)) return@onUseWith false if(removeItem(player,(Item(Items.RAW_CHICKEN_2138)))){ diff --git a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt index 4d40506b5..72a003a7b 100644 --- a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt +++ b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt @@ -10,6 +10,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.world.map.Location import org.rs09.consts.Items +import content.data.Quests /** * Handles interactions with fairy rings @@ -50,7 +51,7 @@ class FairyRingPlugin : InteractionListener { } private fun fairyMagic(player: Player) : Boolean { - if (!hasRequirement(player, "Fairytale I - Growing Pains")) { // should be converted to a FTP2 stage requirement once FTP2 is implemented + if (!hasRequirement(player, Quests.FAIRYTALE_I_GROWING_PAINS)) { // should be converted to a FTP2 stage requirement once FTP2 is implemented player.sendMessage("The fairy ring is inert.") return false } diff --git a/Server/src/main/content/region/misthalin/barbvillage/dialogue/PeksaDialogue.kt b/Server/src/main/content/region/misthalin/barbvillage/dialogue/PeksaDialogue.kt index 44a020873..f40c15c12 100644 --- a/Server/src/main/content/region/misthalin/barbvillage/dialogue/PeksaDialogue.kt +++ b/Server/src/main/content/region/misthalin/barbvillage/dialogue/PeksaDialogue.kt @@ -14,6 +14,7 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.NPCs +import content.data.Quests @Initializable class PeksaDialogue(player: Player? = null) : DialoguePlugin(player){ @@ -36,7 +37,7 @@ class PeksaDialogue(player: Player? = null) : DialoguePlugin(player){ showTopics( Topic("I could be, yes.", GO_SHOPPING), Topic("No, I'll pass on that.", LEAVE), - IfTopic("I've heard you have a small scorpion in your possession.", DIALOGUE_SCORPION_CATCHER, getQuestStage(player, "Scorpion Catcher") == ScorpionCatcher.QUEST_STATE_OTHER_SCORPIONS) + IfTopic("I've heard you have a small scorpion in your possession.", DIALOGUE_SCORPION_CATCHER, getQuestStage(player, Quests.SCORPION_CATCHER) == ScorpionCatcher.QUEST_STATE_OTHER_SCORPIONS) ) } @@ -50,7 +51,7 @@ class PeksaDialogue(player: Player? = null) : DialoguePlugin(player){ } DIALOGUE_SCORPION_CATCHER -> { - openDialogue(player, SCPeksaDialogue(getQuestStage(player, "Scorpion Catcher")), npc) + openDialogue(player, SCPeksaDialogue(getQuestStage(player, Quests.SCORPION_CATCHER)), npc) } } diff --git a/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt b/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt index f60eca32f..f97b20425 100644 --- a/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.digsite.dialogue +import content.data.Quests import content.region.misthalin.digsite.quest.thedigsite.TheDigSite import core.api.* import core.game.dialogue.* @@ -29,7 +30,7 @@ class ExaminerDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TheDigSite.questName, 100) + b.onQuestStages(Quests.THE_DIG_SITE, 100) .npcl(FacialExpression.HAPPY, "Hello there! My colleague tells me you helped to uncover a hidden altar to the god Zaros.") .npcl(FacialExpression.HAPPY, "A great scholar and archaeologist indeed! Good health and prosperity to you.") .options().let { optionBuilder -> @@ -43,10 +44,10 @@ class ExaminerDialogueFile : DialogueBuilderFile() { } } - b.onQuestStages(TheDigSite.questName, 6,7,8,9,10,11,12) + b.onQuestStages(Quests.THE_DIG_SITE, 6, 7, 8, 9, 10, 11, 12) .npcl(FacialExpression.FRIENDLY, "Well, what are you doing here? Get digging!") - b.onQuestStages(TheDigSite.questName, 5) + b.onQuestStages(Quests.THE_DIG_SITE, 5) .playerl(FacialExpression.FRIENDLY, "Hello.") .npcl(FacialExpression.FRIENDLY, "Ah, hello again.") .options().let { optionBuilder -> @@ -169,8 +170,8 @@ class ExaminerDialogueFile : DialogueBuilderFile() { .playerl(FacialExpression.FRIENDLY, "I can dig wherever I want now!") .npcl(FacialExpression.FRIENDLY, "Perhaps you should use your newfound skills to find an artefact on the digsite that will impress the archaeological expert.") .endWith { _, player -> - if(getQuestStage(player, TheDigSite.questName) == 5) { - setQuestStage(player, TheDigSite.questName, 6) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 5) { + setQuestStage(player, Quests.THE_DIG_SITE, 6) } openInterface(player, 444) setInterfaceText(player, player.username, 444, 5) @@ -178,7 +179,7 @@ class ExaminerDialogueFile : DialogueBuilderFile() { } - b.onQuestStages(TheDigSite.questName, 4) + b.onQuestStages(Quests.THE_DIG_SITE, 4) .playerl(FacialExpression.FRIENDLY, "Hello.") .npcl(FacialExpression.FRIENDLY, "Hello again.") .options().let { optionBuilder -> @@ -301,8 +302,8 @@ class ExaminerDialogueFile : DialogueBuilderFile() { } .npcl(FacialExpression.FRIENDLY, "You have now passed the Earth Sciences level 2 intermediate exam. Here is your certificate. Of course, you'll want to get studying for your next exam now!") .endWith { _, player -> - if(getQuestStage(player, TheDigSite.questName) == 4) { - setQuestStage(player, TheDigSite.questName, 5) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 4) { + setQuestStage(player, Quests.THE_DIG_SITE, 5) } openInterface(player, 441) setInterfaceText(player, player.username, 441, 5) @@ -310,13 +311,13 @@ class ExaminerDialogueFile : DialogueBuilderFile() { } - b.onQuestStages(TheDigSite.questName, 1,2,3) + b.onQuestStages(Quests.THE_DIG_SITE, 1, 2, 3) // This is kinda messy due to the dialogue being reused in different stages. .branch { player -> - if (getQuestStage(player, TheDigSite.questName) == 2 && !inInventory(player, Items.SEALED_LETTER_683)){ + if (getQuestStage(player, Quests.THE_DIG_SITE) == 2 && !inInventory(player, Items.SEALED_LETTER_683)){ return@branch 1 // Reuse quest stage 1 if sealed letter is not in inventory. } - return@branch getQuestStage(player, TheDigSite.questName) + return@branch getQuestStage(player, Quests.THE_DIG_SITE) } .let{ branch -> val continuePath = b.placeholder() @@ -360,8 +361,8 @@ class ExaminerDialogueFile : DialogueBuilderFile() { if (inInventory(player, Items.SEALED_LETTER_683)) { removeItem(player, Items.SEALED_LETTER_683) } - if(getQuestStage(player, TheDigSite.questName) == 2) { - setQuestStage(player, TheDigSite.questName, 3) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 2) { + setQuestStage(player, Quests.THE_DIG_SITE, 3) } } .npcl(FacialExpression.NEUTRAL, "Good, good. We will begin the exam...") @@ -481,8 +482,8 @@ class ExaminerDialogueFile : DialogueBuilderFile() { .endWith { _, player -> // Because of onQuestStages and onPredicate, changing quest stage before the dialogue finishes breaks the flow. // As every stage, the onQuestStages and onPredicate functions are ran, so changing the values will switch out the stages. - if(getQuestStage(player, TheDigSite.questName) == 3) { - setQuestStage(player, TheDigSite.questName, 4) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 3) { + setQuestStage(player, Quests.THE_DIG_SITE, 4) } openInterface(player, 440) setInterfaceText(player, player.username, 440, 5) @@ -511,8 +512,8 @@ class ExaminerDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.FRIENDLY, "He's also a very busy man, so I write the letters and he justs stamps them if he approves.") .playerl(FacialExpression.FRIENDLY, "Oh, I see. I'll ask him if he'll approve me, and bring my stamped letter back here. Thanks.") .endWith { _, player -> - if(getQuestStage(player, TheDigSite.questName) == 0) { - setQuestStage(player, TheDigSite.questName, 1) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 0) { + setQuestStage(player, Quests.THE_DIG_SITE, 1) } } optionBuilder.option_playerl("Interesting...") diff --git a/Server/src/main/content/region/misthalin/digsite/dialogue/ResearcherDialogue.kt b/Server/src/main/content/region/misthalin/digsite/dialogue/ResearcherDialogue.kt index 43001efaf..64af6e116 100644 --- a/Server/src/main/content/region/misthalin/digsite/dialogue/ResearcherDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/dialogue/ResearcherDialogue.kt @@ -1,6 +1,6 @@ package content.region.misthalin.digsite.dialogue -import content.region.misthalin.digsite.quest.thedigsite.TheDigSite +import content.data.Quests import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -13,7 +13,7 @@ import org.rs09.consts.NPCs @Initializable class ResearcherDialogue (player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if (isQuestComplete(player, TheDigSite.questName)){ + if (isQuestComplete(player, Quests.THE_DIG_SITE)){ when (stage) { START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "Hello there. What are you doing here?").also { stage++ } 1 -> playerl(FacialExpression.FRIENDLY, "Just looking around at the moment.").also { stage++ } diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertListener.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertListener.kt index cec1d1051..296e9fce0 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertListener.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertListener.kt @@ -1,10 +1,9 @@ package content.region.misthalin.digsite.quest.thedigsite -import content.region.misthalin.digsite.dialogue.ArchaeologistcalExpertUsedOnDialogueFile +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile -import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.interaction.IntType import core.game.interaction.InteractionListener @@ -109,8 +108,8 @@ class ArchaeologicalExpertListenerDialogueFile(val it: Int) : DialogueBuilderFil if (removeItem(player, Items.ANCIENT_TALISMAN_681)) { addItemOrDrop(player, Items.INVITATION_LETTER_696) } - if(getQuestStage(player, TheDigSite.questName) == 6) { - setQuestStage(player, TheDigSite.questName, 7) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 6) { + setQuestStage(player, Quests.THE_DIG_SITE, 7) } } @@ -124,8 +123,8 @@ class ArchaeologicalExpertListenerDialogueFile(val it: Int) : DialogueBuilderFil .item(Items.GOLD_BAR_2357, "The expert gives you two gold bars as payment.") .endWith { _, player -> if (removeItem(player, Items.STONE_TABLET_699)) { - if(getQuestStage(player, TheDigSite.questName) == 11) { - finishQuest(player, TheDigSite.questName) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 11) { + finishQuest(player, Quests.THE_DIG_SITE) } } } diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/DigsiteWorkmanDialogue.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/DigsiteWorkmanDialogue.kt index 054541082..38830c490 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/DigsiteWorkmanDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/DigsiteWorkmanDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.digsite.quest.thedigsite +import content.data.Quests import core.api.* import core.game.dialogue.* import core.game.interaction.IntType @@ -64,8 +65,8 @@ class DigsiteWorkmanDialogueFile : DialogueBuilderFile() { .npc(FacialExpression.FRIENDLY, "I give permission... blah de blah... err. Okay, that's all in", "order, you may use the mineshaft now. I'll hang onto", "this scroll, shall I?") .endWith { _, player -> removeItem(player, Items.INVITATION_LETTER_696) - if(getQuestStage(player, TheDigSite.questName) == 7) { - setQuestStage(player, TheDigSite.questName, 8) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 7) { + setQuestStage(player, Quests.THE_DIG_SITE, 8) } } } diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/StudentsDialogue.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/StudentsDialogue.kt index 7e0764190..5ac84d0f5 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/StudentsDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/StudentsDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.digsite.quest.thedigsite +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -28,10 +29,10 @@ class StudentGreenDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TheDigSite.questName, 6,7,8,9,10,11,12,13,100) + b.onQuestStages(Quests.THE_DIG_SITE, 6, 7, 8, 9, 10, 11, 12, 13, 100) .npcl(FacialExpression.FRIENDLY, " Oh, hi again. News of your find has spread fast; you are quite famous around here now.") - b.onQuestStages(TheDigSite.questName, 5) + b.onQuestStages(Quests.THE_DIG_SITE, 5) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I need more help with the exam.") @@ -42,7 +43,7 @@ class StudentGreenDialogueFile : DialogueBuilderFile() { setAttribute(player, TheDigSite.attributeStudentGreenExam3ObtainAnswer, true) } - b.onQuestStages(TheDigSite.questName, 4) + b.onQuestStages(Quests.THE_DIG_SITE, 4) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I need more help with the exam.") @@ -52,7 +53,7 @@ class StudentGreenDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentGreenExam2ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentGreenExam1ObtainAnswer, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentGreenExam1ObtainAnswer, false)} .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I need more help with the exam.") @@ -62,7 +63,7 @@ class StudentGreenDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentGreenExam1ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentGreenExam1Talked, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentGreenExam1Talked, false)} .branch { player -> return@branch if (inInventory(player, Items.ANIMAL_SKULL_671)) { 1 } else { 0 } }.let{ branch -> @@ -86,7 +87,7 @@ class StudentGreenDialogueFile : DialogueBuilderFile() { } return@let branch } - b.onQuestStages(TheDigSite.questName, 3) + b.onQuestStages(Quests.THE_DIG_SITE, 3) .playerl(FacialExpression.FRIENDLY, "Hello there. Can you help me with the Earth Sciences exams at all?") .npcl(FacialExpression.FRIENDLY, "Well... Maybe I will if you help me with something.") .playerl(FacialExpression.FRIENDLY, "What's that?") @@ -127,7 +128,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 5 && getAttribute(player, TheDigSite.attributeStudentPurpleExam3ObtainAnswer, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 5 && getAttribute(player, TheDigSite.attributeStudentPurpleExam3ObtainAnswer, false)} .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I am stuck on some more exam questions.") @@ -138,7 +139,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { setAttribute(player, TheDigSite.attributeStudentPurpleExam3ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 5 && getAttribute(player, TheDigSite.attributeStudentPurpleExam3Talked, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 5 && getAttribute(player, TheDigSite.attributeStudentPurpleExam3Talked, false)} .branch { player -> return@branch if (inInventory(player, Items.OPAL_1609) || inInventory(player, Items.UNCUT_OPAL_1625)) { 1 } else { 0 } }.let{ branch -> @@ -170,7 +171,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { return@let branch } - b.onQuestStages(TheDigSite.questName, 5) + b.onQuestStages(Quests.THE_DIG_SITE, 5) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "What, you want more help?") .playerl(FacialExpression.FRIENDLY, "Err... Yes please!") @@ -184,7 +185,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { setAttribute(player, TheDigSite.attributeStudentPurpleExam3Talked, true) } - b.onQuestStages(TheDigSite.questName, 4) + b.onQuestStages(Quests.THE_DIG_SITE, 4) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I am stuck on some more exam questions.") @@ -194,7 +195,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentPurpleExam2ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentPurpleExam1ObtainAnswer, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentPurpleExam1ObtainAnswer, false)} .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "I am stuck on some more exam questions.") @@ -204,7 +205,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentPurpleExam1ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentPurpleExam1Talked, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentPurpleExam1Talked, false)} .branch { player -> return@branch if (inInventory(player, Items.TEDDY_673)) { 1 } else { 0 } }.let{ branch -> @@ -229,7 +230,7 @@ class StudentPurpleDialogueFile : DialogueBuilderFile() { } return@let branch } - b.onQuestStages(TheDigSite.questName, 3) + b.onQuestStages(Quests.THE_DIG_SITE, 3) .playerl(FacialExpression.FRIENDLY, "Hello there. Can you help me with the Earth Sciences exams at all?") .npcl(FacialExpression.FRIENDLY, "I can if you help me...") .playerl(FacialExpression.FRIENDLY, "How can I do that?") @@ -266,7 +267,7 @@ class StudentBrownDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TheDigSite.questName, 5) + b.onQuestStages(Quests.THE_DIG_SITE, 5) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "There are more exam questions I'm stuck on.") @@ -277,7 +278,7 @@ class StudentBrownDialogueFile : DialogueBuilderFile() { setAttribute(player, TheDigSite.attributeStudentBrownExam3ObtainAnswer, true) } - b.onQuestStages(TheDigSite.questName, 4) + b.onQuestStages(Quests.THE_DIG_SITE, 4) .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "There are more exam questions I'm stuck on.") @@ -287,7 +288,7 @@ class StudentBrownDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentBrownExam2ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentBrownExam1ObtainAnswer, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentBrownExam1ObtainAnswer, false)} .playerl(FacialExpression.FRIENDLY, "Hello there.") .npcl(FacialExpression.FRIENDLY, "How's it going?") .playerl(FacialExpression.FRIENDLY, "There are more exam questions I'm stuck on.") @@ -297,7 +298,7 @@ class StudentBrownDialogueFile : DialogueBuilderFile() { .endWith { _, player -> setAttribute(player, TheDigSite.attributeStudentBrownExam1ObtainAnswer, true) } - b.onPredicate { player -> getQuestStage(player, TheDigSite.questName) == 3 && getAttribute(player, TheDigSite.attributeStudentBrownExam1Talked, false)} + b.onPredicate { player -> getQuestStage(player, Quests.THE_DIG_SITE) == 3 && getAttribute(player, TheDigSite.attributeStudentBrownExam1Talked, false)} .playerl(FacialExpression.FRIENDLY, "Hello there. How's the study going?") .npcl(FacialExpression.FRIENDLY, "I'm getting there. Have you found my special cup yet?") .branch { player -> @@ -319,7 +320,7 @@ class StudentBrownDialogueFile : DialogueBuilderFile() { } return@let branch } - b.onQuestStages(TheDigSite.questName, 3) + b.onQuestStages(Quests.THE_DIG_SITE, 3) .playerl(FacialExpression.FRIENDLY, "Hello there. Can you help me with the Earth Sciences exams at all?") .npcl(FacialExpression.FRIENDLY, "I can't do anything unless I find my special cup.") .playerl(FacialExpression.FRIENDLY, "Your what?") diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt index be91947b9..a32e9f6f8 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSite.kt @@ -1,12 +1,12 @@ package content.region.misthalin.digsite.quest.thedigsite -import content.region.morytania.quest.creatureoffenkenstrain.CreatureOfFenkenstrain import core.api.* import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * The Dig Site Quest @@ -29,9 +29,8 @@ import org.rs09.consts.Items * 100 - Talked to expert after showing him the STONE_TABLET_699 */ @Initializable -class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { +class TheDigSite : Quest(Quests.THE_DIG_SITE, 47, 46, 2, 131, 0, 1, 9) { companion object { - const val questName = "The Dig Site" const val attributeStudentGreenExam1Talked = "/save:quest:thedigsite-studentgreenexam1talked" const val attributeStudentGreenExam1ObtainAnswer = "/save:quest:thedigsite-studentgreenexam1obtainanswer" const val attributeStudentPurpleExam1Talked = "/save:quest:thedigsite-studentpurpleexam1talked" @@ -83,7 +82,7 @@ class TheDigSite : Quest("The Dig Site", 47, 46, 2, 131, 0, 1, 9) { var line = 11 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.THE_DIG_SITE) > 0 if(!started){ line++ diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSiteListeners.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSiteListeners.kt index c6745cf98..470451817 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSiteListeners.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/TheDigSiteListeners.kt @@ -1,5 +1,6 @@ package content.region.misthalin.digsite.quest.thedigsite +import content.data.Quests import content.global.skill.thieving.ThievingListeners import core.api.* import core.api.utils.PlayerCamera @@ -162,7 +163,7 @@ class TheDigSiteListeners : InteractionListener { return@on true } sendMessage(player, "You attempt to pick the workman's pocket...") - if (getQuestStage(player, TheDigSite.questName) == 3) { + if (getQuestStage(player, Quests.THE_DIG_SITE) == 3) { player.animator.animate(ThievingListeners.PICKPOCKET_ANIM) val rollOutcome = ThievingListeners.pickpocketRoll(player, 84.0, 240.0, workmanPickpocketingTable) if (rollOutcome != null) { @@ -363,7 +364,7 @@ class TheDigSiteListeners : InteractionListener { val level3DigRight = ZoneBorders(3370, 3437, 3377, 3442) val level3DigLeft = ZoneBorders(3350, 3404, 3357, 3412) if (level3DigRight.insideBorder(player.location) || level3DigLeft.insideBorder(player.location)) { - if (getQuestStage(player, TheDigSite.questName) >= 6) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 6) { queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> when (stage) { 0 -> { @@ -392,7 +393,7 @@ class TheDigSiteListeners : InteractionListener { val level2Dig = ZoneBorders(3350, 3424, 3363, 3430) if (level2Dig.insideBorder(player.location)) { - if (getQuestStage(player, TheDigSite.questName) >= 5) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 5) { queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> when (stage) { 0 -> { @@ -422,7 +423,7 @@ class TheDigSiteListeners : InteractionListener { val level1DigCentre = ZoneBorders(3360, 3402, 3363, 3414) val level1DigRight = ZoneBorders(3367, 3403, 3372, 3414) if (level1DigCentre.insideBorder(player.location) || level1DigRight.insideBorder(player.location)) { - if (getQuestStage(player, TheDigSite.questName) >= 4) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 4) { queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> when (stage) { 0 -> { @@ -452,7 +453,7 @@ class TheDigSiteListeners : InteractionListener { val trainingDigLeft = ZoneBorders(3352, 3396, 3357, 3400) val trainingDigRight = ZoneBorders(3367, 3397, 3372, 3400) if (trainingDigLeft.insideBorder(player.location) || trainingDigRight.insideBorder(player.location)) { - if (getQuestStage(player, TheDigSite.questName) >= 3) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 3) { queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> when (stage) { 0 -> { @@ -483,12 +484,12 @@ class TheDigSiteListeners : InteractionListener { // 8: North East Winch goes to Doug Deeping on(Scenery.WINCH_2350, SCENERY, "operate") { player, _ -> - if (getQuestStage(player, TheDigSite.questName) >= 11) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 11) { sendMessage(player, "You try to climb down the rope...") sendMessage(player, "You lower yourself into the shaft...") teleport(player, Location(3369, 9763)) sendMessage(player, "You find yourself in a cavern...") - } else if (getQuestStage(player, TheDigSite.questName) >= 8) { + } else if (getQuestStage(player, Quests.THE_DIG_SITE) >= 8) { if (getAttribute(player, TheDigSite.attributeRopeNorthEastWinch, false)) { sendMessage(player, "You try to climb down the rope...") sendMessage(player, "You lower yourself into the shaft...") @@ -520,7 +521,7 @@ class TheDigSiteListeners : InteractionListener { // 8: Tie rope to winch onUseWith(IntType.SCENERY, Items.ROPE_954, Scenery.WINCH_2350) { player, used, with -> if (removeItem(player, used)) { - if (getQuestStage(player, TheDigSite.questName) >= 8) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 8) { setAttribute(player, TheDigSite.attributeRopeNorthEastWinch, true) sendMessage(player, "You tie the rope to the bucket.") } else { @@ -545,12 +546,12 @@ class TheDigSiteListeners : InteractionListener { // 8: West Winch goes to Skeletons, Explosion and Stone Tablet on(Scenery.WINCH_2351, SCENERY, "operate") { player, _ -> - if (getQuestStage(player, TheDigSite.questName) >= 11) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 11) { sendMessage(player, "You try to climb down the rope...") sendMessage(player, "You lower yourself into the shaft...") teleport(player, Location(3352, 9753)) sendMessage(player, "You find yourself in a cavern...") - } else if (getQuestStage(player, TheDigSite.questName) >= 8) { + } else if (getQuestStage(player, Quests.THE_DIG_SITE) >= 8) { if (getAttribute(player, TheDigSite.attributeRopeWestWinch, false)) { sendMessage(player, "You try to climb down the rope...") sendMessage(player, "You lower yourself into the shaft...") @@ -581,7 +582,7 @@ class TheDigSiteListeners : InteractionListener { // 8: Tie rope to winch onUseWith(IntType.SCENERY, Items.ROPE_954, Scenery.WINCH_2351) { player, used, with -> if (removeItem(player, used)) { - if (getQuestStage(player, TheDigSite.questName) >= 8) { + if (getQuestStage(player, Quests.THE_DIG_SITE) >= 8) { setAttribute(player, TheDigSite.attributeRopeWestWinch, true) sendMessage(player, "You tie the rope to the bucket.") } else { @@ -614,14 +615,14 @@ class TheDigSiteListeners : InteractionListener { // 8: Investigating brick. Transitions to stage 9. on(Scenery.BRICK_2362, SCENERY, "search") { player, _ -> - if(getQuestStage(player, TheDigSite.questName) == 8) { + if(getQuestStage(player, Quests.THE_DIG_SITE) == 8) { sendPlayerDialogue(player, "Hmmm, there's a room past these bricks. If I could move them out of the way then I could find out what's inside. Maybe there's someone around here who can help...", FacialExpression.THINKING) - setQuestStage(player, TheDigSite.questName, 9) + setQuestStage(player, Quests.THE_DIG_SITE, 9) } - if(getQuestStage(player, TheDigSite.questName) == 9) { + if(getQuestStage(player, Quests.THE_DIG_SITE) == 9) { sendPlayerDialogue(player, "Hmmm, there's a room past these bricks. If I could move them out of the way then I could find out what's inside. Maybe there's someone around here who can help...", FacialExpression.THINKING) } - if(getQuestStage(player, TheDigSite.questName) == 10) { + if(getQuestStage(player, Quests.THE_DIG_SITE) == 10) { sendPlayerDialogue(player, "The brick is covered with the chemicals I made.", FacialExpression.THINKING) } return@on true @@ -749,12 +750,12 @@ class TheDigSiteListeners : InteractionListener { // 8/9: Pouring CHEMICAL_COMPOUND_707 on brick. Transitions to stage 10. onUseWith(SCENERY, Items.CHEMICAL_COMPOUND_707, Scenery.BRICK_2362) { player, used, with -> - if (getQuestStage(player, TheDigSite.questName) == 9) { + if (getQuestStage(player, Quests.THE_DIG_SITE) == 9) { if(removeItem(player, used)) { addItemOrDrop(player, Items.VIAL_229) sendMessage(player, "You pour the compound over the bricks...") sendPlayerDialogue(player, "Ok, the mixture is all over the bricks. I need some way to ignite this compound.", FacialExpression.THINKING) - setQuestStage(player, TheDigSite.questName, 10) + setQuestStage(player, Quests.THE_DIG_SITE, 10) } } return@onUseWith true @@ -762,8 +763,8 @@ class TheDigSiteListeners : InteractionListener { // 10: Lighting brick. Transitions to stage 11. onUseWith(SCENERY, Items.TINDERBOX_590, Scenery.BRICK_2362) { player, used, with -> - if(getQuestStage(player, TheDigSite.questName) == 10) { - setQuestStage(player, TheDigSite.questName, 11) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 10) { + setQuestStage(player, Quests.THE_DIG_SITE, 11) lock(player, 15) queueScript(player, 0, QueueStrength.NORMAL) { stage: Int -> when (stage) { diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/dialogue/MistagDialogue.kt b/Server/src/main/content/region/misthalin/dorgeshuun/dialogue/MistagDialogue.kt index efdb1a9be..a05bfeb93 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/dialogue/MistagDialogue.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/dialogue/MistagDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.dialogue +import content.data.Quests import core.game.component.Component import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -23,7 +24,7 @@ class MistagDialogue (player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - val ltStage = player.questRepository.getStage("Lost Tribe") + val ltStage = player.questRepository.getStage(Quests.THE_LOST_TRIBE) if(args.size > 1 && args[1] == "greeting"){ npc("A human knows ancient greeting?") diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/DukeHoracioTLTDialogue.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/DukeHoracioTLTDialogue.kt index 93bb1f871..c71192c37 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/DukeHoracioTLTDialogue.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/DukeHoracioTLTDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.api.* import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC @@ -48,7 +49,7 @@ class DukeHoracioTLTDialogue(val questStage: Int) : DialogueFile() { "this mystery. If there is a blocked tunnel then perhaps", "you should try to un-block it." ) - player!!.questRepository.getQuest("Lost Tribe").setStage(player, 30) + player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 30) stage = END_DIALOGUE } } @@ -108,7 +109,7 @@ class DukeHoracioTLTDialogue(val questStage: Int) : DialogueFile() { "brooch. The librarian in Varrock might be able to help", "identify the symbol." ) - player!!.questRepository.getQuest("Lost Tribe").setStage(player, 40) + player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 40) stage = END_DIALOGUE } } @@ -140,7 +141,7 @@ class DukeHoracioTLTDialogue(val questStage: Int) : DialogueFile() { player!!.name.capitalize() + ", I would still like you to find out more", "about this tribe. It cannot hurt to know one's enemy." ) - player!!.questRepository.getQuest("Lost Tribe").setStage(player, 45) + player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 45) stage = END_DIALOGUE } } @@ -169,7 +170,7 @@ class DukeHoracioTLTDialogue(val questStage: Int) : DialogueFile() { 4 -> { npc("Unless it is returned, I am afraid I will have no option", "but war.") - player!!.questRepository.getQuest("Lost Tribe").setStage(player, 47) + player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 47) stage = END_DIALOGUE } } @@ -216,7 +217,7 @@ class DukeHoracioTLTDialogue(val questStage: Int) : DialogueFile() { "their leader to sign it." ) addItemOrDrop(player!!, Items.PEACE_TREATY_5012) - player!!.questRepository.getQuest("Lost Tribe").setStage(player, 50) + player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 50) setVarbit(player!!, 532, 9, true) stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/HistoryOfTheGoblinRace.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/HistoryOfTheGoblinRace.kt index 57c14a8f0..d6d5ed9ab 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/HistoryOfTheGoblinRace.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/HistoryOfTheGoblinRace.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.game.component.Component import core.game.component.ComponentDefinition import core.game.component.ComponentPlugin @@ -23,11 +24,11 @@ class HistoryOfTheGoblinRace : ComponentPlugin() { player ?: return super.open(player, component) player.packetDispatch.sendInterfaceConfig(183,17,true) - val qstage = player.questRepository.getQuest("Lost Tribe").getStage(player) + val qstage = player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) component?.setCloseEvent { player, c -> if(qstage == 42 || qstage == 41 ) { player.dialogueInterpreter.sendDialogues(player, FacialExpression.THINKING, "Hey... The symbol of the 'Dorgeshuun' tribe looks just", "like the symbol on the brooch I found.") - player.questRepository.getQuest("Lost Tribe").setStage(player, 43) + player.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player, 43) } player.removeAttribute("hgr-index") true diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribe.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribe.kt index fec111418..2bbcda87a 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribe.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribe.kt @@ -8,13 +8,14 @@ import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items import core.api.* +import content.data.Quests @Initializable /** * Represents the lost tribe quest and quest journal * @author Ceikry */ -class LostTribe : Quest("Lost Tribe",84,83,1) { +class LostTribe : Quest(Quests.THE_LOST_TRIBE,84,83,1) { override fun newInstance(`object`: Any?): Quest { return this } @@ -27,8 +28,8 @@ class LostTribe : Quest("Lost Tribe",84,83,1) { line(player,"I can start this quest by speaking to !!Sigmund?? in !!Lumbridge??",line++) line(player,"!!Castle.??",line++) line(player,"I must have completed:",line++) - line(player,"Rune Mysteries",line++,player?.questRepository?.isComplete("Rune Mysteries") == true) - line(player,"Goblin Diplomacy",line++,player?.questRepository?.isComplete("Goblin Diplomacy") == true) + line(player,"Rune Mysteries" ,line++,player?.questRepository?.isComplete(Quests.RUNE_MYSTERIES) == true) + line(player,"Goblin Diplomacy" ,line++,player?.questRepository?.isComplete(Quests.GOBLIN_DIPLOMACY) == true) line(player,"and have:",line++) line(player,"Level 17 mining",line++,player.skills.getLevel(Skills.MINING) >= 17) line(player,"Level 13 agility",line++,player.skills.getLevel(Skills.AGILITY) >= 13) diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeCutscene.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeCutscene.kt index a9413b011..f155df3f5 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeCutscene.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeCutscene.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.api.animate import core.api.face import core.game.activity.Cutscene @@ -105,7 +106,7 @@ class LostTribeCutscene(player: Player) : Cutscene(player) { } 19 -> { end { - player.questRepository.getQuest("Lost Tribe").finish(player) + player.questRepository.getQuest(Quests.THE_LOST_TRIBE).finish(player) } } } diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeOptionHandler.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeOptionHandler.kt index 53c5cdf1e..a361dcfbc 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeOptionHandler.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/LostTribeOptionHandler.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.api.addItemOrDrop import core.cache.def.impl.ItemDefinition import core.cache.def.impl.NPCDefinition @@ -39,7 +40,8 @@ class LostTribeOptionHandler : OptionHandler(){ 5008 -> player.interfaceManager.open(Component(50)) 5009 -> player.interfaceManager.open(Component(183)) 6916 -> { - if(!player.inventory.containsItem(BOOK) && !player.bank.containsItem(BOOK) && player.questRepository.getQuest("Lost Tribe").getStage(player) >= 41){ + if(!player.inventory.containsItem(BOOK) && !player.bank.containsItem(BOOK) && player.questRepository.getQuest( + Quests.THE_LOST_TRIBE).getStage(player) >= 41){ player.dialogueInterpreter.sendDialogue("'A History of the Goblin Race.' This must be it.") player.inventory.add(BOOK) } else { @@ -47,10 +49,10 @@ class LostTribeOptionHandler : OptionHandler(){ } } 6911 -> { - if(!player.inventory.containsItem(Item(Items.SILVERWARE_5011)) && player.questRepository.getQuest("Lost Tribe").getStage(player) == 48){ + if(!player.inventory.containsItem(Item(Items.SILVERWARE_5011)) && player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 48){ player.dialogueInterpreter.sendItemMessage(Items.SILVERWARE_5011,"You find the missing silverware!") addItemOrDrop(player, Items.SILVERWARE_5011) - player.questRepository.getQuest("Lost Tribe").setStage(player,49) + player.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player,49) } else { player.sendMessage("You find nothing.") } diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/MistagLTDialogue.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/MistagLTDialogue.kt index 8e01d2f77..8c637a839 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/MistagLTDialogue.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/MistagLTDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.game.component.Component import core.game.dialogue.FacialExpression import core.game.dialogue.DialogueFile @@ -20,7 +21,8 @@ class MistagLTDialogue(val isGreeting: Boolean, val questStage: Int) : DialogueF 4 -> player("Did you break in to the castle cellar?").also { stage++ } 5 -> npc("It was an accident. We were following a seam of iron","and suddenly we found ourselves in a room!").also { stage++ } 6 -> npc("We blocked up our tunnel behind us and ran back","here. Then we did what cave goblins always do when","there is a problem: we hid and hoped it would go away.").also { stage++ } - 7 -> npc("We meant no harm! Please tell the ruler of the above","people that we want to make peace.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Lost Tribe").setStage(player,46) } + 7 -> npc("We meant no harm! Please tell the ruler of the above","people that we want to make peace.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest( + Quests.THE_LOST_TRIBE).setStage(player,46) } } } @@ -32,7 +34,7 @@ class MistagLTDialogue(val isGreeting: Boolean, val questStage: Int) : DialogueF 2 -> player("Did you break in to the castle cellar?").also { stage++ } 3 -> npc("It was an accident. We were following a seam of iron","and suddenly we found ourselves in a room!").also { stage++ } 4 -> npc("We blocked up our tunnel behind us and ran back","here. Then we did what cave goblins always do when","there is a problem: we hid and hoped it would go away.").also { stage++ } - 5 -> npc("We meant no harm! Please tell the ruler of the above","people that we want to make peace.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Lost Tribe").setStage(player,46) } + 5 -> npc("We meant no harm! Please tell the ruler of the above","people that we want to make peace.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player,46) } } } diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickaxeOnRubble.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickaxeOnRubble.kt index 62c3b392d..a1a871135 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickaxeOnRubble.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickaxeOnRubble.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.game.interaction.NodeUsageEvent import core.game.interaction.UseWithHandler import core.game.node.entity.skill.Skills @@ -25,7 +26,7 @@ class PickaxeOnRubble : UseWithHandler(1265,1267,1269,1271,1273,1275){ override fun handle(event: NodeUsageEvent?): Boolean { val player = event?.player ?: return false - val stage = player.questRepository.getQuest("Lost Tribe").getStage(player) + val stage = player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) if(stage < 30){ player.dialogueInterpreter.sendItemMessage(event.usedItem.id,"I should probably figure out what happened","before vandalizing the castle more.") return true diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickpocketSigmund.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickpocketSigmund.kt index fa6194e68..a4e519efa 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickpocketSigmund.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/PickpocketSigmund.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.game.node.item.Item import core.game.system.task.Pulse import core.game.world.update.flag.context.Animation @@ -25,7 +26,7 @@ class PickpocketSigmund : InteractionListener { when(counter++){ 0 -> player.animator.animate(Animation(881)) 3 -> { - if(player.questRepository.getQuest("Lost Tribe").getStage(player) == 47 && !player.inventory.containsItem(Item(Items.KEY_423))){ + if(player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 47 && !player.inventory.containsItem(Item(Items.KEY_423))){ player.inventory.add(Item(Items.KEY_423)) player.dialogueInterpreter.sendItemMessage(Items.KEY_423,"You find a small key on Sigmund.") } else { diff --git a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/SigmundChestHandler.kt b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/SigmundChestHandler.kt index 246b139f8..ef26dc557 100644 --- a/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/SigmundChestHandler.kt +++ b/Server/src/main/content/region/misthalin/dorgeshuun/quest/thelosttribe/SigmundChestHandler.kt @@ -1,5 +1,6 @@ package content.region.misthalin.dorgeshuun.quest.thelosttribe +import content.data.Quests import core.cache.def.impl.SceneryDefinition import core.game.interaction.OptionHandler import core.game.node.Node @@ -23,14 +24,14 @@ class SigmundChestHandler : OptionHandler() { override fun handle(player: Player?, node: Node?, option: String?): Boolean { player ?: return false - if(player.questRepository.getQuest("Lost Tribe").getStage(player) == 47 && player.inventory.contains(Items.KEY_423,1)){ + if(player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 47 && player.inventory.contains(Items.KEY_423,1)){ player.inventory.remove(Item(Items.KEY_423)) for(item in arrayOf(Items.HAM_ROBE_4300,Items.HAM_SHIRT_4298,Items.HAM_HOOD_4302).map { Item(it) }){ if(!player.inventory.add(item)){ GroundItemManager.create(item,player) } } - player.questRepository.getQuest("Lost Tribe").setStage(player,48) + player.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player,48) } else { player.sendMessage("This chest requires a key.") } diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/AggieDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/AggieDialogue.java index 7e3dbe614..fe7fb4830 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/AggieDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/AggieDialogue.java @@ -9,6 +9,7 @@ import core.game.node.item.Item; import core.game.world.map.Location; import core.plugin.Initializable; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the dialogue plugin used for the aggie npc. @@ -115,7 +116,7 @@ public final class AggieDialogue extends DialoguePlugin { stage = 42; return true; } - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); npc("What can I help you with?"); stage = 0; return true; diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/JoeGuardDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/JoeGuardDialogue.java index 8351ddd49..b7b91c6d8 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/JoeGuardDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/JoeGuardDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue of the Joe guard NPC. @@ -49,7 +50,7 @@ public final class JoeGuardDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); switch (quest.getStage(player)) { case 40: if (player.getAttribute("guard-drunk", false)) { diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/LeelaDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/LeelaDialogue.java index 026f2ff53..133cebfb1 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/LeelaDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/LeelaDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represnets the dialogue used to handle the Leela npc. @@ -76,7 +77,7 @@ public final class LeelaDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); switch (quest.getStage(player)) { case 60: case 100: diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/MissSchismDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/MissSchismDialogue.java index 3cc707120..afa313cd1 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/MissSchismDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/MissSchismDialogue.java @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.plugin.Initializable; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the miss schism dialogue plugin. @@ -90,7 +91,7 @@ public final class MissSchismDialogue extends DialoguePlugin { break; case 110: - if (player.getQuestRepository().isComplete("Vampire Slayer")) { + if (player.getQuestRepository().isComplete(Quests.VAMPIRE_SLAYER)) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, there's nothing to tell NOW. You killed it."); stage = 111; } else { @@ -156,7 +157,7 @@ public final class MissSchismDialogue extends DialoguePlugin { stage = 23; break; case 23: - if(player.getQuestRepository().isComplete("Vampire Slayer")) { + if(player.getQuestRepository().isComplete(Quests.VAMPIRE_SLAYER)) { interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Well, now that I've cleared the vampire out of the manor,", "I guess you won't have too much trouble turning it into a", "museum."); stage = 24; } else { diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/MorganDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/MorganDialogue.java index eb6270e1e..e7d150cf7 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/MorganDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/MorganDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the dialogue plugin used for the morgan npc. @@ -39,9 +40,9 @@ public final class MorganDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest("Vampire Slayer"); + quest = player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER); npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Vampire Slayer"); + quest = player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER); if (quest.getStage(player) == 0) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Please please help us, bold adventurer!"); stage = 0; diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/PrinceAliDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/PrinceAliDialogue.java index eb500dfe2..cb13ff920 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/PrinceAliDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/PrinceAliDialogue.java @@ -8,6 +8,7 @@ import core.game.node.item.Item; import core.game.system.task.Pulse; import core.plugin.Initializable; import core.game.world.GameWorld; +import content.data.Quests; /** * Represents the dialogue used to handle the Pricne Ali NPC. @@ -52,7 +53,7 @@ public class PrinceAliDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Prince Ali Rescue"); + quest = player.getQuestRepository().getQuest(Quests.PRINCE_ALI_RESCUE); switch (quest.getStage(player)) { case 50: interpreter.sendDialogues(player, null, "Prince, I come to rescue you."); diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/ProfessorOddensteinPlugin.java b/Server/src/main/content/region/misthalin/draynor/dialogue/ProfessorOddensteinPlugin.java index 294c14ec7..b90bdc349 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/ProfessorOddensteinPlugin.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/ProfessorOddensteinPlugin.java @@ -14,6 +14,7 @@ import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.game.world.update.flag.context.Graphics; +import content.data.Quests; /** * Represents the plugin dialogue to handle the interaction with professor @@ -81,7 +82,7 @@ public class ProfessorOddensteinPlugin extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - final Quest quest = player.getQuestRepository().getQuest("Ernest the Chicken"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN); switch (quest.getStage(player)) { case 0: case 10: @@ -102,7 +103,7 @@ public class ProfessorOddensteinPlugin extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Ernest the Chicken"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN); switch (quest.getStage(player)) { case 0: case 100: diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/VeronicaDialogue.java b/Server/src/main/content/region/misthalin/draynor/dialogue/VeronicaDialogue.java index 25796ff04..3480ca1b4 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/VeronicaDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/VeronicaDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the dialogue used to handle the interaction between veronica. @@ -39,7 +40,7 @@ public class VeronicaDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Ernest the Chicken"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN); switch (quest.getStage(player)) { case 0: switch (stage) { @@ -169,7 +170,7 @@ public class VeronicaDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - final Quest quest = player.getQuestRepository().getQuest("Ernest the Chicken"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN); switch (quest.getStage(player)) { case 0: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Can you please help me? I'm in a terrible spot of", "trouble."); diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceDialogue.java index 0dcfe9778..0d81ec43b 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.draynor.quest.anma; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -41,7 +42,7 @@ public final class AliceDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); switch (quest.getStage(player)) { default: options("What are you selling?", "I'm okay, thank you."); diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceHusbandDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceHusbandDialogue.java index 691c9b1f0..b584565ff 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceHusbandDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AliceHusbandDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.draynor.quest.anma; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; import core.game.node.entity.player.Player; @@ -52,7 +53,7 @@ public final class AliceHusbandDialogue extends DialoguePlugin { npc("Wooo wooo wooooo!"); return true; } - quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); switch (quest.getStage(player)) { case 0: npc("Hi, I don't feel like talking."); diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetism.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetism.java index 4e2f9dc9c..a04a6c9de 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetism.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetism.java @@ -11,6 +11,7 @@ import content.region.misthalin.draynor.quest.anma.AnimalMagnetismPlugin.HammerM import content.region.misthalin.draynor.quest.anma.AnimalMagnetismPlugin.ResearchNoteHandler; import core.plugin.Initializable; import content.region.misthalin.draynor.quest.anma.AnimalMagnetismPlugin.UndeadTreePlugin; +import content.data.Quests; /** * Handles the animal magnetism quest. @@ -18,12 +19,6 @@ import content.region.misthalin.draynor.quest.anma.AnimalMagnetismPlugin.UndeadT */ @Initializable public final class AnimalMagnetism extends Quest { - - /** - * The name of this quest. - */ - public static String NAME = "Animal Magnetism"; - /** * The crone made amulet item. */ @@ -103,7 +98,7 @@ public final class AnimalMagnetism extends Quest { * Constructs a new {@code AnimalMagnetism} {@code Object}. */ public AnimalMagnetism() { - super("Animal Magnetism", 33, 32, 1); + super(Quests.ANIMAL_MAGNETISM, 33, 32, 1); } @Override @@ -219,9 +214,9 @@ public final class AnimalMagnetism extends Quest { @Override public boolean hasRequirements(Player player) { - requirements[0] = player.getQuestRepository().isComplete("The Restless Ghost"); - requirements[1] = player.getQuestRepository().isComplete("Ernest the Chicken"); - requirements[2] = player.getQuestRepository().isComplete("Priest in Peril"); + requirements[0] = player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST); + requirements[1] = player.getQuestRepository().isComplete(Quests.ERNEST_THE_CHICKEN); + requirements[2] = player.getQuestRepository().isComplete(Quests.PRIEST_IN_PERIL); requirements[3] = player.getSkills().getStaticLevel(Skills.RANGE) >= 30; requirements[4] = player.getSkills().getStaticLevel(Skills.SLAYER) >= 18; requirements[5] = player.getSkills().getStaticLevel(Skills.CRAFTING) >= 19; diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java index 141e8a52f..6156fe9bd 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java @@ -19,7 +19,6 @@ import core.game.node.Node; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.TeleportManager.TeleportType; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.game.system.task.Pulse; @@ -33,9 +32,9 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; import core.plugin.ClassScanner; import core.tools.RandomFunction; -import org.rs09.consts.Sounds; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Handles the animal magnetism plugin. @@ -62,14 +61,14 @@ public final class AnimalMagnetismPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { switch (node.getId()) { case 5167: - if (!hasRequirement(player, "Creature of Fenkenstrain")) { + if (!hasRequirement(player, Quests.CREATURE_OF_FENKENSTRAIN)) { break; } player.teleport(new Location(3577, 9927)); break; case 5198: case 5199: - if (player.getQuestRepository().getQuest(AnimalMagnetism.NAME).getStage(player) == 0) { + if (player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM).getStage(player) == 0) { player.getDialogueInterpreter().sendDialogues((NPC) node, null, "Hello there, I'm busy with my research. Come back in a", "bit, could you?"); break; } @@ -198,7 +197,7 @@ public final class AnimalMagnetismPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); if (quest.getStage(player) <= 28) { SkillingTool tool = SkillingTool.getHatchet(player); if (tool == null || tool.ordinal() < 4) { @@ -243,7 +242,7 @@ public final class AnimalMagnetismPlugin extends OptionHandler { public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); final Animation animation = getAnimation(event.getUsedItem().getId()); - final Quest quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); player.animate(animation, 2); if (quest.getStage(player) == 28) { quest.setStage(player, 29); @@ -293,7 +292,7 @@ public final class AnimalMagnetismPlugin extends OptionHandler { final Object[] data = getIndex(button); final boolean toggled = (boolean) data[1]; final int[] configs = getConfigs((int) data[0]); - final Quest quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); player.getPacketDispatch().sendInterfaceConfig(480, configs[0], !toggled); player.getPacketDispatch().sendInterfaceConfig(480, (int) data[2], toggled); if (quest.getStage(player) == 33) { diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnmaCutscene.kt b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnmaCutscene.kt index 18f6a0438..da0a40472 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnmaCutscene.kt +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnmaCutscene.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.game.world.map.Direction import org.rs09.consts.Animations import org.rs09.consts.NPCs +import content.data.Quests class AnmaCutscene(player: Player) : Cutscene(player) { override fun setup() { @@ -182,7 +183,7 @@ class AnmaCutscene(player: Player) : Cutscene(player) { } 32 -> { end { - setQuestStage(player, "Animal Magnetism", 20) + setQuestStage(player, Quests.ANIMAL_MAGNETISM, 20) } } } diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AvaDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AvaDialogue.java index ce546f229..bae10eb6d 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AvaDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AvaDialogue.java @@ -3,6 +3,7 @@ package content.region.misthalin.draynor.quest.anma; import java.util.ArrayList; import java.util.List; +import content.data.Quests; import core.game.container.Container; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.skill.Skills; @@ -55,7 +56,7 @@ public final class AvaDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); if (!quest.hasRequirements(player)) { player.getPacketDispatch().sendMessage("She doesn't seem interested in talking to you."); return false; diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AvasDevice.kt b/Server/src/main/content/region/misthalin/draynor/quest/anma/AvasDevice.kt index 511e4137f..9607a29ca 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AvasDevice.kt +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AvasDevice.kt @@ -11,6 +11,7 @@ import core.game.interaction.InteractionListener import core.game.interaction.IntType import core.tools.secondsToTicks import core.tools.colorize +import content.data.Quests /** * Handles Ava's device @@ -19,7 +20,7 @@ import core.tools.colorize class AvasDevice : InteractionListener, EventHook { override fun defineListeners() { onEquip(devices) { player, _ -> - if (!isQuestComplete(player, "Animal Magnetism")) { + if (!isQuestComplete(player, Quests.ANIMAL_MAGNETISM)) { sendMessage(player, "You need to complete Animal Magnetism to equip this.") return@onEquip false } diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/OldCronDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/OldCronDialogue.java index c5f97165f..eb76716f4 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/OldCronDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/OldCronDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import content.region.misthalin.lumbridge.quest.therestlessghost.RestlessGhost; +import content.data.Quests; /** * Handles the dialogue used for the old crone. @@ -49,7 +50,7 @@ public final class OldCronDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Animal Magnetism"); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); switch (quest.getStage(player)) { case 16: case 17: diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/WitchDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/WitchDialogue.java index 2e53bb979..7c23e06c0 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/WitchDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/WitchDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.draynor.quest.anma; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -45,7 +46,7 @@ public final class WitchDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(AnimalMagnetism.NAME); + quest = player.getQuestRepository().getQuest(Quests.ANIMAL_MAGNETISM); switch (quest.getStage(player)) { case 25: npc("Hello, hello, my poppet. What brings you to my little", "room?"); diff --git a/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestDialogue.java b/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestDialogue.java index bc29f3b16..8fbf7d11f 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestDialogue.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestDialogue.java @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression; import core.game.node.entity.npc.NPC; import core.plugin.Initializable; import core.game.node.entity.player.Player; +import content.data.Quests; /** * Represents the dialogue which handles the interaction with ernest. @@ -73,12 +74,12 @@ public final class ErnestDialogue extends DialoguePlugin { * Method used to finish the quest. */ public void finish() { - if (player.getQuestRepository().isComplete("Ernest the Chicken")) { + if (player.getQuestRepository().isComplete(Quests.ERNEST_THE_CHICKEN)) { npc.clear(); return; } npc.clear(); - player.getQuestRepository().getQuest("Ernest the Chicken").finish(player); + player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN).finish(player); } @Override diff --git a/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestTheChicken.java b/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestTheChicken.java index d18e635cd..58a9fecef 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestTheChicken.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/ernest/ErnestTheChicken.java @@ -8,6 +8,7 @@ import core.game.node.item.Item; import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the ernest the chicken quest. @@ -40,7 +41,7 @@ public final class ErnestTheChicken extends Quest { * Constructs a new {@code ErnestTheChicken} {@code Object}. */ public ErnestTheChicken() { - super("Ernest the Chicken", 19, 18, 4, 32, 0, 1, 3); + super(Quests.ERNEST_THE_CHICKEN, 19, 18, 4, 32, 0, 1, 3); } @Override @@ -128,7 +129,7 @@ public final class ErnestTheChicken extends Quest { @Override public boolean isHidden(final Player player) { - return player.getQuestRepository().getQuest("Ernest the Chicken").getStage(player) == 100 || player.getAttribute("ernest-hide", false); + return player.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN).getStage(player) == 100 || player.getAttribute("ernest-hide", false); } @Override @@ -174,7 +175,7 @@ public final class ErnestTheChicken extends Quest { @Override public boolean isHidden(final Player player) { Player target = getAttribute("target", null); - if (target != null && target.getQuestRepository().getQuest("Ernest the Chicken").getStage(player) == 100) { + if (target != null && target.getQuestRepository().getQuest(Quests.ERNEST_THE_CHICKEN).getStage(player) == 100) { clear(); return super.isHidden(player); } diff --git a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayer.java b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayer.java index 6231e659e..94e7f13cb 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayer.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayer.java @@ -4,6 +4,7 @@ import core.plugin.Initializable; import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the vampire quest. @@ -16,7 +17,7 @@ public class VampireSlayer extends Quest { * Constructs a new {@code VampireSlayer} {@code Object}. */ public VampireSlayer() { - super("Vampire Slayer", 30, 29, 3, 178, 0, 1, 3); + super(Quests.VAMPIRE_SLAYER, 30, 29, 3, 178, 0, 1, 3); } @Override diff --git a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerNPC.java b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerNPC.java index 35d9e8df3..17c72b2f2 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerNPC.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerNPC.java @@ -11,6 +11,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.game.world.map.Location; import core.tools.RandomFunction; +import content.data.Quests; /** * Handles the Vampie Slayer npc. @@ -127,7 +128,7 @@ public class VampireSlayerNPC extends AbstractNPC { return; } final Player p = ((Player) killer); - final Quest quest = p.getQuestRepository().getQuest("Vampire Slayer"); + final Quest quest = p.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER); if (p.getInventory().containsItem(HAMMER) && p.getInventory().remove(STAKE)) { if (quest.getStage(p) == 30) { quest.finish(p); diff --git a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerPlugin.java b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerPlugin.java index 243b76966..f8f582536 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/vampire/VampireSlayerPlugin.java @@ -11,6 +11,7 @@ import core.game.node.scenery.Scenery; import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the plugin to handle vampire slayer node handling. @@ -51,7 +52,7 @@ public final class VampireSlayerPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Vampire Slayer"); + final Quest quest = player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER); switch (option) { case "open": int id = ((Scenery) node).getId(); diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DukeHoracioDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DukeHoracioDialogue.kt index 59e3b4775..da9ead1cc 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/DukeHoracioDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/DukeHoracioDialogue.kt @@ -10,6 +10,7 @@ import content.region.misthalin.lumbridge.quest.runemysteries.DukeHoracioRMDialo import content.region.misthalin.dorgeshuun.quest.thelosttribe.DukeHoracioTLTDialogue import core.tools.DIALOGUE_INITIAL_OPTIONS_HANDLE import core.tools.END_DIALOGUE +import content.data.Quests /** * Core dialogue plugin for Duke Horacio, redirects to more specific DialogueFiles. @@ -23,11 +24,11 @@ class DukeHoracioDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any): Boolean { npc = args[0] as NPC - if ((player.questRepository.getQuest("Dragon Slayer").getStage(player) == 100 && !player.inventory.containsItem(DragonSlayer.SHIELD) && !player.bank.containsItem(DragonSlayer.SHIELD) )|| (player.questRepository.getQuest("Dragon Slayer").isStarted(player) && !player.questRepository.getQuest("Dragon Slayer").isCompleted(player))) { - addOption("Dragon Slayer", DukeHoracioDSDialogue(player.questRepository.getStage("Dragon Slayer"))) + if ((player.questRepository.getQuest(Quests.DRAGON_SLAYER).getStage(player) == 100 && !player.inventory.containsItem(DragonSlayer.SHIELD) && !player.bank.containsItem(DragonSlayer.SHIELD) )|| (player.questRepository.getQuest(Quests.DRAGON_SLAYER).isStarted(player) && !player.questRepository.getQuest(Quests.DRAGON_SLAYER).isCompleted(player))) { + addOption("Dragon Slayer", DukeHoracioDSDialogue(player.questRepository.getStage(Quests.DRAGON_SLAYER))) } - if (!player.questRepository.isComplete("Lost Tribe") && player.questRepository.getQuest("Lost Tribe").isStarted(player)) { - addOption("Lost Tribe", DukeHoracioTLTDialogue(player.questRepository.getStage("Lost Tribe"))) + if (!player.questRepository.isComplete(Quests.THE_LOST_TRIBE) && player.questRepository.getQuest(Quests.THE_LOST_TRIBE).isStarted(player)) { + addOption("Lost Tribe", DukeHoracioTLTDialogue(player.questRepository.getStage(Quests.THE_LOST_TRIBE))) } if (!sendChoices()) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings. Welcome to my castle.") @@ -66,8 +67,8 @@ class DukeHoracioDialogue(player: Player? = null) : DialoguePlugin(player) { } 20 -> { npc("Let me see...") - if (!player.questRepository.isComplete("Rune Mysteries")) { - loadFile(DukeHoracioRMDialogue(player.questRepository.getStage("Rune Mysteries"))) + if (!player.questRepository.isComplete(Quests.RUNE_MYSTERIES)) { + loadFile(DukeHoracioRMDialogue(player.questRepository.getStage(Quests.RUNE_MYSTERIES))) } else { stage++ } diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/FredTheFarmerDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/dialogue/FredTheFarmerDialogue.kt index 151f8e034..357c76e2d 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/FredTheFarmerDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/FredTheFarmerDialogue.kt @@ -11,6 +11,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests @Initializable class FredTheFarmerDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -20,8 +21,8 @@ class FredTheFarmerDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any): Boolean { npc = args[0] as NPC - if (getQuestStage(player, "Sheep Shearer") in 1..99) { - openDialogue(player, SSFredTheFarmerDialogue(getQuestStage(player, "Sheep Shearer")), npc) + if (getQuestStage(player, Quests.SHEEP_SHEARER) in 1..99) { + openDialogue(player, SSFredTheFarmerDialogue(getQuestStage(player, Quests.SHEEP_SHEARER)), npc) } else { npc(FacialExpression.ANGRY, "What are you doing on my land? You're not the one", "who keeps leaving all my gates open and letting out all", "my sheep are you?").also { stage = START_DIALOGUE } } @@ -31,7 +32,7 @@ class FredTheFarmerDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { when (stage) { START_DIALOGUE -> showTopics( - IfTopic(FacialExpression.NEUTRAL, "I'm looking for a quest.", 1000, getQuestStage(player!!, "Sheep Shearer") == 0), + IfTopic(FacialExpression.NEUTRAL, "I'm looking for a quest.", 1000, getQuestStage(player!!, Quests.SHEEP_SHEARER) == 0), Topic(FacialExpression.HALF_GUILTY, "I'm looking for something to kill.", 100), Topic(FacialExpression.HALF_GUILTY, "I'm lost.", 200) ) @@ -40,7 +41,7 @@ class FredTheFarmerDialogue(player: Player? = null) : DialoguePlugin(player) { 200 -> npc(FacialExpression.HALF_GUILTY, "How can you be lost? Just follow the road east and", "south. You'll end up in Lumbridge fairly quickly.").also { stage = END_DIALOGUE } - 1000 -> openDialogue(player, SSFredTheFarmerDialogue(getQuestStage(player, "Sheep Shearer")), npc) + 1000 -> openDialogue(player, SSFredTheFarmerDialogue(getQuestStage(player, Quests.SHEEP_SHEARER)), npc) } return true } diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/LumbridgeGuideDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/dialogue/LumbridgeGuideDialogue.kt index f2f157707..d01bdf614 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/LumbridgeGuideDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/LumbridgeGuideDialogue.kt @@ -13,6 +13,7 @@ import org.rs09.consts.NPCs import core.game.dialogue.IfTopic import core.game.dialogue.Topic import core.tools.END_DIALOGUE +import content.data.Quests @Initializable class LumbridgeGuideDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -23,8 +24,8 @@ class LumbridgeGuideDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { val staff = player.isStaff val ironman = player.ironmanManager.isIronman - val sheepShearerComplete = isQuestComplete(player, "Sheep Shearer") - val cooksAssistantComplete = isQuestComplete(player, "Cook's Assistant") + val sheepShearerComplete = isQuestComplete(player, Quests.SHEEP_SHEARER) + val cooksAssistantComplete = isQuestComplete(player, Quests.COOKS_ASSISTANT) when (stage) { 0 -> npcl(FacialExpression.FRIENDLY, "Greetings, adventurer. I am Phileas, the Lumbridge Guide. I am here to give information and directions to new players. Do you require any help?").also { stage++ } diff --git a/Server/src/main/content/region/misthalin/lumbridge/dialogue/SigmundDialogue.java b/Server/src/main/content/region/misthalin/lumbridge/dialogue/SigmundDialogue.java index f384019e9..e4e521668 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/dialogue/SigmundDialogue.java +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/SigmundDialogue.java @@ -7,6 +7,7 @@ import core.plugin.Initializable; import core.game.node.entity.player.Player; import static core.tools.DialogueConstKt.END_DIALOGUE; +import content.data.Quests; /** @@ -35,7 +36,7 @@ public class SigmundDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Can I help you?"); - if(player.getQuestRepository().getQuest("Lost Tribe").getStage(player) > 0 && player.getQuestRepository().getQuest("Lost Tribe").getStage(player) < 100){ + if(player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) > 0 && player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) < 100){ npc("Have you found out what it was?"); stage = 34; return true; @@ -80,12 +81,12 @@ public class SigmundDialogue extends DialoguePlugin { end(); break; case 10: - if(player.getQuestRepository().hasStarted("Lost Tribe") && !player.getQuestRepository().isComplete("Lost Tribe")){ + if(player.getQuestRepository().hasStarted(Quests.THE_LOST_TRIBE) && !player.getQuestRepository().isComplete(Quests.THE_LOST_TRIBE)){ npc("No, not right now."); stage = 12; break; } - if(player.getQuestRepository().isComplete("Goblin Diplomacy") && player.getQuestRepository().isComplete("Rune Mysteries") && !player.getQuestRepository().hasStarted("Lost Tribe")){ + if(player.getQuestRepository().isComplete(Quests.GOBLIN_DIPLOMACY) && player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES) && !player.getQuestRepository().hasStarted(Quests.THE_LOST_TRIBE)){ npc("There was recently some damage to the castle cellar.","Part of the wall has collapsed."); stage = 30; break; @@ -107,7 +108,7 @@ public class SigmundDialogue extends DialoguePlugin { case 31: npc("You should ask other people around the town if they","saw anything."); stage = END_DIALOGUE; - player.getQuestRepository().getQuest("Lost Tribe").start(player); + player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).start(player); player.setAttribute("/save:tlt-witness", TLTNPCS[0]); break; case 34: diff --git a/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt b/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt index af65c278c..5a8ca76db 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt @@ -19,6 +19,7 @@ import core.game.diary.AreaDiaryTask import core.game.diary.DiaryEventHookBase import core.game.diary.DiaryLevel import core.game.event.* +import content.data.Quests class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { @@ -346,7 +347,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { override fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) { when (event.dialogue) { is DukeHoracioDSDialogue -> { - val dragonSlayerStage = getQuestStage(player, "Dragon Slayer") + val dragonSlayerStage = getQuestStage(player, Quests.DRAGON_SLAYER) if ((dragonSlayerStage == 100 && event.currentStage == 4) || event.currentStage == 12) { diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java index 39350352d..7a810e667 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java @@ -22,6 +22,7 @@ import core.plugin.Initializable; import core.tools.RandomFunction; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the lumbridge basement. diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/CooksAssistant.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/CooksAssistant.kt index 790b6aec2..54d38f426 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/CooksAssistant.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/CooksAssistant.kt @@ -4,6 +4,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable +import content.data.Quests /** * The Quest Journal and Configuration for the Cook's Assistant Quest. @@ -11,7 +12,7 @@ import core.plugin.Initializable */ @Initializable -class CooksAssistant : Quest("Cook's Assistant",15, 14, 1, 29, 0, 1, 2){ +class CooksAssistant : Quest(Quests.COOKS_ASSISTANT,15, 14, 1, 29, 0, 1, 2){ val MILK = 1927 val FLOUR = 1933 val EGG = 1944 @@ -21,7 +22,7 @@ class CooksAssistant : Quest("Cook's Assistant",15, 14, 1, 29, 0, 1, 2){ super.drawJournal(player, stage) var line = 12 - var stage = player?.questRepository?.getStage("Cook's Assistant")!! + var stage = player?.questRepository?.getStage(Quests.COOKS_ASSISTANT)!! if(stage < 10){ //If the quest has not been started diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/LumbridgeCookDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/LumbridgeCookDialogue.kt index 67e96da73..ae7b6439f 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/LumbridgeCookDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/cooksassistant/LumbridgeCookDialogue.kt @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable +import content.data.Quests /** * Dialogue for the Lumbridge Cook. @@ -29,16 +30,16 @@ class LumbridgeCookDialogue (player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - if(player?.questRepository?.getQuest("Lost Tribe")?.getStage(player) == 10){ + if (player?.questRepository?.getQuest(Quests.THE_LOST_TRIBE)?.getStage(player) == 10) { player("Did you see what happened in the cellar?") stage = 0 return true } - if (player?.questRepository?.getQuest("Cook's Assistant")!!.getStage(player) <= 0) { //If the player has ot started cook's assistant + if (player?.questRepository?.getQuest(Quests.COOKS_ASSISTANT)!!.getStage(player) <= 0) { //If the player has ot started cook's assistant npc(FacialExpression.SAD, "What am I to do?") stage = 0 return true - } else if (player?.questRepository?.getQuest("Cook's Assistant")!!.getStage(player) in 10..99) { //During the Cook's Assistant Quest + } else if (player?.questRepository?.getQuest(Quests.COOKS_ASSISTANT)!!.getStage(player) in 10..99) { //During the Cook's Assistant Quest if (player.getAttribute("cooks_assistant:all_submitted", false) || (player.getAttribute("cooks_assistant:milk_submitted", false) && player.getAttribute("cooks_assistant:flour_submitted", false) && player.getAttribute("cooks_assistant:egg_submitted", false))){ //If the player has handed all the ingredients to the chef but did not continue the dialogue npc(FacialExpression.HAPPY, "You've brought me everything I need! I am saved!", "Thank you!") stage = 200 @@ -57,14 +58,14 @@ class LumbridgeCookDialogue (player: Player? = null) : DialoguePlugin(player){ } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - if(player.questRepository.getQuest("Lost Tribe").getStage(player) == 10){ + if (player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 10) { when(stage){ //Lost Tribe 0 -> npc("Last night I was in the kitchen and I heard a noise","from the cellar. I opened the trapdoor and saw a","creature dart into a hole in the wall.").also { stage++ } 1 -> npc("It looked a bit like a goblin, but it had big bulging eyes.","It wasn't wearing armour, but it had this odd helmet","with a light on it.").also { stage++ } 2 -> npc("The tunnel was too dark for me to follow it, so I went","to tell the Duke. But when we went down to the cellar","the hole had been blocked up, and no one believes me.").also { stage++ } 3 -> player("I believe you.").also { stage++ } - 4 -> npc("Thank you, ${player.username}! If you can convince the Duke","I'm telling the truth then we can get to the bottom of","this mystery.").also { stage = 1000; player.questRepository.getQuest("Lost Tribe").setStage(player,20) } + 4 -> npc("Thank you, ${player.username}! If you can convince the Duke","I'm telling the truth then we can get to the bottom of","this mystery.").also { stage = 1000; player.questRepository.getQuest(Quests.THE_LOST_TRIBE).setStage(player,20) } 5 -> end() } return true @@ -117,7 +118,7 @@ class LumbridgeCookDialogue (player: Player? = null) : DialoguePlugin(player){ 44 -> npc(FacialExpression.ANGRY, "I AM a real cook! I haven't got time to be chatting", "about culinary fashion. I'm in desperate need of help!").also { stage = 21 } //Yes, I'll help you - 50 -> npc(FacialExpression.HAPPY, "Oh thank you, thank you. I need milk, an egg and", "flour. I'd be very grateful if you can get them for me.").also{ player?.questRepository?.getQuest("Cook's Assistant")?.start(player!!); stage++ } + 50 -> npc(FacialExpression.HAPPY, "Oh thank you, thank you. I need milk, an egg and", "flour. I'd be very grateful if you can get them for me.").also{ player?.questRepository?.getQuest(Quests.COOKS_ASSISTANT)?.start(player!!); stage++ } 51 -> player(FacialExpression.NEUTRAL, "So where do I find these ingredients then?").also { stage = 60 } //Where do I find these ingredients? @@ -241,10 +242,10 @@ class LumbridgeCookDialogue (player: Player? = null) : DialoguePlugin(player){ 203 -> npc(FacialExpression.NEUTRAL, "Maybe, but I won't be holding my breath.").also { stage++ } //Activate the Cook's Assistant Quest Complete Certificate - 204 -> end().also { player?.questRepository?.getQuest("Cook's Assistant")?.finish(player!!) } + 204 -> end().also { player?.questRepository?.getQuest(Quests.COOKS_ASSISTANT)?.finish(player!!) } //Dialogue after Cook's Assistant Completion - 300 -> if(player.questRepository.getQuest("Lost Tribe").getStage(player) == 10) { + 300 -> if(player.questRepository.getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 10) { player("Do you know what happened in the castle cellar?").also { stage = 600 } } else { options("I am getting strong and mighty.", "I keep on dying.", "Can I use your range?").also { stage++ } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/DramenTreeListener.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/DramenTreeListener.kt index 735e384d7..679e28bde 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/DramenTreeListener.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/DramenTreeListener.kt @@ -10,13 +10,14 @@ import core.game.interaction.InteractionListener import core.api.getQuestStage import core.api.sendMessage import core.game.interaction.IntType +import content.data.Quests class DramenTreeListener : InteractionListener { override fun defineListeners() { on(Sceneries.DRAMEN_TREE_1292, IntType.SCENERY, "chop down"){ player, node -> - val questStage = getQuestStage(player,"Lost City") + val questStage = getQuestStage(player,Quests.LOST_CITY) if (SkillingTool.getHatchet(player) == null) { sendMessage(player,"You do not have an axe which you have the level to use.") return@on true diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCity.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCity.kt index f83e0248a..744ef3ca1 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCity.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCity.kt @@ -6,6 +6,7 @@ import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * LostCity class for the Lost City quest @@ -14,7 +15,7 @@ import org.rs09.consts.Items * @author Aero */ @Initializable -class LostCity : Quest("Lost City", 83, 82, 3, 147, 0, 1, 6) { +class LostCity : Quest(Quests.LOST_CITY, 83, 82, 3, 147, 0, 1, 6) { class SkillRequirement(val skill: Int?, val level: Int?) diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCityListeners.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCityListeners.kt index c922a107e..32bef2049 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCityListeners.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/LostCityListeners.kt @@ -13,6 +13,7 @@ import core.game.interaction.IntType import org.rs09.consts.Scenery as Sceneries import core.game.interaction.InteractionListener import core.game.world.GameWorld +import content.data.Quests /** * This class covers some listeners for the Lost City quest @@ -27,12 +28,11 @@ class LostCityListeners : InteractionListener { // the shed teleport, to allow players to access zanaris if they enter the shed while wielding the dramen staff on(Sceneries.DOOR_2406, IntType.SCENERY,"open"){ player, node -> core.game.global.action.DoorActionHandler.handleAutowalkDoor(player,node as Scenery) - val quest = "Lost City" val isOutsideShed = player.location.x < node.location.x - val canDramenTeleport = inEquipment(player,Items.DRAMEN_STAFF_772) && ( getQuestStage(player,quest) > 20 ) && isOutsideShed - if(canDramenTeleport) { + val canDramenTeleport = inEquipment(player,Items.DRAMEN_STAFF_772) && getQuestStage(player, Quests.LOST_CITY) > 20 && isOutsideShed + if (canDramenTeleport) { var count = 0 - // pulser to handle the teleport. after 2 ticks it checks if the player hasnt completed lost city; if so, then it finishes the quest after the teleport + // pulser to handle the teleport. after 2 ticks it checks if the player hasn't completed Lost City; if so, then it finishes the quest after the teleport GameWorld.Pulser.submit(object : Pulse(2) { override fun pulse(): Boolean { when (count++) { @@ -44,9 +44,9 @@ class LostCityListeners : InteractionListener { teleport(player, Location(2452, 4473, 0), TeleportType.FAIRY_RING) } } - 1 -> return isQuestComplete(player,quest) + 1 -> return isQuestComplete(player, Quests.LOST_CITY) 2 -> { - finishQuest(player,quest) + finishQuest(player, Quests.LOST_CITY) return true } } @@ -66,8 +66,8 @@ class LostCityListeners : InteractionListener { if (removeItem(player, Item(Items.DRAMEN_BRANCH_771, 1), Container.INVENTORY)) { sendDialogue(player,"You carve the branch into a staff.") addItem(player, Items.DRAMEN_STAFF_772, 1, Container.INVENTORY) - } } + } return@onUseWith true } } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/ShamusDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/ShamusDialogue.kt index 8a3e0baf2..15800e2f7 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/ShamusDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/ShamusDialogue.kt @@ -5,6 +5,7 @@ import core.plugin.Initializable import org.rs09.consts.NPCs import core.api.getQuestStage import core.api.setQuestStage +import content.data.Quests /** * ShamusDialogue, to handle the dialogue of Shamus the Leprechaun from the Lost City quest @@ -13,9 +14,6 @@ import core.api.setQuestStage */ @Initializable class ShamusDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { - - val quest = "Lost City" - override fun open(vararg args: Any?): Boolean { npcl(core.game.dialogue.FacialExpression.ANNOYED,"Ay yer big elephant! Yer've caught me, to be sure! What would an elephant like yer be wanting wid ol' Shamus then?") stage = 0 @@ -23,7 +21,7 @@ class ShamusDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(getQuestStage(player,quest)) { + when(getQuestStage(player, Quests.LOST_CITY)) { 0 -> when(stage++) { 0 -> playerl(core.game.dialogue.FacialExpression.THINKING, "I'm not sure.") 1 -> npcl(core.game.dialogue.FacialExpression.ANNOYED,"Well you'll have to be catchin' me again when yer are, elephant!") @@ -45,7 +43,7 @@ class ShamusDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin 12 -> end().also { ShamusTreeListener.disappearShamus() sendDialogue("The leprechaun magically disappears.") - setQuestStage(player,quest,20) + setQuestStage(player, Quests.LOST_CITY, 20) } } else -> when(stage++) { diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/TreeSpiritNPC.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/TreeSpiritNPC.kt index 0449ca69e..754a82d69 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/TreeSpiritNPC.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/TreeSpiritNPC.kt @@ -1,7 +1,6 @@ package content.region.misthalin.lumbridge.quest.lostcity import core.game.node.entity.Entity -import core.game.node.entity.combat.CombatStyle import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player import core.game.world.map.Location @@ -10,6 +9,7 @@ import org.rs09.consts.NPCs import core.api.getQuestStage import core.api.sendDialogue import core.api.setQuestStage +import content.data.Quests /** * TreeSpiritNPC class to handle the tree spirit that spawns out of the dramen tree @@ -47,9 +47,8 @@ class TreeSpiritNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, l override fun finalizeDeath(killer: Entity) { super.finalizeDeath(killer) if (killer is Player) { - val quest = "Lost City" - if (getQuestStage(killer,quest) == 20) { - setQuestStage(killer,quest,21) + if (getQuestStage(killer, Quests.LOST_CITY) == 20) { + setQuestStage(killer, Quests.LOST_CITY,21) sendDialogue(killer, "With the Tree Spirit defeated you can now chop the tree.") } } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/WarriorDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/WarriorDialogue.kt index a82989f47..9281c9153 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/WarriorDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/lostcity/WarriorDialogue.kt @@ -7,6 +7,7 @@ import core.game.dialogue.Topic import core.tools.END_DIALOGUE import core.api.getQuestStage import core.api.startQuest +import content.data.Quests /** * WarriorDialogue, to handle the dialogue for the Warrior in the Lost City quest @@ -17,7 +18,7 @@ import core.api.startQuest class WarriorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { - when(getQuestStage(player,"Lost City")) { + when(getQuestStage(player,Quests.LOST_CITY)) { 10 -> playerl(core.game.dialogue.FacialExpression.THINKING,"So let me get this straight: I need to search the trees around here for a leprechaun; and then when I find him, he will tell me where this 'Zanaris' is?").also { stage = 1000 } 20, 21 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Have you found anything yet?").also { stage = 2000 } 100 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Hey, thanks for all the information. It REALLY helped me out in finding the lost city of Zanaris and all.").also { stage = 3000 } @@ -49,7 +50,7 @@ class WarriorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugi 6 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"So a leprechaun knows where Zanaris is eh?").also { stage = 600 } 7 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Thanks for the help!").also { stage = 700 } 8 -> end().also { - startQuest(player,"Lost City") + startQuest(player,Quests.LOST_CITY) } 100 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We're looking for Zanaris...GAH! I mean we're not here for any particular reason at all.").also { stage = 3 } 101 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL,"Well we're on an adventure right now. Mind you, this is OUR adventure and we don't want to share it - find your own!").also { stage = 2 } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/DukeHoracioRMDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/DukeHoracioRMDialogue.kt index 7eb8b9547..42ad4fa36 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/DukeHoracioRMDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/DukeHoracioRMDialogue.kt @@ -6,6 +6,7 @@ import core.game.node.item.Item import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests class DukeHoracioRMDialogue(val questStage: Int) : DialogueFile() { @@ -29,7 +30,7 @@ class DukeHoracioRMDialogue(val questStage: Int) : DialogueFile() { 10 -> npc("Thank you very much, stranger. I am sure the head", "wizard will reward you for such an interesting find.").also { stage++ } 11 -> { interpreter!!.sendDialogue("The Duke hands you an " + Quest.BLUE + "air talisman.").also { stage++ } - player!!.questRepository.getQuest("Rune Mysteries").start(player) + player!!.questRepository.getQuest(Quests.RUNE_MYSTERIES).start(player) if (!player!!.inventory.add(TALISMAN)) { GroundItemManager.create(TALISMAN, player!!.location, player) } diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/RuneMysteries.java b/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/RuneMysteries.java index ebe46af39..85e329907 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/RuneMysteries.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/runemysteries/RuneMysteries.java @@ -3,6 +3,7 @@ package content.region.misthalin.lumbridge.quest.runemysteries; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the rune mysteries fortress quest. @@ -15,7 +16,7 @@ public class RuneMysteries extends Quest { * Constructs a new {@code RuneMysteries} {@code Object}. */ public RuneMysteries() { - super("Rune Mysteries", 27, 26, 1, 63, 0, 1, 6); + super(Quests.RUNE_MYSTERIES, 27, 26, 1, 63, 0, 1, 6); } @Override diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SSFredTheFarmerDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SSFredTheFarmerDialogue.kt index 9392a5926..12a1af387 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SSFredTheFarmerDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SSFredTheFarmerDialogue.kt @@ -6,6 +6,7 @@ import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.Items +import content.data.Quests class SSFredTheFarmerDialogue(val questStage: Int) : DialogueFile() { companion object { @@ -58,7 +59,7 @@ class SSFredTheFarmerDialogue(val questStage: Int) : DialogueFile() { 2000 -> { // NOTE: In a July 2009 video, this only happens when the dialogue ends - startQuest(player!!, "Sheep Shearer") + startQuest(player!!, Quests.SHEEP_SHEARER) npc(FacialExpression.NEUTRAL, "Good! Now one more thing, do you actually know how", "to shear a sheep?").also { stage++ } } 2001 -> options("Of course!", "Err. No, I don't know actually.").also { stage++ } @@ -150,7 +151,7 @@ class SSFredTheFarmerDialogue(val questStage: Int) : DialogueFile() { 30101 -> { val ballsOfWoolDelivered = SheepShearer.deliverBallsOfWool(player!!) if (SheepShearer.getBallsOfWoolRequired(player!!) == 0) { - setQuestStage(player!!, "Sheep Shearer", 90) + setQuestStage(player!!, Quests.SHEEP_SHEARER, 90) player(FacialExpression.HAPPY, "That's the last of them.").also { stage = 30300 } } else { sendDialogue(player!!, "You give Fred $ballsOfWoolDelivered balls of wool").also { stage = 30200 } @@ -162,7 +163,7 @@ class SSFredTheFarmerDialogue(val questStage: Int) : DialogueFile() { 30202 -> player(FacialExpression.NEUTRAL, "Ok I'll work on it.").also { stage = END_DIALOGUE } 30300 -> npc(FacialExpression.SAD, "I guess I'd better pay you then.").also { stage++ } - STAGE_FINISH_QUEST -> finishQuest(player!!, "Sheep Shearer").also { stage = END_DIALOGUE } + STAGE_FINISH_QUEST -> finishQuest(player!!, Quests.SHEEP_SHEARER).also { stage = END_DIALOGUE } 31000 -> npc(FacialExpression.NEUTRAL, "You need to collect ${SheepShearer.getBallsOfWoolRequired(player!!)} more balls of wool.").also { stage++ } 31001 -> { diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SheepShearer.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SheepShearer.kt index a30669774..634041363 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SheepShearer.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/sheepshearer/SheepShearer.kt @@ -8,9 +8,10 @@ import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items import kotlin.math.min +import content.data.Quests @Initializable -class SheepShearer : Quest("Sheep Shearer", 28, 27, 1, 179, 0, 20, 21) { +class SheepShearer : Quest(Quests.SHEEP_SHEARER, 28, 27, 1, 179, 0, 20, 21) { companion object { val ATTR_NUM_BALLS_OF_WOOL_DELIVERED = "/save:sheep-shearer:num-balls-of-wool-delivered" val ATTR_IS_PENGUIN_SHEEP_SHEARED = "/save:sheep-shearer:is-penguin-sheep-sheared" diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt index c319e4988..b5a2a1685 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/JunaDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.tearsofguthix +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -32,7 +33,7 @@ class JunaDialogue : InteractionListener { class JunaDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(TearsOfGuthix.questName, 0) + b.onQuestStages(Quests.TEARS_OF_GUTHIX, 0) .branch { player -> if(TearsOfGuthix.hasRequirements(player)) { 1 } else { 0 } } .let { branch -> branch.onValue(0) @@ -67,8 +68,8 @@ class JunaDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.OLD_NORMAL,"There is a cave on the south side of the chasm that is similarly infused with the power of Guthix. The stone in that cave is the only substance that can catch the Tears of Guthix.") .npcl(FacialExpression.OLD_NORMAL,"Mine some stone from that cave, make it into a bowl, and bring it to me, and then I will let you catch the Tears.") .endWith { _, player -> - if(getQuestStage(player, TearsOfGuthix.questName) == 0) { - setQuestStage(player, TearsOfGuthix.questName, 1) + if(getQuestStage(player, Quests.TEARS_OF_GUTHIX) == 0) { + setQuestStage(player, Quests.TEARS_OF_GUTHIX, 1) } } @@ -92,7 +93,7 @@ class JunaDialogueFile : DialogueBuilderFile() { } - b.onQuestStages(TearsOfGuthix.questName, 1) + b.onQuestStages(Quests.TEARS_OF_GUTHIX, 1) .npc(FacialExpression.OLD_NORMAL, "Before you can collect the Tears of Guthix you must", "make a bowl out of the stone in the cave on the south", "of the chasm.") .branch { player -> if(inInventory(player, Items.STONE_BOWL_4704)) { 1 } else { 0 } } .let{ branch -> @@ -131,11 +132,11 @@ class JunaDialogueFile : DialogueBuilderFile() { .npcl(FacialExpression.OLD_NORMAL, "Now... tell me another story, and I will let you collect the tears for the first time.") .endWith { _, player -> if (removeItem(player, Items.STONE_BOWL_4704)) { - finishQuest(player, TearsOfGuthix.questName) + finishQuest(player, Quests.TEARS_OF_GUTHIX) } } - b.onQuestStages(TearsOfGuthix.questName, 100) + b.onQuestStages(Quests.TEARS_OF_GUTHIX, 100) .npcl(FacialExpression.OLD_NORMAL, "Tell me... a story...") .let { builder -> val returnJoin = b.placeholder() diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt index a27e2ba22..52a859bb3 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthix.kt @@ -1,12 +1,12 @@ package content.region.misthalin.lumbridge.quest.tearsofguthix +import content.data.Quests import core.api.* import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items -import java.util.* /** * Tears of Guthix Quest @@ -17,10 +17,9 @@ import java.util.* * if (VARPBIT[451] > 1) return 2; if (VARPBIT[451] == 0) return 0; return 1; }; if (arg0 == 88) */ @Initializable -class TearsOfGuthix : Quest("Tears of Guthix", 120, 119, 1, 449, 451, 0, 1, 2) { +class TearsOfGuthix : Quest(Quests.TEARS_OF_GUTHIX, 120, 119, 1, 449, 451, 0, 1, 2) { companion object { - const val questName = "Tears of Guthix" const val attributePreviousDate = "/save:quest:tearsofguthix-previousdateofaccess" // The date in milliseconds in which TOG was played. const val attributePreviousXPAmount = "/save:quest:tearsofguthix-previousxpamount" // The last snapshot of XP user had. const val attributePreviousQuestPoints = "/save:quest:tearsofguthix-previousquestpoints" // The last snapshot of quest points user had. @@ -63,7 +62,7 @@ class TearsOfGuthix : Quest("Tears of Guthix", 120, 119, 1, 449, 451, 0, 1, 2) { var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.TEARS_OF_GUTHIX) > 0 if (!started) { line(player, "I can start this quest by speaking to !!Juna the serpent?? who", line++, false) diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt index ef5477186..bd7c48800 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixListeners.kt @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.tearsofguthix +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.interaction.IntType @@ -105,7 +106,7 @@ class TearsOfGuthixListeners : InteractionListener { } onUseWith(NPC, Items.SAPPHIRE_LANTERN_4702, NPCs.LIGHT_CREATURE_2021) { player, used, with -> - if (hasRequirement(player, "While Guthix Sleeps")) { + if (hasRequirement(player, Quests.WHILE_GUTHIX_SLEEPS)) { // Options when you have WGS - B6KHH7AQc2Q openDialogue(player, object : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt index cda71126e..ab27cbd71 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/tearsofguthix/TearsOfGuthixMinigame.kt @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.tearsofguthix +import content.data.Quests import core.api.* import core.game.component.Component import core.game.event.EventHook @@ -102,15 +103,15 @@ class TearsOfGuthixMinigame : InteractionListener, EventHook, MapArea acc } // If you don't have Druidic Ritual completed, you cannot earn xp on it. - else if (curr == Skills.HERBLORE && !isQuestComplete(player, "Druidic Ritual")) { + else if (curr == Skills.HERBLORE && !isQuestComplete(player, Quests.DRUIDIC_RITUAL)) { acc } // If you don't have Rune Mysteries, you cannot earn xp on it. - else if (curr == Skills.RUNECRAFTING && !isQuestComplete(player, "Rune Mysteries")) { + else if (curr == Skills.RUNECRAFTING && !isQuestComplete(player, Quests.RUNE_MYSTERIES)) { acc } // If you don't have Wolf Whistle, you cannot earn xp on it. - else if (curr == Skills.SUMMONING && !isQuestComplete(player, "Wolf Whistle")) { + else if (curr == Skills.SUMMONING && !isQuestComplete(player, Quests.WOLF_WHISTLE)) { acc } else if (player.skills.getExperience(acc) <= player.skills.getExperience(curr)) { diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherAereckDialogue.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherAereckDialogue.java index c301fc637..acf0ca8c2 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherAereckDialogue.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherAereckDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.diary.DiaryType; import core.plugin.Initializable; import core.game.node.entity.player.Player; import core.game.dialogue.DialoguePlugin; +import content.data.Quests; /** @@ -42,7 +43,7 @@ public final class FatherAereckDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - int questStage = player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player); + int questStage = player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player); if (questStage == 10) { npc("Have you got rid of the ghost yet?"); stage = 520; @@ -72,7 +73,7 @@ public final class FatherAereckDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().isComplete("The Restless Ghost")) { + if (player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST)) { interpreter.sendOptions("What would you like to say?", "Can you change my gravestone now?", "Who's Saradomin?", "Nice place you've got here."); stage = 1; } else { @@ -128,7 +129,7 @@ public final class FatherAereckDialogue extends DialoguePlugin { end(); break; case 510: - player.getQuestRepository().getQuest(RestlessGhost.NAME).start(player); + player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).start(player); player.getQuestRepository().syncronizeTab(player); npc("Thank you. The problem is, there is a ghost in the", "church graveyard. I would like you to get rid of it."); stage = 511; diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherUhrneyDialogue.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherUhrneyDialogue.java index abedfb9a0..1097d1d5e 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherUhrneyDialogue.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/FatherUhrneyDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.therestlessghost; +import content.data.Quests; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.diary.DiaryType; @@ -49,13 +50,13 @@ public final class FatherUhrneyDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) == 0) { + if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) == 0) { options("Well, that's friendly.", "I've come to respossess your house."); stage = 1; - } else if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) == 10) { + } else if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) == 10) { options("Well, that's friendly.", "I've come to respossess your house.", "Father Aereck sent me to talk to you."); stage = 500; - } else if (player.getGameAttributes().getAttributes().containsKey("restless-ghost:urhney") || player.getQuestRepository().isComplete(RestlessGhost.NAME)) { + } else if (player.getGameAttributes().getAttributes().containsKey("restless-ghost:urhney") || player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST)) { options("Well, that's friendly.", "I've come to respossess your house.", "I've lost the Amulet of Ghostspeak."); stage = 514; } @@ -112,7 +113,7 @@ public final class FatherUhrneyDialogue extends DialoguePlugin { } interpreter.sendItemMessage(552, "Father Urhney hands you an amulet."); player.getInventory().add(new Item(552, 1)); - player.getQuestRepository().getQuest(RestlessGhost.NAME).setStage(player, 20); + player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).setStage(player, 20); player.getGameAttributes().setAttribute("/save:restless-ghost:urhney", true); stage = 509; break; diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhost.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhost.java index ccf60a649..11fd553b1 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhost.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhost.java @@ -9,6 +9,7 @@ import core.plugin.Initializable; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -18,22 +19,16 @@ import static core.api.ContentAPIKt.*; */ @Initializable public class RestlessGhost extends Quest { - - /** - * The name of the quest. - */ - public static final String NAME = "The Restless Ghost"; - /** * The ghost speak amulet. */ public static final Item AMULET = new Item(552); - + /** * Constructs a new {@Code RestlessGhost} {@Code Object} */ public RestlessGhost() { - super(NAME, 25, 24, 1, 107, 0, 4, 5); + super(Quests.THE_RESTLESS_GHOST, 25, 24, 1, 107, 0, 4, 5); } @Override diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostDialogue.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostDialogue.java index b282450cd..41b9f046b 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostDialogue.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.therestlessghost; +import content.data.Quests; import core.game.node.entity.npc.NPC; import core.plugin.Initializable; import core.game.node.entity.player.Player; @@ -43,17 +44,17 @@ public class RestlessGhostDialogue extends DialoguePlugin { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Wooo wooo wooooo!"); stage = 1; } else { - if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) == 20) { + if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) == 20) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Not very good actually."); stage = 500; break; } - if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) == 30) { + if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) == 30) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "How are you doing finding my skull?"); stage = 520; break; } - if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) == 40) { + if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) == 40) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "How are you doing finding my skull?"); stage = 550; break; @@ -111,7 +112,7 @@ public class RestlessGhostDialogue extends DialoguePlugin { break; case 511: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Ok. I will try and get the skull back for you, then you", "can rest in peace."); - player.getQuestRepository().getQuest(RestlessGhost.NAME).setStage(player, 30); + player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).setStage(player, 30); stage = 512; break; case 512: diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostPlugin.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostPlugin.java index 15e31d74a..d19f260a1 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostPlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostPlugin.java @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.therestlessghost; +import content.data.Quests; import core.cache.def.impl.SceneryDefinition; import core.game.interaction.OptionHandler; import core.game.node.Node; @@ -106,11 +107,11 @@ public final class RestlessGhostPlugin extends OptionHandler { searchAltar(player, object); break; case 15051: - if (!player.getQuestRepository().isComplete(RestlessGhost.NAME) && !player.getBank().containsItem(SKULL) && !player.getInventory().containsItem(SKULL)) { + if (!player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST) && !player.getBank().containsItem(SKULL) && !player.getInventory().containsItem(SKULL)) { player.getInventory().add(SKULL); player.getPacketDispatch().sendMessage("You find another skull."); } - player.getQuestRepository().getQuest(RestlessGhost.NAME).setStage(player, 40); + player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).setStage(player, 40); break; case 2145: toggleCoffin(player, object); @@ -132,7 +133,7 @@ public final class RestlessGhostPlugin extends OptionHandler { player.animate(open ? OPEN_ANIM : CLOSE_ANIM); SceneryBuilder.replace(object, object.transform(open ? 15061 : 2145)); player.getPacketDispatch().sendMessage("You " + (open ? "open" : "close") + " the coffin."); - if (open && !player.getQuestRepository().isComplete(RestlessGhost.NAME)) { + if (open && !player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST)) { sendGhost(); } } @@ -161,7 +162,7 @@ public final class RestlessGhostPlugin extends OptionHandler { */ private void searchAltar(final Player player, final Scenery object) { final boolean hasSkull = object.getId() == 15051; - if (player.getQuestRepository().getQuest(RestlessGhost.NAME).getStage(player) != 30) { + if (player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).getStage(player) != 30) { player.getPacketDispatch().sendMessage("You search the altar and find nothing."); return; } @@ -170,7 +171,7 @@ public final class RestlessGhostPlugin extends OptionHandler { GroundItemManager.create(SKULL, player); } setVarp(player, 728, 5, true); - player.getQuestRepository().getQuest(RestlessGhost.NAME).setStage(player, 40); + player.getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).setStage(player, 40); player.getPacketDispatch().sendMessage("The skeleton in the corner suddenly comes to life!"); sendSkeleton(player); } @@ -259,7 +260,7 @@ public final class RestlessGhostPlugin extends OptionHandler { if (this.getRespawnTick() > GameWorld.getTicks()) { return true; } - return player.getQuestRepository().isComplete(RestlessGhost.NAME) || (pl != null && player != pl); + return player.getQuestRepository().isComplete(Quests.THE_RESTLESS_GHOST) || (pl != null && player != pl); } @Override diff --git a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostSkull.java b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostSkull.java index 58bb7d0b1..4a899c64a 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostSkull.java +++ b/Server/src/main/content/region/misthalin/lumbridge/quest/therestlessghost/RestlessGhostSkull.java @@ -1,5 +1,6 @@ package content.region.misthalin.lumbridge.quest.therestlessghost; +import content.data.Quests; import core.api.Container; import core.game.interaction.NodeUsageEvent; import core.game.interaction.UseWithHandler; @@ -42,7 +43,7 @@ public final class RestlessGhostSkull extends UseWithHandler { } if (removeItem(event.getPlayer(), Items.SKULL_964, Container.INVENTORY)) { event.getPlayer().getPacketDispatch().sendMessage("You put the skull in the coffin."); - event.getPlayer().getQuestRepository().getQuest(RestlessGhost.NAME).finish(event.getPlayer()); + event.getPlayer().getQuestRepository().getQuest(Quests.THE_RESTLESS_GHOST).finish(event.getPlayer()); } return true; } diff --git a/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBane.java b/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBane.java index 3cc8a184c..91f1f33ef 100644 --- a/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBane.java +++ b/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBane.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.content.quest.members.asoulsbane.SoulsBaneLaunaDialogue; import core.plugin.PluginManager; +import content.data.Quests; */ /** @@ -14,10 +15,8 @@ import core.plugin.PluginManager; @Initializable public class ASoulsBane extends Quest { - public static final String NAME = "A Soul's Bane"; - public ASoulsBane() { - super(NAME, 115, 114, 1, 709, 0, 1, 1261); + super(Quests.A_SOULS_BANE, 115, 114, 1, 709, 0, 1, 1261); } // config 710 does a lot of shit diff --git a/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBaneListeners.kt b/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBaneListeners.kt index 1813665e6..256c7e17d 100644 --- a/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBaneListeners.kt +++ b/Server/src/main/content/region/misthalin/quest/asoulsbane/ASoulsBaneListeners.kt @@ -4,6 +4,7 @@ import core.api.* import core.game.interaction.InteractionListener import core.game.world.map.Location import org.rs09.consts.Scenery +import content.data.Quests // Temporary access since the monsters in there drop nothing. class ASoulsBaneListener : InteractionListener { @@ -13,7 +14,7 @@ class ASoulsBaneListener : InteractionListener { } override fun defineListeners() { on(RIFT_IDS, SCENERY, "enter") { player, _ -> - if (hasRequirement(player, "A Soul's Bane")) { + if (hasRequirement(player, Quests.A_SOULS_BANE)) { teleport(player, Location(3297, 9824, 0)) } return@on true diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/DoorPerilDialogue.java b/Server/src/main/content/region/misthalin/quest/priestinperil/DoorPerilDialogue.java index 9731861ef..c21b288a8 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/DoorPerilDialogue.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/DoorPerilDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.scenery.Scenery; +import content.data.Quests; /** * Represents the door peril dialogue. @@ -46,7 +47,7 @@ public final class DoorPerilDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { door = (Scenery) args[0]; - Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); if (quest.getStage(player) == 10) { interpreter.sendDialogue("You knock at the door...You hear a voice from inside.", "Who are you, and what do you want?"); stage = 0; @@ -106,7 +107,7 @@ public final class DoorPerilDialogue extends DialoguePlugin { stage = 10; break; case 10: - Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); quest.setStage(player, 11); end(); break; diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelDialogue.java b/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelDialogue.java index 5f1dc8b97..4d06a70d8 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelDialogue.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelDialogue.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for the drezel npc. @@ -49,7 +50,7 @@ public final class DrezelDialogue extends DialoguePlugin { npc = (NPC) args[0]; npc.setName("Drezel"); NPCDefinition.forId(getIds()[0]).setName("Drezel"); - Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); if (quest.getStage(player) == 13) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hello."); stage = 0; @@ -68,7 +69,7 @@ public final class DrezelDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + final Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); switch (stage) { case 0: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Oh! You do not appear to be on of those Zamorakians", "who imprisoned me here! Who are you and why are", "you here?"); @@ -369,7 +370,7 @@ public final class DrezelDialogue extends DialoguePlugin { stage = 802; break; case 802: - Quest quests = player.getQuestRepository().getQuest("Priest in Peril"); + Quest quests = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); quests.setStage(player, 17); end(); break; diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelMonumentDialogue.java b/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelMonumentDialogue.java index 20072af6c..06c77b5cc 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelMonumentDialogue.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/DrezelMonumentDialogue.java @@ -13,6 +13,7 @@ import org.rs09.consts.NPCs; import content.region.morytania.quest.naturespirit.NSDrezelDialogue; import static core.tools.DialogueConstKt.END_DIALOGUE; +import content.data.Quests; /** * Represents the dialogue plugin used for the drezel monument. @@ -52,7 +53,7 @@ public final class DrezelMonumentDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); if (quest.getStage(player) == 17) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ah, " + player.getUsername() + ". I see you finally made it down here.", "Things are worse than I feared. I'm not sure if I will", "be able to repair the damage."); stage = 900; @@ -79,7 +80,7 @@ public final class DrezelMonumentDialogue extends DialoguePlugin { stage = 420; }*/ - quest = player.getQuestRepository().getQuest("Nature Spirit"); + quest = player.getQuestRepository().getQuest(Quests.NATURE_SPIRIT); if(quest.getStage(player) <= 5){ interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings again adventurer, How go your travels in", "Morytania? Is it as evil as I have heard?"); @@ -95,7 +96,7 @@ public final class DrezelMonumentDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + final Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); switch (stage) { case 400: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ah, " + player.getUsername() + ". For all the assistance you have given", "both myself and Misthalin in your actions, I cannot let", "you pass without warning you."); diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/KingRoaldPIPDialogue.kt b/Server/src/main/content/region/misthalin/quest/priestinperil/KingRoaldPIPDialogue.kt index aba02ad76..d8f8f35d8 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/KingRoaldPIPDialogue.kt +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/KingRoaldPIPDialogue.kt @@ -3,6 +3,7 @@ package content.region.misthalin.quest.priestinperil import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests class KingRoaldPIPDialogue(val questStage: Int) : DialogueFile() { @@ -25,7 +26,7 @@ class KingRoaldPIPDialogue(val questStage: Int) : DialogueFile() { 8 -> when(buttonID){ 1 -> { player("Sure. I don't have anything better to do right now.") - player!!.questRepository.getQuest("Priest in Peril").start(player) + player!!.questRepository.getQuest(Quests.PRIEST_IN_PERIL).start(player) stage++ } 2 -> { @@ -58,7 +59,7 @@ class KingRoaldPIPDialogue(val questStage: Int) : DialogueFile() { 9 -> npc("You get back there and do whatever is necessary to", "safeguard my kingdom from attack, or I will see you", "beheaded for high treason!").also { stage++ } 10 -> { player("Y-yes your Highness.") - player!!.questRepository.getQuest("Priest in Peril").setStage(player,13) + player!!.questRepository.getQuest(Quests.PRIEST_IN_PERIL).setStage(player,13) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/MonkOfZamorakNPC.java b/Server/src/main/content/region/misthalin/quest/priestinperil/MonkOfZamorakNPC.java index c7811d7cd..9ca6c99be 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/MonkOfZamorakNPC.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/MonkOfZamorakNPC.java @@ -8,6 +8,7 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.plugin.Initializable; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the monk of zamorak npc. @@ -57,7 +58,7 @@ public final class MonkOfZamorakNPC extends AbstractNPC { public void finalizeDeath(final Entity killer) { super.finalizeDeath(killer); final Player p = ((Player) killer); - final Quest quest = p.getQuestRepository().getQuest("Priest in Peril"); + final Quest quest = p.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); if (quest.isStarted(p)) { GroundItemManager.create(GOLDEN_KEY, getLocation(), p); } diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPeril.java b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPeril.java index b123278b8..c14d08d0d 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPeril.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPeril.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the Quest priest in peril. @@ -18,7 +19,7 @@ public class PriestInPeril extends Quest { * Constructs a new {@code PriestInPeril} {@code Object}. */ public PriestInPeril() { - super("Priest in Peril", 99, 98, 1, 302, 0, 1, 100); + super(Quests.PRIEST_IN_PERIL, 99, 98, 1, 302, 0, 1, 100); } @Override diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java index efc682437..538afabc8 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilOptionPlugin.java @@ -15,6 +15,7 @@ import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; import org.rs09.consts.NPCs; +import content.data.Quests; /** * Represents the quest node plugin handler. @@ -93,7 +94,7 @@ public class PriestInPerilOptionPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Priest in Peril"); + final Quest quest = player.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); int id = node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); switch (option) { case "study": @@ -194,7 +195,7 @@ public class PriestInPerilOptionPlugin extends OptionHandler { break; case 3443: /** the barrier. */ - if (!player.getQuestRepository().isComplete("Priest in Peril")) { + if (!player.getQuestRepository().isComplete(Quests.PRIEST_IN_PERIL)) { player.getPacketDispatch().sendMessage("A magic force prevents you from passing through."); } else { player.getProperties().setTeleportLocation(Location.create(3425, 3485, 0)); diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt index dfc4e05fc..8a3b1c912 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt @@ -7,6 +7,7 @@ import org.rs09.consts.NPCs import org.rs09.consts.Scenery import core.game.interaction.IntType import core.game.interaction.InteractionListener +import content.data.Quests /** * Listener for Priest in Peril usage interactions @@ -101,7 +102,7 @@ class PriestInPerilUseListener : InteractionListener { return@onUseWith false } - setQuestStage(player, "Priest in Peril", 15) + setQuestStage(player, Quests.PRIEST_IN_PERIL, 15) sendMessage(player, "You have unlocked the cell door.") val npc = core.game.node.entity.npc.NPC.create(NPCs.DREZEL_7690, player.location) @@ -117,7 +118,7 @@ class PriestInPerilUseListener : InteractionListener { } addItem(player, Items.BUCKET_1925) - setQuestStage(player, "Priest in Peril", 16) + setQuestStage(player, Quests.PRIEST_IN_PERIL, 16) sendMessage(player, "You pour the blessed water over the coffin...") return@onUseWith true diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/TempleGuardianNPC.java b/Server/src/main/content/region/misthalin/quest/priestinperil/TempleGuardianNPC.java index c7bc48ebf..23dcd52c7 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/TempleGuardianNPC.java +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/TempleGuardianNPC.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.world.map.Location; +import content.data.Quests; /** * Handles the temple guardian npc. @@ -49,7 +50,7 @@ public class TempleGuardianNPC extends AbstractNPC { public void finalizeDeath(final Entity killer) { super.finalizeDeath(killer); final Player p = ((Player) killer); - final Quest quest = p.getQuestRepository().getQuest("Priest in Peril"); + final Quest quest = p.getQuestRepository().getQuest(Quests.PRIEST_IN_PERIL); if (quest.getStage(p) == 11) { quest.setStage(p, 12); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BatBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BatBehavior.kt index cd3590531..932997b5f 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BatBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BatBehavior.kt @@ -1,5 +1,6 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC @@ -20,7 +21,7 @@ class BatBehavior : NPCBehavior(*batIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Bat Wing during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.BAT_WING_7833)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BearBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BearBehavior.kt index 644372584..c489832bc 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BearBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BearBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.* import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -27,7 +27,7 @@ class BearBehavior : NPCBehavior(*bearIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Bear Ribs during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.BEAR_RIBS_7815)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BigFrogBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BigFrogBehavior.kt index f3aede96b..cd4cd6c4f 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BigFrogBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/BigFrogBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -21,7 +21,7 @@ class BigFrogBehavior : NPCBehavior(*bigFrogIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Big Frog Leg during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.BIG_FROG_LEG_7908)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantBatBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantBatBehavior.kt index bad83bbf6..0ffe43400 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantBatBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantBatBehavior.kt @@ -1,5 +1,6 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC @@ -29,7 +30,7 @@ class GiantBatBehavior : NPCBehavior(*giantBatIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Giant Bat Wing during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.GIANT_BAT_WING_7827)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantRatBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantRatBehavior.kt index ba1f06f82..b670f24de 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantRatBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GiantRatBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -35,7 +35,7 @@ class GiantRatBehavior : NPCBehavior(*giantRatIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Giant Rat Bone during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.GIANT_RAT_BONE_7824)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GoblinBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GoblinBehavior.kt index 168f3dcde..923b9a5ef 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GoblinBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/GoblinBehavior.kt @@ -1,11 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman -import content.global.handlers.npc.ChromaticDragonBehavior +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -179,7 +178,7 @@ class GoblinBehavior : NPCBehavior(*goblinIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Goblin Skull during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.GOBLIN_SKULL_7812)) } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/MonkeyBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/MonkeyBehavior.kt index 98c505819..2646a8676 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/MonkeyBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/MonkeyBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -45,7 +45,7 @@ class MonkeyBehavior : NPCBehavior(*monkeyIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Monkey Paw during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.MONKEY_PAW_7854)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/OddOldManDialogueFile.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/OddOldManDialogueFile.kt index 440a279b4..9351b6c1b 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/OddOldManDialogueFile.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/OddOldManDialogueFile.kt @@ -1,6 +1,6 @@ package content.region.misthalin.silvarea.quest.ragandboneman -import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau +import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression @@ -14,7 +14,7 @@ class OddOldManDialogueFile : DialogueFile() { // BONES_3674 is the Sack on ODD_OLD_MAN_3670 // There are probably FacialExpressions for the bone sack, but that's too much work. override fun handle(componentID: Int, buttonID: Int) { - when (getQuestStage(player!!, RagAndBoneMan.questName)) { + when (getQuestStage(player!!, Quests.RAG_AND_BONE_MAN)) { 0 -> { when (stage) { START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "Can I help you with something?").also { stage++ } @@ -82,7 +82,7 @@ class OddOldManDialogueFile : DialogueFile() { 57 -> npcl(FacialExpression.FRIENDLY, "It takes a while for the vinegar to evaporate, but the bone will be nice and clean in the end.").also { stage++ } 58 -> playerl(FacialExpression.FRIENDLY, "All right, I'll be back later.").also { stage++ } 59 -> npcl(FacialExpression.FRIENDLY, "Bye!").also { - setQuestStage(player!!, RagAndBoneMan.questName, 1) + setQuestStage(player!!, Quests.RAG_AND_BONE_MAN, 1) stage = END_DIALOGUE } @@ -137,7 +137,7 @@ class OddOldManDialogueFile : DialogueFile() { 8 -> npcl(FacialExpression.FRIENDLY, "I'm always on the lookout for fresh bones, so if you see some bring them right over.").also { stage++ } 9 -> playerl(FacialExpression.FRIENDLY, "No problem, I'll be sure to bring anything you might like over if I find something.").also { stage++ } 10 -> playerl(FacialExpression.FRIENDLY, "I can't wait to see the displays once they are finished.").also { stage++ } - 11 -> finishQuest(player!!, RagAndBoneMan.questName).also { + 11 -> finishQuest(player!!, Quests.RAG_AND_BONE_MAN).also { end() } 20 -> playerl(FacialExpression.FRIENDLY, "Not at the moment. Can you just give me a run down on which bones I have left to get?").also { stage++ } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RagAndBoneMan.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RagAndBoneMan.kt index 0da5e32ec..97e5e9a35 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RagAndBoneMan.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RagAndBoneMan.kt @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Rag and Bone Man Quest @@ -24,9 +25,8 @@ import org.rs09.consts.Items * Quest Journal 2012 https://www.youtube.com/watch?v=0I8fNTeAwA8&t=764 */ @Initializable -class RagAndBoneMan : Quest("Rag and Bone Man",100, 99, 2, 714, 0, 1, 4) { +class RagAndBoneMan : Quest(Quests.RAG_AND_BONE_MAN,100, 99, 2, 714, 0, 1, 4) { companion object { - const val questName = "Rag and Bone Man" const val attributeGoblinBone = "/save:quest:ragandboneman-goblinbonesubmit" const val attributeBearBone = "/save:quest:ragandboneman-bearbonesubmit" const val attributeBigFrogBone = "/save:quest:ragandboneman-bigfrogbonesubmit" diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RamBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RamBehavior.kt index fa54dabbe..b98630ed6 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RamBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/RamBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.* import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -25,7 +25,7 @@ class RamBehavior : NPCBehavior(*ramIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Ram Skull during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.RAM_SKULL_7818)); } diff --git a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/UnicornBehavior.kt b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/UnicornBehavior.kt index 54f5ba15e..894f0261d 100644 --- a/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/UnicornBehavior.kt +++ b/Server/src/main/content/region/misthalin/silvarea/quest/ragandboneman/UnicornBehavior.kt @@ -1,10 +1,10 @@ package content.region.misthalin.silvarea.quest.ragandboneman +import content.data.Quests import core.api.isQuestInProgress import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPCBehavior -import core.game.node.entity.npc.drop.DropFrequency import core.game.node.entity.player.Player import core.game.node.item.Item import core.tools.RandomFunction @@ -23,7 +23,7 @@ class UnicornBehavior : NPCBehavior(*unicornIds) { override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { super.onDropTableRolled(self, killer, drops) // Drops the Unicorn Bone during Rag and Bone Man quest - if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) { + if (killer is Player && isQuestInProgress(killer, Quests.RAG_AND_BONE_MAN, 1, 99)) { if(RandomFunction.roll(4)) { drops.add(Item(Items.UNICORN_BONE_7821)); } diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/ApothecaryDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/ApothecaryDialogue.java index 73f8b00bc..d9ca490aa 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/ApothecaryDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/ApothecaryDialogue.java @@ -8,6 +8,7 @@ import core.game.node.item.GroundItem; import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for the apothecary npc. @@ -67,12 +68,12 @@ public final class ApothecaryDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - if (player.getQuestRepository().getQuest("Romeo & Juliet").getStage(player) == 40) { + if (player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(player) == 40) { interpreter.sendDialogues(player, null, "Apothecary. Father Lawrence sent me."); stage = 500; return true; } - if (player.getQuestRepository().getQuest("Romeo & Juliet").getStage(player) == 50) { + if (player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(player) == 50) { if (!player.getInventory().contains(753, 1)) { npc("Keep searching for those Cadava berries. They're needed", "for the potion."); stage = 507; @@ -83,7 +84,7 @@ public final class ApothecaryDialogue extends DialoguePlugin { return true; } } - if (player.getQuestRepository().getQuest("Romeo & Juliet").getStage(player) == 60) { + if (player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(player) == 60) { if (!player.getInventory().contains(756, 1) && !player.getBank().contains(756, 1)) { if (player.getInventory().contains(753, 1)) { npc("Well done. You have the berries."); @@ -237,7 +238,7 @@ public final class ApothecaryDialogue extends DialoguePlugin { stage = 506; break; case 506: - player.getQuestRepository().getQuest("Romeo & Juliet").setStage(player, 50); + player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).setStage(player, 50); interpreter.sendDialogues(player, null, "Ok, thanks."); stage = 507; break; @@ -262,7 +263,7 @@ public final class ApothecaryDialogue extends DialoguePlugin { stage = 640; break; case 640: - player.getQuestRepository().getQuest("Romeo & Juliet").setStage(player, 60); + player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).setStage(player, 60); end(); break; } diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/BaraekDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/BaraekDialogue.java index 953bd1b72..ab062f4b4 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/BaraekDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/BaraekDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for the baraek npc. @@ -61,7 +62,7 @@ public final class BaraekDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Shield of Arrav"); + quest = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); switch (quest.getStage(player)) { case 30: if (!player.getInventory().containsItem(FUR)) { diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/DrHarlowDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/DrHarlowDialogue.java index a906641b0..0e14e004f 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/DrHarlowDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/DrHarlowDialogue.java @@ -8,6 +8,7 @@ import core.game.node.item.GroundItem; import core.game.node.item.GroundItemManager; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue used for dr harlow. @@ -56,10 +57,10 @@ public final class DrHarlowDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (player.getQuestRepository().getQuest("Vampire Slayer").getStage(player) == 10) { + if (player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER).getStage(player) == 10) { interpreter.sendOptions("Select an Option", "No, you've had enough.", "Morgan needs your help!"); stage = 1; - } else if (player.getQuestRepository().getQuest("Vampire Slayer").getStage(player) == 20) { + } else if (player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER).getStage(player) == 20) { if (player.getInventory().contains(1917, 1)) { interpreter.sendDialogues(player, null, "Here you go."); stage = 20; @@ -67,7 +68,7 @@ public final class DrHarlowDialogue extends DialoguePlugin { interpreter.sendDialogues(player, null, "I'll just go and buy one."); stage = 2; } - } else if (player.getQuestRepository().getQuest("Vampire Slayer").getStage(player) == 30) { + } else if (player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER).getStage(player) == 30) { if (!player.getBank().contains(1549, 1) && !player.getInventory().contains(1549, 1)) { if (!player.getInventory().add(ITEMS[0])) { GroundItem item = new GroundItem(ITEMS[0], npc.getLocation(), player); @@ -122,7 +123,7 @@ public final class DrHarlowDialogue extends DialoguePlugin { stage = 10; break; case 10: - player.getQuestRepository().getQuest("Vampire Slayer").setStage(player, 20); + player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER).setStage(player, 20); end(); break; case 2: @@ -131,7 +132,7 @@ public final class DrHarlowDialogue extends DialoguePlugin { case 20: if (player.getInventory().remove(ITEMS[1])) { interpreter.sendItemMessage(1917, "You give a beer to Dr Harlow."); - player.getQuestRepository().getQuest("Vampire Slayer").setStage(player, 30); + player.getQuestRepository().getQuest(Quests.VAMPIRE_SLAYER).setStage(player, 30); stage = 21; } break; diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/FatherLawrenceDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/FatherLawrenceDialogue.java index 6e45fa50c..db0f198ad 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/FatherLawrenceDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/FatherLawrenceDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the father lawrence dialogue plugin. @@ -35,7 +36,7 @@ public final class FatherLawrenceDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - final Quest quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); if (quest.getStage(player) < 30) { interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Oh to be a father in the times of whiskey."); stage = 0; @@ -68,7 +69,7 @@ public final class FatherLawrenceDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); switch (stage) { case 0: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I sing and I drink and I wake up in gutters."); diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudeDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudeDialogue.java index 531243cb8..9fcbd6bb2 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudeDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudeDialogue.java @@ -1,7 +1,6 @@ package content.region.misthalin.varrock.dialogue; import content.global.skill.summoning.pet.Pet; -import content.global.skill.summoning.pet.PetDetails; import core.game.container.Container; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -13,10 +12,9 @@ import core.plugin.Initializable; import core.tools.RandomFunction; import org.rs09.consts.Items; -import java.util.Map; +import content.data.Quests; -import static core.api.ContentAPIKt.freeSlots; -import static core.api.ContentAPIKt.inInventory; +import static core.api.ContentAPIKt.*; /** * Represents the gertrude dialogue plugin. @@ -56,8 +54,7 @@ public final class GertrudeDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); - switch (quest.getStage(player)) { + switch (getQuestStage(player, Quests.GERTRUDES_CAT)) { case 0: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello, are you OK?"); break; @@ -95,7 +92,7 @@ public final class GertrudeDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 0: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Do I look OK? Those kids drive me crazy."); diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudesCatDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudesCatDialogue.java index edca24e12..93d5a003e 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudesCatDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/GertrudesCatDialogue.java @@ -8,6 +8,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.plugin.Initializable; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the gertrude cat dialogue plugin. @@ -53,7 +54,7 @@ public final class GertrudesCatDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 545: end(); diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/KingRoaldDialogue.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/KingRoaldDialogue.kt index b4e0f7ecf..1f775acc6 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/KingRoaldDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/KingRoaldDialogue.kt @@ -11,6 +11,7 @@ import content.region.misthalin.quest.priestinperil.KingRoaldPIPDialogue import core.tools.DIALOGUE_INITIAL_OPTIONS_HANDLE import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests /** * Central dialogue plugin for King Roald. Reroutes to the more specific DialogueFiles @@ -32,15 +33,15 @@ class KingRoaldDialogue(player: Player? = null) : DialoguePlugin(player) { return true } - if(player.questRepository.isComplete("Priest in Peril")) { - if (!player.questRepository.hasStarted("All Fired Up") || player.questRepository.getQuest("All Fired Up").getStage(player) == 90) { - addOption("All Fired Up", KingRoaldAFUDialogue(player.questRepository.getStage("All Fired Up"))) + if(player.questRepository.isComplete(Quests.PRIEST_IN_PERIL)) { + if (!player.questRepository.hasStarted(Quests.ALL_FIRED_UP) || player.questRepository.getQuest(Quests.ALL_FIRED_UP).getStage(player) == 90) { + addOption("All Fired Up", KingRoaldAFUDialogue(player.questRepository.getStage(Quests.ALL_FIRED_UP))) } } else { - addOption("Priest in Peril", KingRoaldPIPDialogue(player.questRepository.getStage("Priest in Peril"))) + addOption("Priest in Peril", KingRoaldPIPDialogue(player.questRepository.getStage(Quests.PRIEST_IN_PERIL))) } - if (player.questRepository.getQuest("Shield of Arrav").isStarted(player) && !player.questRepository.getQuest("Shield of Arrav").isCompleted(player)) { + if (player.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).isStarted(player) && !player.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).isCompleted(player)) { addOption("Shield of Arrav", KingRoaldArravDialogue()) } diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt index 332ee4407..6880892b7 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/MuseumGuardsDialoguePlugin.kt @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.dialogue +import content.data.Quests import content.region.misthalin.varrock.handlers.MuseumInteractionListener.Companion.handleMuseumDoor import core.api.forceWalk import core.api.getScenery @@ -27,7 +28,7 @@ class DoorGuardDialogue(player: Player? = null) : DialoguePlugin(player) { 1 -> npcl(FacialExpression.NEUTRAL, "Well, the main entrance is 'round the front. Just head west then north slightly, you can't miss it!").also { stage++ } 2 -> playerl(FacialExpression.NEUTRAL, "What about these doors?").also { stage++ } 3 -> { - if (isQuestComplete(player, "The Dig Site")) { + if (isQuestComplete(player, Quests.THE_DIG_SITE)) { npcl(FacialExpression.NEUTRAL, "They're primarily for the workmen bringing finds from the Dig Site, but you can go through if you want.").also { stage++ } } else { npcl(FacialExpression.NEUTRAL, "They're for the workmen bringing finds from the Dig Site; sorry, but you can't go through.").also { stage = END_DIALOGUE } @@ -57,7 +58,7 @@ class GateGuardDialogue(player: Player? = null) : DialoguePlugin(player) { // Shows the player walking to this spot first https://www.youtube.com/watch?v=t-oeY3a-ZSA&t=53s if (player.location != Location(3261, 3447)) forceWalk(player, Location(3261, 3447), "smart") - if (isQuestComplete(player, "The Dig Site")) { + if (isQuestComplete(player, Quests.THE_DIG_SITE)) { npcl(FacialExpression.NEUTRAL, "Welcome! Would you like to go into the Dig Site archaeology cleaning area?").also { stage = START_DIALOGUE } } else { npcl(FacialExpression.NEUTRAL, "You're not permitted in this area.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java index 7c875fd45..ea1614e55 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue plugin used for the shilop npc. @@ -55,7 +56,7 @@ public final class ShilopDialogue extends DialoguePlugin { } else if (args[0] instanceof Integer) { id = (Integer) args[0]; } - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (quest.getStage(player)) { case 0: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); @@ -82,7 +83,7 @@ public final class ShilopDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 0: interpreter.sendDialogues(id, FacialExpression.OLD_NORMAL, "You think you're tough do you?"); diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java index f25b6048d..61b1097c7 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.plugin.Initializable; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue used for wilough. @@ -55,7 +56,7 @@ public final class WiloughDialogue extends DialoguePlugin { } else if (args[0] instanceof Integer) { id = (int) args[0]; } - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (quest.getStage(player)) { case 0: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); @@ -82,7 +83,7 @@ public final class WiloughDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 0: interpreter.sendDialogues(id, FacialExpression.HALF_GUILTY, "You think you're tough do you?"); diff --git a/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt b/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt index 19a1f06aa..f49899210 100644 --- a/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt +++ b/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt @@ -21,6 +21,7 @@ import core.game.diary.DiaryLevel import core.game.event.* import core.game.node.entity.player.link.SpellBookManager import core.game.node.entity.skill.Skills +import content.data.Quests class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) { companion object { @@ -203,7 +204,7 @@ class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) { ) } - if (player.questRepository.isComplete("Dragon Slayer")) { + if (player.questRepository.isComplete(Quests.DRAGON_SLAYER)) { if (event.target.id == NPCs.OZIACH_747 && event.option == "trade" && inBorders(player, OZIACH_SHOP)) { finishTask( player, diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/LumberYardCratePlugin.java b/Server/src/main/content/region/misthalin/varrock/handlers/LumberYardCratePlugin.java index fc5c15e86..277d7d634 100644 --- a/Server/src/main/content/region/misthalin/varrock/handlers/LumberYardCratePlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/handlers/LumberYardCratePlugin.java @@ -14,6 +14,7 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; import core.tools.RandomFunction; +import content.data.Quests; /** * Represents the plugin used for handling a lumber yard crate. @@ -30,7 +31,7 @@ public final class LumberYardCratePlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (option) { case "squeeze-under": Location dest = null; diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/ZaffPlugin.kt b/Server/src/main/content/region/misthalin/varrock/handlers/ZaffPlugin.kt index 795b33ce1..1af2980f0 100644 --- a/Server/src/main/content/region/misthalin/varrock/handlers/ZaffPlugin.kt +++ b/Server/src/main/content/region/misthalin/varrock/handlers/ZaffPlugin.kt @@ -17,6 +17,7 @@ import org.json.simple.JSONObject import org.rs09.consts.Items import core.ServerStore import core.ServerStore.Companion.getInt +import content.data.Quests /** * Represents the plugin used for buying a battle staff from zeke. @@ -70,7 +71,7 @@ class ZaffPlugin : OptionHandler() { override fun open(vararg args: Any): Boolean { npc = args[0] as NPC - quest = player.questRepository.getQuest("What Lies Below") + quest = player.questRepository.getQuest(Quests.WHAT_LIES_BELOW) interpreter.sendDialogues( npc, core.game.dialogue.FacialExpression.HALF_GUILTY, diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt index f3e992ffc..29f85806b 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/AllFiredUp.kt @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.allfiredup +import content.data.Quests import content.minigame.allfiredup.AFUBeacon import core.api.setVarbit import core.game.node.entity.player.Player @@ -14,7 +15,7 @@ import org.rs09.consts.Items * @author Ceikry */ @Initializable -class AllFiredUp : Quest("All Fired Up", 157, 156, 1){ +class AllFiredUp : Quest(Quests.ALL_FIRED_UP, 157, 156, 1){ override fun newInstance(`object`: Any?): Quest { return this } @@ -29,7 +30,7 @@ class AllFiredUp : Quest("All Fired Up", 157, 156, 1){ line++ line(player, "To start this quest, I require:", line++) line(player, "!!43 Firemaking??", line++, player.skills.getLevel(Skills.FIREMAKING) >= 43) - line(player, "!!Completion of Priest in Peril??", line++, player.questRepository.isComplete("Priest in Peril")) + line(player, "!!Completion of Priest in Peril??", line++, player.questRepository.isComplete(Quests.PRIEST_IN_PERIL)) limitScrolling(player, line, true) } else { line(player, "I have agreed to help King Roald test the beacon network", line++, true) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/BlazeSharpeyeDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/BlazeSharpeyeDialogue.kt index 200749835..9f85e6603 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/BlazeSharpeyeDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/BlazeSharpeyeDialogue.kt @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -14,7 +15,7 @@ class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("All Fired Up") ?: -1 + val qstage = player?.questRepository?.getStage(Quests.ALL_FIRED_UP) ?: -1 when(qstage){ 0 -> player.dialogueInterpreter.sendDialogue("He seems uninterested in talking.").also { stage = 1000 } 10 -> player("So, what's going on?").also { stage = 100 } @@ -48,7 +49,7 @@ class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { 112 -> npc("Our technique is super-secret, but quite effective. All","you do is put twenty logs of the same type on a","beacon and...").also { stage++ } 113 -> npc(FacialExpression.AMAZED,"SET IT ON FIRE WITH A TINDERBOX!").also { stage++ } 114 -> player("You really enjoy your job, don't you?").also { stage++ } - 115 -> npc("Yes. Yes I do. Now, why don't you go over there and","try lighting that beacon. Show us what you've got.").also { stage++; player.questRepository.getQuest("All Fired Up").setStage(player,20) } + 115 -> npc("Yes. Yes I do. Now, why don't you go over there and","try lighting that beacon. Show us what you've got.").also { stage++; player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player,20) } 116 -> options("Does it matter what type of log I use?","Okay.").also { stage++ } 117 -> when(buttonId){ 1 -> player("Does it matter what type of log I use?").also { stage = 150 } @@ -61,7 +62,7 @@ class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { 201 -> npc("Well, apparently, not for someone of your Firemaking","calibre and expertise. Now that you've got the hang of","things, we can get this show on the road.").also { stage++ } 202 -> npc("If you'd be so kind as to light the beacon to the west","and report back to me, I can make sure I can clearly","see its glow on the horizon.").also { stage++ } 203 -> npc("It's near the limestone quarry, north-east of Varrock,","west of the Rag and Bone Man's hovel.").also { stage++ } - 204 -> npc("My colleague, Squire Fyre, is tending that beacon.","She'll help you out if you run into any trouble.").also { stage = 116; player.questRepository.getQuest("All Fired Up").setStage(player,40) } + 204 -> npc("My colleague, Squire Fyre, is tending that beacon.","She'll help you out if you run into any trouble.").also { stage = 116; player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player,40) } //Stage = 60 300 -> player("Can you really see it from this far away?").also { stage++ } @@ -69,7 +70,7 @@ class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { 302 -> npc("This beacon, however, is struggling at the moment.","Do you see how the fire has died down?").also { stage++ } 303 -> player("Hmm, yes. The fire is a bit smaller and the logs look","rather charred.").also { stage++ } 304 -> npc("If a beacon's fire starts to die down, you can restore it","to its blazing glory by adding five logs.").also { stage++ } - 305 -> npc("You wouldn't mind topping this one up for me, would","you? Oh, how I love to see things burn!").also { stage++; player.questRepository.getQuest("All Fired Up").setStage(player, 70) } + 305 -> npc("You wouldn't mind topping this one up for me, would","you? Oh, how I love to see things burn!").also { stage++; player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player, 70) } 306 -> options("Oh, alright, then.","Don't you have logs of your own you can use?").also { stage++ } 307 -> when(buttonId){ 1 -> player("Oh, alright, then.").also { stage++ } @@ -94,7 +95,7 @@ class BlazeSharpeyeDialogue(player: Player? = null) : DialoguePlugin(player) { 410 -> npc("Imminently, I'm sure - we're just waiting for the word","from King Roald. Speaking of which, have you reported","back to him about the progress we've made?").also { stage++ } 411 -> player("Not yet, I'm afraid.").also { stage++ } 412 -> npc("Well, what are you waiting for? This is a serious","matter! I'm sure King Roald is on the edge of his","throne, waiting for the news.").also { stage++ } - 413 -> player("I'll get right on that.").also { stage = 1000; player.questRepository.getQuest("All Fired Up").setStage(player,90) } + 413 -> player("I'll get right on that.").also { stage = 1000; player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player,90) } 420 -> npc("Yes... YES HAHAHAHA FIRE").also { stage = 412 } 1000 -> end() diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/KingRoaldAFUDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/KingRoaldAFUDialogue.kt index bd84874bc..4c5d4480a 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/KingRoaldAFUDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/KingRoaldAFUDialogue.kt @@ -4,6 +4,7 @@ import core.game.node.entity.skill.Skills import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests class KingRoaldAFUDialogue(val questStage: Int) : DialogueFile() { @@ -85,7 +86,7 @@ class KingRoaldAFUDialogue(val questStage: Int) : DialogueFile() { 17 -> { player("Thank you, Your Majesty. I'll seek out Blaze", "right away.") stage = END_DIALOGUE - player!!.questRepository.getQuest("All Fired Up").start(player) + player!!.questRepository.getQuest(Quests.ALL_FIRED_UP).start(player) } END_DIALOGUE -> end() @@ -103,7 +104,7 @@ class KingRoaldAFUDialogue(val questStage: Int) : DialogueFile() { 6 -> npc("There is much more to be done and this is but a", "pittance compared to what I'm willing to offer for", "further assistance!").also { stage++ } 7 -> { end() - player!!.questRepository.getQuest("All Fired Up").finish(player) + player!!.questRepository.getQuest(Quests.ALL_FIRED_UP).finish(player) } } } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/SquireFyreDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/SquireFyreDialogue.kt index ca33ddff3..606e784dc 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/SquireFyreDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/allfiredup/SquireFyreDialogue.kt @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import content.minigame.allfiredup.BeaconState import core.api.* +import content.data.Quests @Initializable class SquireFyreDialogue(player: Player? = null) : DialoguePlugin(player){ @@ -15,7 +16,7 @@ class SquireFyreDialogue(player: Player? = null) : DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player.questRepository.getQuest("All Fired Up").getStage(player) + val qstage = player.questRepository.getQuest(Quests.ALL_FIRED_UP).getStage(player) when(qstage){ 40 -> player("Hi there. I'm helping Blaze and King Roald test the","beacon network. Can you see it from here? Blaze said","you have pretty sharp eyes.").also { stage = 100 } else -> npc("Carry on, friend.").also { stage = 1000 } @@ -27,7 +28,7 @@ class SquireFyreDialogue(player: Player? = null) : DialoguePlugin(player){ when(stage){ 100 -> npc("Of course I can see it. I haven't spent my entire life","practising my seeing skills for nothing! I'm happy to","report that the fire near Blaze is burning brightly.").also { stage++ } 101 -> player("Terrific! Blaze has asked me to light this fire as well, so","he can see how things look from his vantage point.").also { stage++ } - 102 -> npc("Be my guest!").also { stage++; player.questRepository.getQuest("All Fired Up").setStage(player,50); setVarbit(player, 5146, BeaconState.DYING.ordinal) } + 102 -> npc("Be my guest!").also { stage++; player.questRepository.getQuest(Quests.ALL_FIRED_UP).setStage(player,50); setVarbit(player, 5146, BeaconState.DYING.ordinal) } 103 -> options("How do I light the beacon?","I suppose you don't have any logs I could have?","Okay, thanks.").also { stage++ } 104 -> when(buttonId){ 1 -> player("How do I light the beacon?").also { stage = 110 } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSCutsceneTrigger.kt b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSCutsceneTrigger.kt index 8ede2454c..d498fd07a 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSCutsceneTrigger.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSCutsceneTrigger.kt @@ -6,6 +6,7 @@ import core.game.activity.ActivityManager import core.game.node.entity.Entity import core.game.node.entity.player.Player import org.rs09.consts.Items +import content.data.Quests class DSCutsceneTrigger : MapArea { @@ -16,7 +17,7 @@ class DSCutsceneTrigger : MapArea { override fun areaEnter(entity: Entity) { if (entity !is Player) return - val quest = entity.questRepository.getQuest("Demon Slayer") + val quest = entity.questRepository.getQuest(Quests.DEMON_SLAYER) val alreadyInCutscene = getAttribute(entity, "demon-slayer:cutscene", false) val hasSilverlight = inInventory(entity, Items.SILVERLIGHT_2402) || inEquipment(entity, Items.SILVERLIGHT_2402) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSlayerDrainPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSlayerDrainPlugin.java index b8a37841a..253484745 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSlayerDrainPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DSlayerDrainPlugin.java @@ -11,6 +11,7 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -51,7 +52,7 @@ public final class DSlayerDrainPlugin extends UseWithHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest("Demon Slayer"); + final Quest quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); if (player.getInventory().remove(BUCKET_OF_WATER)) { player.getInventory().add(BUCKET); player.animate(ANIMATION); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayer.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayer.java index 2fc51558f..0492bb2a9 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayer.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayer.java @@ -12,6 +12,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the demon slayer quest. @@ -50,7 +51,7 @@ public class DemonSlayer extends Quest { * Constructs a new {@Code DemonSlayer} {@Code Object} */ public DemonSlayer() { - super("Demon Slayer", 16, 15, 3, 222, 0, 1, 3); + super(Quests.DEMON_SLAYER, 16, 15, 3, 222, 0, 1, 3); } @Override @@ -196,7 +197,7 @@ public class DemonSlayer extends Quest { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Demon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); switch (quest.getStage(player)) { default: interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What are you doing up here? Only the palace guards", "are allowed up here."); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerCutscene.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerCutscene.java index 7a90c6fd0..7c46309f0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerCutscene.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerCutscene.java @@ -30,6 +30,7 @@ import core.net.packet.out.CameraViewPacket; import core.net.packet.out.MinimapState; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the cutscene during the combat of fighting delrith the demon. @@ -121,7 +122,7 @@ public final class DemonSlayerCutscene extends CutscenePlugin { return true; } final Player player = ((Player) entity); - final Quest quest = player.getQuestRepository().getQuest("Demon Slayer"); + final Quest quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); boolean in = player.getAttribute("demon-slayer:cutscene", false); if (quest.getStage(player) == 30 && !in && (player.getEquipment().containsItem(DemonSlayer.SILVERLIGHT) || player.getInventory().containsItem(DemonSlayer.SILVERLIGHT))) { ActivityManager.start(player, "Demon Slayer Cutscene", false); @@ -422,7 +423,7 @@ public final class DemonSlayerCutscene extends CutscenePlugin { cutscene.end(); cutscene.delrith.clear(); setVarp(player, 222, 5653570, true); - player.getQuestRepository().getQuest("Demon Slayer").finish(player); + player.getQuestRepository().getQuest(Quests.DEMON_SLAYER).finish(player); end(); return true; } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java index b31d4a22b..87740d6df 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/DemonSlayerPlugin.java @@ -2,7 +2,6 @@ package content.region.misthalin.varrock.quest.demonslayer; import core.cache.def.impl.NPCDefinition; import core.cache.def.impl.SceneryDefinition; -import core.game.global.action.ClimbActionHandler; import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.npc.NPC; @@ -10,12 +9,11 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; import core.game.world.map.Location; -import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -46,7 +44,7 @@ public final class DemonSlayerPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Demon Slayer"); + final Quest quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); final int id = node instanceof Scenery ? ((Scenery) node).getId() : node instanceof Item ? ((Item) node).getId() : ((NPC) node).getId(); switch (id) { case 880: diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/GypsyArisDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/GypsyArisDialogue.java index 3e318c85c..7d0c85262 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/GypsyArisDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/GypsyArisDialogue.java @@ -17,6 +17,7 @@ import core.net.packet.PacketRepository; import core.net.packet.context.CameraContext; import core.net.packet.context.CameraContext.CameraType; import core.net.packet.out.CameraViewPacket; +import content.data.Quests; /** * Represents the dialogue which handles the transcript for the gypsy aris. @@ -75,7 +76,7 @@ public final class GypsyArisDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Demon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); switch (quest.getStage(player)) { case 100: npc("Greetings young one."); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/SirPyrsinDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/SirPyrsinDialogue.java index a0fc32221..8be176a64 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/SirPyrsinDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/SirPyrsinDialogue.java @@ -1,6 +1,5 @@ package content.region.misthalin.varrock.quest.demonslayer; -import content.region.misthalin.draynor.handlers.DraynorNodePlugin; import core.api.Container; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; @@ -16,6 +15,7 @@ import org.rs09.consts.Items; import static core.api.ContentAPIKt.*; import static core.tools.DialogueConstKt.END_DIALOGUE; import static core.tools.GlobalsKt.colorize; +import content.data.Quests; /** * Represents the dialogue which handles the Sir Prysin NPC. @@ -64,7 +64,7 @@ public class SirPyrsinDialogue extends DialoguePlugin { } else if (args[0] instanceof Integer) { id = ((int) args[0]); } - quest = player.getQuestRepository().getQuest("Demon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); switch (quest.getStage(player)) { case 30: npc(id, "Have you sorted that demon out yet?"); @@ -481,7 +481,7 @@ public class SirPyrsinDialogue extends DialoguePlugin { private final void handleDefault(int buttonId) { switch (stage) { case 0: - if(getQuestStage(player, "Demon Slayer") == 100) + if(getQuestStage(player, Quests.DEMON_SLAYER) == 100) options("I am a mighty adventurer. Who are you?", "I'm not sure, I was hoping you could tell me.", "Hey can you give me another Silverlight"); else options("I am a mighty adventurer. Who are you?", "I'm not sure, I was hoping you could tell me."); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/TraibornDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/TraibornDialogue.java index b16a415a2..5ea8e3622 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/TraibornDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/TraibornDialogue.java @@ -12,6 +12,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the dialogue used to handle the Traiborn NPC. @@ -60,7 +61,7 @@ public class TraibornDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Demon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); switch (quest.getStage(player)) { case 20: if (player.getAttribute("demon-slayer:traiborn", false)) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/WallyCutscenePlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/WallyCutscenePlugin.java index 918451e1c..190989d52 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/WallyCutscenePlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/demonslayer/WallyCutscenePlugin.java @@ -10,6 +10,7 @@ import core.net.packet.PacketRepository; import core.net.packet.context.CameraContext; import core.net.packet.context.CameraContext.CameraType; import core.net.packet.out.CameraViewPacket; +import content.data.Quests; /** * Represents the wally cutscene plugin. @@ -54,7 +55,7 @@ public class WallyCutscenePlugin extends CutscenePlugin { @Override public void fade() { - player.getQuestRepository().getQuest("Demon Slayer").start(player); + player.getQuestRepository().getQuest(Quests.DEMON_SLAYER).start(player); player.getDialogueInterpreter().open(882, Repository.findNPC(882), this); } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/CabinBoyJenkins.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/CabinBoyJenkins.java index 149fb9609..096bbba01 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/CabinBoyJenkins.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/CabinBoyJenkins.java @@ -5,6 +5,9 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; + +import static core.api.ContentAPIKt.getQuestStage; /** * Represents the cabin boy jenkins dialogue. @@ -12,12 +15,6 @@ import core.game.node.entity.player.link.quest.Quest; */ @Initializable public class CabinBoyJenkins extends DialoguePlugin { - - /** - * Represents the quest instance. - */ - private Quest quest; - /** * Constructs a new {@code CabinBoyJenkins} {@code Object}. */ @@ -43,8 +40,7 @@ public class CabinBoyJenkins extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); - switch (quest.getStage(player)) { + switch (getQuestStage(player, Quests.DRAGON_SLAYER)) { case 20: npc("Ahoy! Whay d'ye think of yer ship then?"); stage = 0; @@ -60,7 +56,7 @@ public class CabinBoyJenkins extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - switch (quest.getStage(player)) { + switch (getQuestStage(player, Quests.DRAGON_SLAYER)) { case 40: case 30: switch (stage) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSMagicDoorPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSMagicDoorPlugin.java index e6c55249d..0501b06f0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSMagicDoorPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSMagicDoorPlugin.java @@ -6,6 +6,7 @@ import core.game.node.Node; import core.game.node.entity.player.Player; import core.game.world.map.Location; import core.plugin.Plugin; +import content.data.Quests; /** * Represents the dragon slayer magic door plugin. @@ -40,7 +41,7 @@ public final class DSMagicDoorPlugin extends UseWithHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) < 20) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) < 20) { return true; } if (player.getInventory().remove(event.getUsedItem())) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSNedNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSNedNPC.java index 846fc7f90..4040b3190 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSNedNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DSNedNPC.java @@ -3,6 +3,7 @@ package content.region.misthalin.varrock.quest.dragonslayer; import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the dragon slayer npc. @@ -39,7 +40,7 @@ public final class DSNedNPC extends AbstractNPC { @Override public boolean isHidden(final Player player) { - return player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 30 && player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 40; + return player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 30 && player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 40; } @Override diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayer.kt b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayer.kt index 8b6bb5ec5..3bb325be9 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayer.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayer.kt @@ -23,13 +23,14 @@ import core.integrations.discord.Discord import core.plugin.ClassScanner.definePlugins import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests /** * Represents the dragon slayer quest. * @author Vexia - Converted to Kotlin with use of event hooks by not-Vexia */ @Initializable -class DragonSlayer : Quest("Dragon Slayer", 18, 17, 2, 176, 0, 1, 10), LoginListener { +class DragonSlayer : Quest(Quests.DRAGON_SLAYER, 18, 17, 2, 176, 0, 1, 10), LoginListener { override fun newInstance(`object`: Any?): Quest { definePlugins( CrandorMapPlugin(), @@ -323,7 +324,7 @@ class DragonSlayer : Quest("Dragon Slayer", 18, 17, 2, 176, 0, 1, 10), LoginList } override fun login(player: Player) { - if (getQuestStage(player, this.name) == 20) { + if (getQuestStage(player, this.quest) == 20) { player.hook(Event.SpellCast, SpellCastHook) player.hook(Event.PickedUp, PickedUpHook) } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerCutscene.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerCutscene.java index 40044126c..b1a4fbc34 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerCutscene.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerCutscene.java @@ -28,6 +28,7 @@ import core.net.packet.out.MinimapState; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents the dragon slayer cutscene. @@ -103,7 +104,7 @@ public final class DragonSlayerCutscene extends CutscenePlugin { player.animate(ANIMATION); player.getDialogueInterpreter().close(); player.getDialogueInterpreter().sendDialogue("You are knocked unconscious and later awake on an ash-strewn", "beach."); - player.getQuestRepository().getQuest("Dragon Slayer").setStage(player, 40); + player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).setStage(player, 40); player.getSavedData().getQuestData().setDragonSlayerAttribute("repaired", false); setVarp(player, 177, 8257540); setVarp(player, 176, 8); @@ -292,7 +293,7 @@ public final class DragonSlayerCutscene extends CutscenePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); if (args.length > 1) { cutscene = ((DragonSlayerCutscene) args[1]); npc("Ah it's good to feel that salt spray on my face once", "again!"); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java index 4adfe8537..f16658df0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java @@ -25,6 +25,7 @@ import core.plugin.Plugin; import java.util.List; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** @@ -106,7 +107,7 @@ public final class DragonSlayerPlugin extends OptionHandler { @Override public boolean handle(final Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Dragon Slayer"); + final Quest quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); final int id = node instanceof Item ? ((Item) node).getId() : node instanceof Scenery ? ((Scenery) node).getId() : ((NPC) node).getId(); switch (id) { case 1755: @@ -118,12 +119,12 @@ public final class DragonSlayerPlugin extends OptionHandler { } break; case 742: - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { player.getPacketDispatch().sendMessage("You have already slain the dragon. Now you just need to return to Oziach for"); player.getPacketDispatch().sendMessage("your reward!"); return true; } - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) > 40) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) > 40) { player.getPacketDispatch().sendMessage("You have already slain Elvarg the dragon."); return true; } @@ -136,16 +137,16 @@ public final class DragonSlayerPlugin extends OptionHandler { movement.run(player, 10); return true; } - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { player.getPacketDispatch().sendMessage("You have already slain the dragon. Now you just need to return to Oziach for"); player.getPacketDispatch().sendMessage("your reward!"); return true; } - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) > 40) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) > 40) { player.getPacketDispatch().sendMessage("You have already slain the dragon."); return true; } - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 40 && !player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD)) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) == 40 && !player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD)) { ForceMovement movement = new ForceMovement(player, player.getLocation(), player.getLocation().transform(player.getLocation().getX() == 2845 ? 2 : -2, 0, 0), new Animation(839)); movement.run(player, 10); if (player.getLocation().getX() <= 2845) { @@ -164,7 +165,7 @@ public final class DragonSlayerPlugin extends OptionHandler { player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 2); break; case 2606: - if (player.getLocation().getY() < 9600 && !player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized") && player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 100) { + if (player.getLocation().getY() < 9600 && !player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized") && player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 100) { player.getPacketDispatch().sendMessage("The door is securely locked."); } else { if (!player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized")) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ElvargNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ElvargNPC.java index 047821ec9..fa25a9fdb 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ElvargNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ElvargNPC.java @@ -20,12 +20,12 @@ import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; import core.tools.RandomFunction; import content.global.handlers.item.equipment.special.DragonfireSwingHandler; import static core.api.ContentAPIKt.calculateDragonfireMaxHit; +import content.data.Quests; /** @@ -154,14 +154,14 @@ public final class ElvargNPC extends AbstractNPC { return super.isAttackable(entity, style, message); } final Player player = (Player) entity; - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) == 40 && (player.getInventory().containsItem(DragonSlayer.ELVARG_HEAD))) { if(message) { player.getPacketDispatch().sendMessage("You have already slain the dragon. Now you just need to return to Oziach for"); player.getPacketDispatch().sendMessage("your reward!"); } return false; } - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) > 40) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) > 40) { if(message) { player.getPacketDispatch().sendMessage("You have already slain Elvarg."); } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java index c71367bc4..a94d7ba5e 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/GuildmasterDialogue.java @@ -5,6 +5,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; +import content.data.Quests; /** * Represents the guild master dialogue at the champions guild related to dragon slayer. @@ -46,7 +47,7 @@ public final class GuildmasterDialogue extends DialoguePlugin { if (player.getQuestRepository().getPoints() < 32) { return true; } - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); npc("Greetings!"); if (quest.getStage(player) == 10) { stage = 0; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDSDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDSDialogue.kt index 5cecdad45..7b59f9c70 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDSDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDSDialogue.kt @@ -1,9 +1,9 @@ package content.region.misthalin.varrock.quest.dragonslayer -import content.region.misthalin.varrock.quest.dragonslayer.DragonSlayer import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests private const val SHIP_DIALOGUE = 2000 class NedDSDialogue(val questStage: Int) : DialogueFile() { @@ -49,7 +49,7 @@ class NedDSDialogue(val questStage: Int) : DialogueFile() { 2006 -> { if (player!!.inventory.remove(DragonSlayer.CRANDOR_MAP)) { interpreter!!.sendItemMessage(DragonSlayer.CRANDOR_MAP.id, "You hand the map to Ned.") - player!!.questRepository.getQuest("Dragon Slayer").setStage(player, 30) + player!!.questRepository.getQuest(Quests.DRAGON_SLAYER).setStage(player, 30) stage++ } else stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDialogue.kt index 46d87047a..dcc331bf6 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/NedDialogue.kt @@ -11,6 +11,7 @@ import content.region.desert.alkharid.quest.princealirescue.NedPARDialogue import content.region.misthalin.lumbridge.diary.NedDiaryDialogue import core.game.world.GameWorld.settings import core.tools.END_DIALOGUE +import content.data.Quests /** @@ -41,8 +42,8 @@ class NedDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(pl override fun handle(interfaceId: Int, buttonId: Int): Boolean { when (stage) { 0 -> { - val dSlayerStage = player.questRepository.getStage("Dragon Slayer") - val parStage = player.questRepository.getStage("Prince Ali Rescue") + val dSlayerStage = player.questRepository.getStage(Quests.DRAGON_SLAYER) + val parStage = player.questRepository.getStage(Quests.PRINCE_ALI_RESCUE) showTopics( IfTopic("I'd like to talk about Dragon Slayer.", NedDSDialogue(dSlayerStage), dSlayerStage == 20 || dSlayerStage == 30), IfTopic("I'd like to talk about Prince Ali Rescue.", NedPARDialogue(parStage), parStage == 20 || parStage == 30 || parStage == 40 || parStage == 50), diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/OziachDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/OziachDialogue.java index c24850f15..faebde0bd 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/OziachDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/OziachDialogue.java @@ -5,6 +5,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import content.data.Quests; /** * Represents the dialogue used to handle the oziach dialogue. @@ -43,7 +44,7 @@ public final class OziachDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); player.debug("" + quest.getStage(player)); switch (quest.getStage(player)) { case 100: @@ -261,7 +262,7 @@ public final class OziachDialogue extends DialoguePlugin { case 6: end(); int heads = player.getInventory().getAmount(DragonSlayer.ELVARG_HEAD); - if (player.getInventory().remove(new Item(DragonSlayer.ELVARG_HEAD.getId(),heads)) && !player.getQuestRepository().getQuest("Dragon Slayer").isCompleted(player)) { + if (player.getInventory().remove(new Item(DragonSlayer.ELVARG_HEAD.getId(),heads)) && !player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).isCompleted(player)) { quest.finish(player); } break; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainDialogue.java index 9a69a3bd8..84feb6bfc 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.integrations.discord.Discord; +import content.data.Quests; /** * Represents the dialogue used to handle the wormbrain npc related to the @@ -51,7 +52,7 @@ public final class WormbrainDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Dragon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER); switch (quest.getStage(player)) { default: npc("Whut you want?"); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainNPC.java index 25c81de50..f755bd88f 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/WormbrainNPC.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; import core.game.node.item.GroundItemManager; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the worm brain npc. @@ -44,7 +45,7 @@ public final class WormbrainNPC extends AbstractNPC { public void finalizeDeath(final Entity killer) { super.finalizeDeath(killer); if (killer instanceof Player) { - if (((Player) killer).getQuestRepository().getQuest("Dragon Slayer").getStage(killer.asPlayer()) == 20 && !((Player) killer).getInventory().containsItem(DragonSlayer.WORMBRAIN_PIECE) && !((Player) killer).getBank().containsItem(DragonSlayer.WORMBRAIN_PIECE)) { + if (((Player) killer).getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(killer.asPlayer()) == 20 && !((Player) killer).getInventory().containsItem(DragonSlayer.WORMBRAIN_PIECE) && !((Player) killer).getBank().containsItem(DragonSlayer.WORMBRAIN_PIECE)) { GroundItemManager.create(DragonSlayer.WORMBRAIN_PIECE, getLocation(), ((Player) killer)); ((Player) killer).getPacketDispatch().sendMessage("Wormbrain drops a map piece on the floor."); } @@ -55,7 +56,7 @@ public final class WormbrainNPC extends AbstractNPC { public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { if (entity instanceof Player) { final Player player = (Player) entity; - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 20) { + if (player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 20) { if(message) { player.getPacketDispatch().sendMessage("The goblin is already in prison. You have no reason to attack him."); } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ZombieRatNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ZombieRatNPC.java index 679922780..65a602673 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ZombieRatNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/ZombieRatNPC.java @@ -8,6 +8,9 @@ import core.game.node.item.GroundItemManager; import core.game.node.item.Item; import core.game.world.map.Location; import core.tools.RandomFunction; +import content.data.Quests; + +import static core.api.ContentAPIKt.getQuestStage; /** * Represents a zombie rat npc related to dragon slayer and witch's potion. @@ -52,12 +55,10 @@ public final class ZombieRatNPC extends AbstractNPC { super.finalizeDeath(killer); if (killer instanceof Player) { final Player p = ((Player) killer); - Quest quest = p.getQuestRepository().getQuest("Dragon Slayer"); if (RandomFunction.random(0, 4) == 2) { - GroundItemManager.create(DragonSlayer.RED_KEY, getLocation(), ((Player) killer)); + GroundItemManager.create(DragonSlayer.RED_KEY, getLocation(), p); } - quest = p.getQuestRepository().getQuest("Witch's Potion"); - if (quest.getStage(p) > 0 && quest.getStage(p) < 100) { + if (getQuestStage(p, Quests.WITCHS_POTION) > 0 && getQuestStage(p, Quests.WITCHS_POTION) < 100) { GroundItemManager.create(RAT_TAIL, getLocation(), p); } GroundItemManager.create(new Item(526), getLocation(), p); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/AvanDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/AvanDialogue.kt index 6b8c402a8..1961c4586 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/AvanDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/AvanDialogue.kt @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class AvanDialogue (player: Player? = null): DialoguePlugin(player) { @@ -19,7 +20,7 @@ class AvanDialogue (player: Player? = null): DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("Family Crest") ?: -1 + val qstage = player?.questRepository?.getStage(Quests.FAMILY_CREST) ?: -1 if (qstage == 100) { options("Can you change my gauntlets for me?", "Nevermind") @@ -101,7 +102,7 @@ class AvanDialogue (player: Player? = null): DialoguePlugin(player) { 15 -> player("Well, I'll see what I can do.").also{ stage = 1000 - player.questRepository.getQuest("Family Crest").setStage(player, 14) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 14) } 100 -> player("I'm still after that 'perfect gold'.").also { stage++ } @@ -128,7 +129,7 @@ class AvanDialogue (player: Player? = null): DialoguePlugin(player) { "with a red precious stone, and a perfect gold ring to match.").also { stage = 1000 } 300 -> sendDialogue("You hand Avan the perfect gold ring and necklace.").also{ - player.questRepository.getQuest("Family Crest").setStage(player, 16) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 16) player.inventory.remove(Item(774), Item(773)) player.inventory.add(CREST_PIECE_AVAN) stage++ diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/BootDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/BootDialogue.kt index 8a29de6e1..89dd53a2f 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/BootDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/BootDialogue.kt @@ -5,6 +5,7 @@ import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable +import content.data.Quests @Initializable @@ -15,7 +16,7 @@ class BootDialogue (player: Player? = null): DialoguePlugin(player){ override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("Family Crest") ?: -1 + val qstage = player?.questRepository?.getStage(Quests.FAMILY_CREST) ?: -1 if(qstage < 14 || qstage > 14){ npc(FacialExpression.OLD_NORMAL,"Hello tall person.") @@ -61,7 +62,7 @@ class BootDialogue (player: Player? = null): DialoguePlugin(player){ 21 -> npc("I don't believe it's exactly easy to get to though...").also { stage = 1000 - player.questRepository.getQuest("Family Crest").setStage(player, 15) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 15) } 1000 -> end() } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/CalebDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/CalebDialogue.kt index e25e5e60c..618bf40ec 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/CalebDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/CalebDialogue.kt @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable @@ -20,7 +21,7 @@ class CalebDialogue (player: Player? = null): DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("Family Crest") ?: -1 + val qstage = player?.questRepository?.getStage(Quests.FAMILY_CREST) ?: -1 if (qstage == 100) { options("Can you change my gauntlets for me?", "Nevermind") @@ -122,7 +123,7 @@ class CalebDialogue (player: Player? = null): DialoguePlugin(player) { 207 -> when(buttonId){ 1 -> npc("You will? It would help me a lot!").also{stage = 1000}.also{ - player.questRepository.getQuest("Family Crest").setStage(player, 11) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 11) } 2 -> npc("It's a valuable family heirloom. " , @@ -141,7 +142,7 @@ class CalebDialogue (player: Player? = null): DialoguePlugin(player) { 301 -> sendDialogue("You exchange the fish for Caleb's piece of the crest.").also{stage++}.also{ player.inventory.remove(Item(315),Item(329), Item(361), Item(365), Item(373)) player.inventory.add(CREST_PIECE) - player.questRepository.getQuest("Family Crest").setStage(player, 12) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 12) } 302 -> options("Uh... what happened to the rest of it?" , "Thank you very much!").also{stage++} diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt index 792f8da09..1ca3002f0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt @@ -14,6 +14,7 @@ import core.api.getQuestStage import core.api.hasAnItem import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests @Initializable @@ -34,7 +35,7 @@ class ChronozonCaveZone: MapZone("FC ChronozoneZone", true), Plugin { if (e != null) { if (e.isPlayer) { val player = e as Player - if (getQuestStage(player,"Family Crest") in (19..99) && + if (getQuestStage(player,Quests.FAMILY_CREST) in (19..99) && !hasAnItem(player, Items.CREST_PART_781).exists() ){ // Chronozon is allowed to spawn (quest stage right and the player doesn't have the crest part) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonNPC.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonNPC.kt index 0e8fcac05..954e5b02e 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonNPC.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonNPC.kt @@ -7,6 +7,7 @@ import core.game.node.entity.npc.AbstractNPC import core.game.node.entity.player.Player import core.game.world.map.Location import org.rs09.consts.NPCs +import content.data.Quests class ChronozonNPC(id: Int, location: Location?) : AbstractNPC(NPCs.CHRONOZON_667, Location(3086, 9936, 0)){ @@ -72,8 +73,8 @@ class ChronozonNPC(id: Int, location: Location?) : AbstractNPC(NPCs.CHRONOZON_66 override fun finalizeDeath(killer: Entity?) { if(killer == targetplayer) { - if (targetplayer.questRepository.getStage("Family Crest") != 20){ - targetplayer.questRepository.getQuest("Family Crest").setStage(targetplayer, 20) + if (targetplayer.questRepository.getStage(Quests.FAMILY_CREST) != 20){ + targetplayer.questRepository.getQuest(Quests.FAMILY_CREST).setStage(targetplayer, 20) // Make sure to despawn Chronozon this.clear() } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt index 3263df6cb..e5e2f9ba0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/DimintheisDialogue.kt @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable @@ -18,12 +19,10 @@ class DimintheisDialogue(player: Player? = null): core.game.dialogue.DialoguePlu return DimintheisDialogue(player) } - private val questName = "Family Crest" - override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val questStage = getQuestStage(player, questName) - val questComplete = isQuestComplete(player, questName) + val questStage = getQuestStage(player, Quests.FAMILY_CREST) + val questComplete = isQuestComplete(player, Quests.FAMILY_CREST) if (questStage == 20 && inInventory(player, Items.FAMILY_CREST_782)) { player("I have retrieved your crest.").also{ stage = 5000 } @@ -134,7 +133,7 @@ class DimintheisDialogue(player: Player? = null): core.game.dialogue.DialoguePlu 1 -> npc("I thank you greatly adventurer!").also { stage++ } 2 -> npc("I realise it was a lot to ask of a stranger.").also { stage = 1000 } } - 2012 -> if(startQuest(player, questName)) { + 2012 -> if(startQuest(player, Quests.FAMILY_CREST)) { npc("If you find Caleb, or my other sons... please... ", "let them know their father still loves them...").also { stage = 1000 } } else { @@ -167,7 +166,7 @@ class DimintheisDialogue(player: Player? = null): core.game.dialogue.DialoguePlu "they should be able to imbue them with a skill for you.").also { stage = 1000 if (removeItem(player, Items.FAMILY_CREST_782)) { - finishQuest(player, questName) + finishQuest(player, Quests.FAMILY_CREST) } } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/FamilyCrest.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/FamilyCrest.kt index 0303ba3f8..2cedd6105 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/FamilyCrest.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/FamilyCrest.kt @@ -10,7 +10,7 @@ import core.game.node.entity.skill.Skills import core.plugin.Initializable import core.tools.Log import org.rs09.consts.Items -import core.tools.SystemLogger +import content.data.Quests /** * Represents the "Family Crest" quest. @@ -18,7 +18,7 @@ import core.tools.SystemLogger */ @Initializable -class FamilyCrest: Quest("Family Crest", 59, 58, 1, 148, 0, 1, 11) { +class FamilyCrest: Quest(Quests.FAMILY_CREST, 59, 58, 1, 148, 0, 1, 11) { override fun newInstance(`object`: Any?): Quest { return this diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonAntiPoisonInteraction.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonAntiPoisonInteraction.kt index 2ed748bab..9c12e517a 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonAntiPoisonInteraction.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonAntiPoisonInteraction.kt @@ -6,6 +6,7 @@ import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests class JohnathonAntiPosionInteraction: InteractionListener { override fun defineListeners() { @@ -14,14 +15,14 @@ class JohnathonAntiPosionInteraction: InteractionListener { onUseWith(IntType.NPC, poisons, NPCs.JOHNATHON_668){ player, used, with -> val npc = with.asNpc() val antip = used.asItem() - val stage = getQuestStage(player, "Family Crest") + val stage = getQuestStage(player, Quests.FAMILY_CREST) val index = poisons.indexOf(used.id) val returnItem = if(index + 1 == poisons.size) Items.VIAL_229 else poisons[index + 1] if(stage == 17 && removeItem(player, antip)){ addItem(player, returnItem) - setQuestStage(player, "Family Crest", 18) + setQuestStage(player, Quests.FAMILY_CREST, 18) openDialogue(player, NPCs.JOHNATHON_668, npc) } else { sendMessage(player, "Nothing interesting happens.") diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonDialogue.kt index 8942d0ab8..c0e6d6f35 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/JohnathonDialogue.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable class JohnathonDialogue(player: Player? = null): DialoguePlugin(player) { @@ -18,7 +19,7 @@ class JohnathonDialogue(player: Player? = null): DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = (args[0] as NPC).getShownNPC(player) - val qstage = player?.questRepository?.getStage("Family Crest") ?: -1 + val qstage = player?.questRepository?.getStage(Quests.FAMILY_CREST) ?: -1 if (qstage == 100) { options("Can you change my gauntlets for me?", "Nevermind") @@ -53,7 +54,7 @@ class JohnathonDialogue(player: Player? = null): DialoguePlugin(player) { "too much... My head... " , "will not... stop spinning...").also { stage++ } 4 -> sendDialogue("Sweat is pouring down Jonathons' face.").also { stage = 1000 - player.questRepository.getQuest("Family Crest").setStage(player, 17) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 17) } 100 -> npc("Ooooh... thank you... Wow! " , @@ -68,7 +69,7 @@ class JohnathonDialogue(player: Player? = null): DialoguePlugin(player) { "I lost a lot of equipment in our last battle when he " , "bested me and forced me away from his den. He probably still has it now.").also{ stage = 200 - player.questRepository.getQuest("Family Crest").setStage(player, 19) + player.questRepository.getQuest(Quests.FAMILY_CREST).setStage(player, 19) } 200 -> options("So is this Chronozon hard to defeat?", "Where can I find Chronozon?", "So how did you end up getting poisoned?", "I will be on my way now.").also{stage++} diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/WitchavenLeverInteraction.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/WitchavenLeverInteraction.kt index d0b7f8541..af534f4d8 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/WitchavenLeverInteraction.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/WitchavenLeverInteraction.kt @@ -11,6 +11,7 @@ import core.net.packet.out.ConstructScenery import core.net.packet.out.UpdateAreaPosition import core.game.interaction.InteractionListener import core.game.interaction.IntType +import content.data.Quests fun doDoor(player: Player, scenery: Scenery) { val d = if(scenery.rotation == 0 || scenery.rotation == 3) { -1 } else { 0 } @@ -50,7 +51,7 @@ class WitchavenLeverInteraction : InteractionListener { override fun defineListeners() { on(LEVERS, IntType.SCENERY, "pull") { player, node -> val baseId = if(node.id % 2 == 0) { node.id - 1 } else { node.id } - if(player.questRepository.getQuest("Family Crest").getStage(player) == 0) { + if(player.questRepository.getQuest(Quests.FAMILY_CREST).getStage(player) == 0) { player.sendMessage("Nothing interesting happens.") } val old = player.getAttribute("family-crest:witchaven-lever:${baseId}", false) @@ -80,7 +81,7 @@ class WitchavenLeverInteraction : InteractionListener { val northA = player.getAttribute("family-crest:witchaven-lever:${NORTH_LEVER_A}", false) val northB = player.getAttribute("family-crest:witchaven-lever:${NORTH_LEVER_B}", false) val south = player.getAttribute("family-crest:witchaven-lever:${SOUTH_LEVER}", false) - val questComplete = player.questRepository.getQuest("Family Crest").getStage(player) >= 100 + val questComplete = player.questRepository.getQuest(Quests.FAMILY_CREST).getStage(player) >= 100 // Authentic door formulae from https://gitlab.com/open-runescape-classic/core/-/blob/develop/server/plugins/com/openrsc/server/plugins/authentic/quests/members/FamilyCrest.java#L575-657 val canPass = when(node.id) { NORTH_DOOR -> !northA && (south || northB) diff --git a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/FluffNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/FluffNPC.java index 7fa4028e2..fd90e43a0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/FluffNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/FluffNPC.java @@ -4,6 +4,7 @@ import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the plugin used for the fluff npc. @@ -41,7 +42,7 @@ public final class FluffNPC extends AbstractNPC { @Override public boolean isHidden(final Player player) { - if (player.getQuestRepository().getQuest("Gertrude's Cat").getStage(player) < 20) { + if (player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT).getStage(player) < 20) { return true; } return player.getAttribute("hidefluff", 0L) > System.currentTimeMillis(); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java index 16ce95fcd..31cd7bbc2 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java @@ -9,6 +9,7 @@ import core.game.node.item.Item; import core.tools.RandomFunction; import static core.api.ContentAPIKt.addItemOrBank; +import content.data.Quests; /** * Represents the gertrudes fortress quest. @@ -21,7 +22,7 @@ public class GertrudesCat extends Quest { * Constructs a new {@code GertrudesCat} {@code Object}. */ public GertrudesCat() { - super("Gertrude's Cat", 67, 66, 1, 180, 0, 1, 100); + super(Quests.GERTRUDES_CAT, 67, 66, 1, 180, 0, 1, 100); } @Override diff --git a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/LumberKittenNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/LumberKittenNPC.java index 9b1714bd4..51ab6f1b5 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/LumberKittenNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/LumberKittenNPC.java @@ -7,6 +7,7 @@ import core.game.world.GameWorld; import core.game.world.map.Location; import core.plugin.Initializable; import core.tools.RandomFunction; +import content.data.Quests; /** * Represents the lumber kittens at the lumber yard. @@ -77,7 +78,7 @@ public final class LumberKittenNPC extends AbstractNPC { @Override public boolean isHidden(final Player player) { - Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat"); + Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); if (hidden) { return true; } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietDialogue.java index b8d37f6d0..7d6b190e4 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietDialogue.java @@ -15,6 +15,7 @@ import core.game.world.map.path.Path; import core.game.world.map.path.Pathfinder; import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; +import content.data.Quests; /** * Represents the dialogue of the juliet NPC. @@ -67,7 +68,7 @@ public final class JulietDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); npc = (NPC) args[0]; if (args.length > 1) { cutscene = (JulietCutscenePlugin) args[1]; @@ -123,7 +124,7 @@ public final class JulietDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); final NPC phil = cutscene != null ? cutscene.getPhillipia() : (NPC) Repository.findNPC(3325); final NPC dad = cutscene != null ? cutscene.getNPCS().get(2) : (NPC) Repository.findNPC(3324); switch (stage) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietNPC.java index 549692660..d87164ef7 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/JulietNPC.java @@ -4,6 +4,7 @@ import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the juliet npc. @@ -41,7 +42,7 @@ public final class JulietNPC extends AbstractNPC { @Override public boolean isHidden(final Player player) { - return player.getQuestRepository().getQuest("Romeo & Juliet").getStage(player) > 60 && player.getQuestRepository().getQuest("Romeo & Juliet").getStage(player) < 100; + return player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(player) > 60 && player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(player) < 100; } @Override diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RJCutscenePlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RJCutscenePlugin.java index ecb1d1d4d..17a33f20b 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RJCutscenePlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RJCutscenePlugin.java @@ -21,6 +21,7 @@ import core.net.packet.context.CameraContext; import core.net.packet.context.CameraContext.CameraType; import core.plugin.Initializable; import core.net.packet.out.CameraViewPacket; +import content.data.Quests; /** * Represents the romeo and juliet cutscene plugin. @@ -93,7 +94,7 @@ public final class RJCutscenePlugin extends CutscenePlugin { @Override public void fade() { - player.getQuestRepository().getQuest("Romeo & Juliet").finish(player); + player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).finish(player); } @Override @@ -169,7 +170,7 @@ public final class RJCutscenePlugin extends CutscenePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - Quest quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + Quest quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); switch (stage) { case 0: interpreter.sendOptions("Select an Option", "No sorry. I haven't seen her.", "Perhaps I could help to find her for you?"); @@ -771,7 +772,7 @@ public final class RJCutscenePlugin extends CutscenePlugin { @Override public boolean open(Object... args) { - Quest quest = player.getQuestRepository().getQuest("Romeo & Juliet"); + Quest quest = player.getQuestRepository().getQuest(Quests.ROMEO_JULIET); npc = (NPC) args[0]; if (args.length > 1) { cutscene = (RJCutscenePlugin) args[1]; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java index 90ddba6a7..2e5945316 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoJuliet.java @@ -3,6 +3,7 @@ package content.region.misthalin.varrock.quest.romeo; import core.game.node.entity.player.Player; import core.plugin.Initializable; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the romeo and juliet quest. @@ -15,7 +16,7 @@ public class RomeoJuliet extends Quest { * Constructs a new {@code RomeoJuliet} {@code Object}. */ public RomeoJuliet() { - super("Romeo & Juliet", 26, 25, 5, 144, 0, 1, 100); + super(Quests.ROMEO_JULIET, 26, 25, 5, 144, 0, 1, 100); } @Override @@ -130,7 +131,7 @@ public class RomeoJuliet extends Quest { @Override public void finish(Player player) { - if(player.getQuestRepository().getQuest("Romeo & Juliet").isCompleted(player)){ + if(player.getQuestRepository().getQuest(Quests.ROMEO_JULIET).isCompleted(player)){ return; } super.finish(player); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoNPC.java index e520a3ce9..0034cddca 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/romeo/RomeoNPC.java @@ -55,7 +55,7 @@ public class RomeoNPC extends AbstractNPC { /*if (speakDelay < GameWorld.getTicks()) { speakDelay = GameWorld.getTicks() + 30; for (Player p : RegionManager.getLocalPlayers(this, 2)) { - if (!p.getInterfaceManager().isOpened() && RandomFunction.random(0, 8) == 2 && p.getQuestRepository().getQuest("Romeo & Juliet").getStage(p) == 0) { + if (!p.getInterfaceManager().isOpened() && RandomFunction.random(0, 8) == 2 && p.getQuestRepository().getQuest(Quests.ROMEO_JULIET).getStage(p) == 0) { if (p.getDialogueInterpreter().getDialogue() != null || p.getDialogueInterpreter().getDialogueStage() != null) { continue; } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CharlieTheTrampDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CharlieTheTrampDialogue.kt index 5b6d6ba3f..3ba076b35 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CharlieTheTrampDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CharlieTheTrampDialogue.kt @@ -6,6 +6,7 @@ import core.game.node.item.Item import core.plugin.Initializable import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests /** * @author qmqz @@ -13,8 +14,6 @@ import org.rs09.consts.NPCs @Initializable class CharlieTheTrampDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ - var q = "Shield of Arrav" - override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC npc(core.game.dialogue.FacialExpression.FRIENDLY,"Spare some change guv?").also { stage = 0 } @@ -70,11 +69,11 @@ class CharlieTheTrampDialogue(player: Player? = null) : core.game.dialogue.Dialo 282 -> npc(core.game.dialogue.FacialExpression.AFRAID, "But don't upset her, she's pretty dangerous.").also { stage++ } 283 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "I also heard that Reldo the librarian knows more about them, go talk to him.").also { stage++ } 284 -> { - if (!player.questRepository.hasStarted(q)) { - player.questRepository.getQuest(q).start(player) - player.questRepository.getQuest(q).setStage(player,50) + if (!player.questRepository.hasStarted(Quests.SHIELD_OF_ARRAV)) { + player.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).start(player) + player.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).setStage(player,50) } else if (!ShieldofArrav.isBlackArm(player) && !ShieldofArrav.isPhoenix(player)) { - player.questRepository.getQuest(q).setStage(player, 50) + player.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).setStage(player, 50) } end() } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CuratorHaigHalenDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CuratorHaigHalenDialogue.kt index aa24c2ca2..67422ee21 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CuratorHaigHalenDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/CuratorHaigHalenDialogue.kt @@ -1,7 +1,6 @@ package content.region.misthalin.varrock.quest.shieldofarrav import content.region.desert.quest.thegolem.CuratorHaigHalenGolemDialogue -import content.region.misthalin.digsite.quest.thedigsite.TheDigSite import core.api.* import core.game.dialogue.* import core.game.node.entity.player.Player @@ -10,6 +9,7 @@ import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests class CuratorHaigHalenDialogue (player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { @@ -18,7 +18,7 @@ class CuratorHaigHalenDialogue (player: Player? = null) : DialoguePlugin(player) if (player.getQuestRepository().points >= 50 && !player.achievementDiaryManager.hasCompletedTask(DiaryType.VARROCK, 0, 12)) { player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 12) } - if (getQuestStage(player, TheDigSite.questName) == 1 && inInventory(player, Items.UNSTAMPED_LETTER_682) ) { + if (getQuestStage(player, Quests.THE_DIG_SITE) == 1 && inInventory(player, Items.UNSTAMPED_LETTER_682) ) { stage = 11 // Couldn't do a dialogueFile for digsite as it needs to resume the topic after. } stage++ @@ -26,11 +26,12 @@ class CuratorHaigHalenDialogue (player: Player? = null) : DialoguePlugin(player) 1 -> showTopics( Topic(FacialExpression.FRIENDLY, "Have you any interesting news?", 2), Topic(FacialExpression.FRIENDLY, "Do you know where I could find any treasure?", 8), - IfTopic(FacialExpression.FRIENDLY, "I've lost the letter of recommendation.", 18, getQuestStage(player, TheDigSite.questName) == 2 && !inInventory(player, Items.SEALED_LETTER_683)), + IfTopic(FacialExpression.FRIENDLY, "I've lost the letter of recommendation.", 18, + getQuestStage(player, Quests.THE_DIG_SITE) == 2 && !inInventory(player, Items.SEALED_LETTER_683)), IfTopic("I have the Shield of Arrav", CuratorHaigHalenSOADialogue(), - getQuestStage(player, "Shield of Arrav") == 70, false), + getQuestStage(player, Quests.SHIELD_OF_ARRAV) == 70, false), IfTopic("I'm looking for a statuette recovered from the city of Uzer.", CuratorHaigHalenGolemDialogue(), - getQuestStage(player, "The Golem") == 3, false) + getQuestStage(player, Quests.THE_GOLEM) == 3, false) ) 2 -> npcl(FacialExpression.FRIENDLY, "Yes, we found a rather interesting island to the north of Morytania. We believe that it may be of archaeological significance.").also { stage++ } 3 -> playerl(FacialExpression.FRIENDLY, "Oh? That sounds interesting.").also { stage++ } @@ -61,8 +62,8 @@ class CuratorHaigHalenDialogue (player: Player? = null) : DialoguePlugin(player) stage++ } 16 -> playerl(FacialExpression.FRIENDLY, "Ok, I will. Thanks, see you later.").also { - if(getQuestStage(player, TheDigSite.questName) == 1) { - setQuestStage(player, TheDigSite.questName, 2) + if(getQuestStage(player, Quests.THE_DIG_SITE) == 1) { + setQuestStage(player, Quests.THE_DIG_SITE, 2) } stage = 1 } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java index da7ef94ba..f5be4a4b0 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/JohnnyBeardNPC.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.world.map.Location; +import content.data.Quests; /** * Represents the npc to handle Johnny the beard npc. @@ -45,7 +46,7 @@ public final class JohnnyBeardNPC extends AbstractNPC { super.finalizeDeath(killer); if (killer instanceof Player) { final Player p = ((Player) killer); - final Quest quest = p.getQuestRepository().getQuest("Shield of Arrav"); + final Quest quest = p.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); if (quest.getStage(p) == 60 && ShieldofArrav.isPhoenixMission(p) && !p.getInventory().containsItem(ShieldofArrav.INTEL_REPORT) && !p.getBank().containsItem(ShieldofArrav.INTEL_REPORT)) { GroundItemManager.create(ShieldofArrav.INTEL_REPORT, getLocation(), p); } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java index 027e04ba0..53f90edcd 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KatrineDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; +import content.data.Quests; import static core.api.ContentAPIKt.openDialogue; @@ -51,11 +52,11 @@ public final class KatrineDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Shield of Arrav"); + quest = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); switch (quest.getStage(player)) { case 100: if (ShieldofArrav.isBlackArm(player)) { - Quest heroesQuest = player.getQuestRepository().getQuest("Heroes' Quest"); + Quest heroesQuest = player.getQuestRepository().getQuest(Quests.HEROES_QUEST); if (0 < heroesQuest.getStage(player) && heroesQuest.getStage(player) < 100) { openDialogue(player, new KatrineDialogueFile(), npc); break; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KingRoaldArravDialogue.kt b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KingRoaldArravDialogue.kt index 9135bd1d5..26238d76d 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KingRoaldArravDialogue.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/KingRoaldArravDialogue.kt @@ -1,11 +1,11 @@ package content.region.misthalin.varrock.quest.shieldofarrav -import content.region.misthalin.varrock.quest.shieldofarrav.ShieldofArrav import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.game.dialogue.DialogueFile import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import content.data.Quests private val CERTIFICATE = Item(769) @@ -46,7 +46,7 @@ class KingRoaldArravDialogue() : DialogueFile() { if (!player!!.inventory.add(Item(995, 600))) { GroundItemManager.create(Item(995, 600), player) } - player!!.questRepository.getQuest("Shield of Arrav").finish(player) + player!!.questRepository.getQuest(Quests.SHIELD_OF_ARRAV).finish(player) stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ReldoDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ReldoDialogue.java index 8d2859688..91bee2817 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ReldoDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ReldoDialogue.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.link.diary.AchievementDiary; import core.game.node.entity.player.link.diary.DiaryType; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; +import content.data.Quests; /** * Represents the dialogue to handle reldo. @@ -55,14 +56,14 @@ public class ReldoDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - knightSword = player.getQuestRepository().getQuest("The Knight's Sword"); - shieldArrav = player.getQuestRepository().getQuest("Shield of Arrav"); + knightSword = player.getQuestRepository().getQuest(Quests.THE_KNIGHTS_SWORD); + shieldArrav = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); if (args.length == 2 && ((String) args[1]).equals("book")) { player("Aha! 'The Shield of Arrav'! Exactly what I was looking", "for."); stage = 3; return true; } - if(player.getQuestRepository().getQuest("Lost Tribe").getStage(player) == 40 && player.getInventory().contains(Items.BROOCH_5008,1)){ + if(player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 40 && player.getInventory().contains(Items.BROOCH_5008,1)){ options("Hello stranger.","I have a question about my Achievement Diary.","Ask about the brooch."); } else { options("Hello stranger.", "I have a question about my Achievement Diary."); @@ -237,7 +238,7 @@ public class ReldoDialogue extends DialoguePlugin { break; case 2005: npc("The other day I filed a book about ancient goblin tribes.","It's somewhere on the west end of the library, I think.","Maybe that will be of some use."); - player.getQuestRepository().getQuest("Lost Tribe").setStage(player,42); + player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).setStage(player,42); stage++; break; case 2006: diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java index 2b51df2cf..80a581a22 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java @@ -23,6 +23,7 @@ import core.game.global.action.PickupHandler; import core.game.world.repository.Repository; import java.util.List; +import content.data.Quests; /** * Represents the shield of arrav plugin. @@ -59,7 +60,7 @@ public final class ShieldArravPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Shield of Arrav"); + final Quest quest = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); final int id = node instanceof Scenery ? ((Scenery) node).getId() : node instanceof Item ? ((Item) node).getId() : ((NPC) node).getId(); switch (id) { case 769: diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java index 90174100c..4b427035d 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArrav.java @@ -6,6 +6,7 @@ import core.game.node.item.Item; import core.plugin.Initializable; import content.region.misthalin.varrock.dialogue.KingRoaldDialogue; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the shield of arrav quest. @@ -54,7 +55,7 @@ public class ShieldofArrav extends Quest { * Constructs a new {@Code ShieldofArrav} {@Code Object} */ public ShieldofArrav() { - super("Shield of Arrav", 29, 28, 1, 145, 0, 1, 7); + super(Quests.SHIELD_OF_ARRAV, 29, 28, 1, 145, 0, 1, 7); } @Override diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArravBook.kt b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArravBook.kt index faebb66c3..10ec52e4e 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArravBook.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldofArravBook.kt @@ -4,11 +4,13 @@ import content.global.handlers.iface.BookInterface import content.global.handlers.iface.BookLine import content.global.handlers.iface.Page import content.global.handlers.iface.PageSet -import core.api.setAttribute import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.player.Player import org.rs09.consts.Items +import content.data.Quests +import core.api.getQuestStage +import core.api.setQuestStage /** * Shield of Arrav Book @@ -18,7 +20,7 @@ import org.rs09.consts.Items */ class ShieldofArravBook : InteractionListener { companion object { - private val TITLE = "Shield of Arrav" + private val TITLE = "The Shield of Arrav" private val CONTENTS = arrayOf( PageSet( Page( @@ -86,8 +88,8 @@ class ShieldofArravBook : InteractionListener { private fun display(player: Player, pageNum: Int, buttonID: Int) : Boolean { BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS) if (BookInterface.isLastPage(pageNum, CONTENTS.size)) { - if (player.questRepository.getQuest("Shield of Arrav").getStage(player) == 10) { - player.questRepository.getQuest("Shield of Arrav").setStage(player, 20) + if (getQuestStage(player, Quests.SHIELD_OF_ARRAV) == 10) { + setQuestStage(player, Quests.SHIELD_OF_ARRAV, 20) } } return true diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java index f429afc46..f12d9cef4 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/StravenDialogue.java @@ -5,6 +5,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; +import content.data.Quests; import content.region.asgarnia.burthorpe.quest.heroesquest.StravenDialogueFile; import static core.api.ContentAPIKt.openDialogue; @@ -46,11 +47,11 @@ public class StravenDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Shield of Arrav"); + quest = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); switch (quest.getStage(player)) { case 100: if (ShieldofArrav.isPhoenix(player)) { - Quest heroesQuest = player.getQuestRepository().getQuest("Heroes' Quest"); + Quest heroesQuest = player.getQuestRepository().getQuest(Quests.HEROES_QUEST); if (0 < heroesQuest.getStage(player) && heroesQuest.getStage(player) < 100) { openDialogue(player, new StravenDialogueFile(), npc); break; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/WeaponsMasterDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/WeaponsMasterDialogue.java index c521eb492..e0f0f5fc6 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/WeaponsMasterDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/WeaponsMasterDialogue.java @@ -4,6 +4,7 @@ import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; +import content.data.Quests; /** * Represents the dialogue which handles the weapons master. @@ -42,7 +43,7 @@ public final class WeaponsMasterDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Shield of Arrav"); + quest = player.getQuestRepository().getQuest(Quests.SHIELD_OF_ARRAV); switch (quest.getStage(player)) { default: if (args.length > 1) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/AnnaJonesDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/AnnaJonesDialogue.java index 6e68c8dca..645995cdb 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/AnnaJonesDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/AnnaJonesDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.whatliesbelow; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; @@ -40,7 +41,7 @@ public class AnnaJonesDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - quest = player.getQuestRepository().getQuest(WhatLiesBelow.NAME); + quest = player.getQuestRepository().getQuest(Quests.WHAT_LIES_BELOW); switch (quest.getStage(player)) { default: if (args.length >= 2) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/OutlawNPC.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/OutlawNPC.java index e4c9bdc19..9649f5fa3 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/OutlawNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/OutlawNPC.java @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.whatliesbelow; +import content.data.Quests; import core.game.node.entity.Entity; import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; @@ -39,7 +40,7 @@ public class OutlawNPC extends AbstractNPC { super.finalizeDeath(killer); if (killer instanceof Player) { Player p = killer.asPlayer(); - Quest quest = p.getQuestRepository().getQuest(WhatLiesBelow.NAME); + Quest quest = p.getQuestRepository().getQuest(Quests.WHAT_LIES_BELOW); if (quest.getStage(p) == 10) { int amount = p.getInventory().getAmount(WhatLiesBelow.RATS_PAPER) + p.getBank().getAmount(WhatLiesBelow.RATS_PAPER); if (amount < 5) { diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/RatBurgissDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/RatBurgissDialogue.java index 11b84906c..0a8e97bc6 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/RatBurgissDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/RatBurgissDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.whatliesbelow; +import content.data.Quests; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; @@ -52,7 +53,7 @@ public class RatBurgissDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(WhatLiesBelow.NAME); + quest = player.getQuestRepository().getQuest(Quests.WHAT_LIES_BELOW); options("Hello there!", "I have a question about my Achievement Diary."); stage = -1; return true; diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/SurokMagisDialogue.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/SurokMagisDialogue.java index 1f4cf375f..838900d75 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/SurokMagisDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/SurokMagisDialogue.java @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.whatliesbelow; +import content.data.Quests; import core.game.activity.ActivityManager; import core.game.dialogue.DialoguePlugin; import core.game.node.entity.npc.NPC; @@ -50,7 +51,7 @@ public class SurokMagisDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest(WhatLiesBelow.NAME); + quest = player.getQuestRepository().getQuest(Quests.WHAT_LIES_BELOW); switch (quest.getStage(player)) { default: npc("Excuse me?"); diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WLBelowPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WLBelowPlugin.java index 7f3b85182..09c27bcd9 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WLBelowPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WLBelowPlugin.java @@ -1,5 +1,6 @@ package content.region.misthalin.varrock.quest.whatliesbelow; +import content.data.Quests; import core.cache.def.impl.SceneryDefinition; import core.game.component.Component; import core.game.node.entity.player.link.diary.DiaryType; @@ -56,7 +57,7 @@ public class WLBelowPlugin extends OptionHandler { @Override public boolean handle(final Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(WhatLiesBelow.NAME); + final Quest quest = player.getQuestRepository().getQuest(Quests.WHAT_LIES_BELOW); switch (option) { case "summon": case "operate": diff --git a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java index 6f53a36fc..0b0238179 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/whatliesbelow/WhatLiesBelow.java @@ -9,6 +9,7 @@ import core.game.node.item.Item; import core.plugin.ClassScanner; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * The what lies below quest. @@ -17,12 +18,6 @@ import static core.api.ContentAPIKt.*; */ @Initializable public class WhatLiesBelow extends Quest { - - /** - * The name of the quest. - */ - public static final String NAME = "What Lies Below"; - /** * The bowl item. */ @@ -87,7 +82,7 @@ public class WhatLiesBelow extends Quest { * Constructs a new {@Code WhatLiesBelow} {@Code Object} */ public WhatLiesBelow() { - super(NAME, 136, 135, 1); + super(Quests.WHAT_LIES_BELOW, 136, 135, 1); } @Override @@ -107,7 +102,7 @@ public class WhatLiesBelow extends Quest { line(player, "Before I begin I will need to:", line++); line(player, "Have level 35 !!Runecrafting??.", line++, getStatLevel(player, Skills.RUNECRAFTING) >= 35); line(player, "Be able to defeat a !!level 47 enemy??.", line++); - line(player, "I need to have completed the !!Rune Mysteries?? quest.", line++, isQuestComplete(player, "Rune Mysteries")); + line(player, "I need to have completed the !!Rune Mysteries?? quest.", line++, isQuestComplete(player, Quests.RUNE_MYSTERIES)); line(player, "Have a !!Mining?? level of 42 to use the !!Chaos Tunnel??.", line++, getStatLevel(player, Skills.MINING) >= 42); } else { // These are somehow at the top with different stage when crossed out. @@ -202,7 +197,7 @@ public class WhatLiesBelow extends Quest { requirements[0] = player.getSkills().getStaticLevel(Skills.RUNECRAFTING) >= 35; requirements[1] = false; requirements[3] = player.getSkills().getStaticLevel(Skills.MINING) >= 42; - requirements[2] = player.getQuestRepository().isComplete("Rune Mysteries"); + requirements[2] = player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES); return requirements[0] && requirements[2] && requirements[3]; } @@ -217,7 +212,7 @@ public class WhatLiesBelow extends Quest { } else if (stage > 0 && stage < 100) { return new int[] { id, 1 }; } - setVarp(player, 1181, (1 << 8) + (1 << 9), true); + setVarp(player, 1181, (1 << 8) + (1 << 9), true); return new int[] { id, 502 }; } diff --git a/Server/src/main/content/region/misthalin/wiztower/dialogue/TraibornDialogue.java b/Server/src/main/content/region/misthalin/wiztower/dialogue/TraibornDialogue.java index 37c40a125..4f4200c9e 100644 --- a/Server/src/main/content/region/misthalin/wiztower/dialogue/TraibornDialogue.java +++ b/Server/src/main/content/region/misthalin/wiztower/dialogue/TraibornDialogue.java @@ -14,6 +14,7 @@ import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import content.region.misthalin.varrock.quest.demonslayer.DemonSlayer; +import content.data.Quests; /** * Represents the dialogue used to handle the Traiborn NPC. @@ -68,7 +69,7 @@ public class TraibornDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - quest = player.getQuestRepository().getQuest("Demon Slayer"); + quest = player.getQuestRepository().getQuest(Quests.DEMON_SLAYER); switch (quest.getStage(player)) { case 20: if (player.getAttribute("demon-slayer:traiborn", false)) { diff --git a/Server/src/main/content/region/misthalin/wiztower/handlers/WizardTowerPlugin.java b/Server/src/main/content/region/misthalin/wiztower/handlers/WizardTowerPlugin.java index 2cf368836..01b970fd8 100644 --- a/Server/src/main/content/region/misthalin/wiztower/handlers/WizardTowerPlugin.java +++ b/Server/src/main/content/region/misthalin/wiztower/handlers/WizardTowerPlugin.java @@ -10,7 +10,6 @@ import core.game.global.action.ClimbActionHandler; import core.game.global.action.DoorActionHandler; import core.game.interaction.OptionHandler; import core.game.node.Node; -import core.game.node.entity.Entity; import core.game.node.entity.combat.spell.CombatSpell; import core.game.node.entity.combat.CombatStyle; import core.game.node.entity.npc.AbstractNPC; @@ -39,6 +38,7 @@ import kotlin.Unit; import content.global.travel.EssenceTeleport; import core.game.world.GameWorld; import core.plugin.ClassScanner; +import content.data.Quests; /** * Represents the plugins used related to the wizard tower. @@ -81,7 +81,7 @@ public final class WizardTowerPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { switch (option) { case "teleport": - if (!player.getQuestRepository().isComplete("Rune Mysteries")) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES)) { player.getPacketDispatch().sendMessage("You need to have completed the Rune Mysteries Quest to use this feature."); return true; } @@ -311,7 +311,7 @@ public final class WizardTowerPlugin extends OptionHandler { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - Quest quest = player.getQuestRepository().getQuest("Imp Catcher"); + Quest quest = player.getQuestRepository().getQuest(Quests.IMP_CATCHER); switch (quest.getStage(player)) { case 0: player("Give me a quest!"); @@ -331,7 +331,7 @@ public final class WizardTowerPlugin extends OptionHandler { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Imp Catcher"); + final Quest quest = player.getQuestRepository().getQuest(Quests.IMP_CATCHER); switch (quest.getStage(player)) { case 0: switch (stage) { @@ -1041,7 +1041,7 @@ public final class WizardTowerPlugin extends OptionHandler { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Rune Mysteries"); + final Quest quest = player.getQuestRepository().getQuest(Quests.RUNE_MYSTERIES); switch (stage) { case 0: if (quest.getStage(player) == 100) { @@ -1542,7 +1542,7 @@ public final class WizardTowerPlugin extends OptionHandler { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - final Quest quest = player.getQuestRepository().getQuest("Rune Mysteries"); + final Quest quest = player.getQuestRepository().getQuest(Quests.RUNE_MYSTERIES); if (quest.getStage(player) == 40) { npc("My gratitude to you adventurer for bringing me these", "research notes. I notice that you brought the head", "wizard a special talisman that was the key to our finally", "unlocking the puzzle."); stage = 900; @@ -1559,7 +1559,7 @@ public final class WizardTowerPlugin extends OptionHandler { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Rune Mysteries"); + final Quest quest = player.getQuestRepository().getQuest(Quests.RUNE_MYSTERIES); switch (stage) { case 0: if (quest.getStage(player) == 30) { @@ -1577,7 +1577,7 @@ public final class WizardTowerPlugin extends OptionHandler { stage = 950; return true; } - if (!player.getQuestRepository().isComplete("Rune Mysteries")) { + if (!player.getQuestRepository().isComplete(Quests.RUNE_MYSTERIES)) { options("Yes please!", "Oh, it's a rune shop. No thank you, then."); stage = 100; } else { diff --git a/Server/src/main/content/region/misthalin/wiztower/quest/ImpCatcher.java b/Server/src/main/content/region/misthalin/wiztower/quest/ImpCatcher.java index a24c4d6d6..d077a59f1 100644 --- a/Server/src/main/content/region/misthalin/wiztower/quest/ImpCatcher.java +++ b/Server/src/main/content/region/misthalin/wiztower/quest/ImpCatcher.java @@ -10,6 +10,7 @@ import core.game.node.scenery.SceneryBuilder; import core.game.world.map.Location; import core.plugin.Initializable; import core.game.world.map.RegionManager; +import content.data.Quests; /** * Represents the imp catcher quest. @@ -48,7 +49,7 @@ public class ImpCatcher extends Quest { * Constructs a new {@Code ImpCatcher} {@Code Object} */ public ImpCatcher() { - super("Imp Catcher", 21, 20, 1, 160, 0, 1, 2); + super(Quests.IMP_CATCHER, 21, 20, 1, 160, 0, 1, 2); } @Override diff --git a/Server/src/main/content/region/morytania/canifis/dialogue/RoavarDialogue.kt b/Server/src/main/content/region/morytania/canifis/dialogue/RoavarDialogue.kt index 97b81b311..edb3fbdda 100644 --- a/Server/src/main/content/region/morytania/canifis/dialogue/RoavarDialogue.kt +++ b/Server/src/main/content/region/morytania/canifis/dialogue/RoavarDialogue.kt @@ -10,10 +10,9 @@ import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.item.Item import core.plugin.Initializable -import core.tools.END_DIALOGUE -import core.tools.START_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs +import content.data.Quests /** * Roavar dialogue. @@ -38,7 +37,7 @@ class RoavarDialogue (player: Player? = null) : DialoguePlugin(player) { 1 -> showTopics( Topic(FacialExpression.HALF_GUILTY, "Can I buy a beer?", 10, false), Topic(FacialExpression.HALF_GUILTY, "Can I hear some gossip", 20, false), - IfTopic(FacialExpression.HALF_GUILTY, "Can I buy something to eat?", RoavarDialogueFile(1), player.getQuestRepository().getQuest("Creature of Fenkenstrain").getStage(player) == 2, false), + IfTopic(FacialExpression.HALF_GUILTY, "Can I buy something to eat?", RoavarDialogueFile(1), player.getQuestRepository().getQuest(Quests.CREATURE_OF_FENKENSTRAIN).getStage(player) == 2, false), Topic(FacialExpression.HALF_GUILTY, "Nothing thanks.", 40, false) ) diff --git a/Server/src/main/content/region/morytania/handlers/MorytaniaArea.kt b/Server/src/main/content/region/morytania/handlers/MorytaniaArea.kt index 19429c4bd..5edfa55f7 100644 --- a/Server/src/main/content/region/morytania/handlers/MorytaniaArea.kt +++ b/Server/src/main/content/region/morytania/handlers/MorytaniaArea.kt @@ -11,6 +11,7 @@ import org.rs09.consts.NPCs import core.game.bots.AIPlayer import core.game.dialogue.DialogueFile import core.game.world.GameWorld +import content.data.Quests class MorytaniaArea : MapArea { override fun defineAreaBorders(): Array { @@ -22,7 +23,7 @@ class MorytaniaArea : MapArea { override fun areaEnter(entity: Entity) { if (entity is Player && entity !is AIPlayer && ( - !isQuestComplete(entity, "Priest in Peril") || //not allowed to be anywhere in Morytania + !isQuestComplete(entity, Quests.PRIEST_IN_PERIL) || //not allowed to be anywhere in Morytania defineAreaBorders()[1].insideBorder(entity) //Werewolf agility course is not implemented )) { kickThemOut(entity) diff --git a/Server/src/main/content/region/morytania/handlers/MorytaniaListeners.kt b/Server/src/main/content/region/morytania/handlers/MorytaniaListeners.kt index ccce9cbaf..0cd82feda 100644 --- a/Server/src/main/content/region/morytania/handlers/MorytaniaListeners.kt +++ b/Server/src/main/content/region/morytania/handlers/MorytaniaListeners.kt @@ -13,6 +13,7 @@ import org.rs09.consts.Scenery import core.game.interaction.InteractionListener import core.game.interaction.IntType import kotlin.random.Random +import content.data.Quests /** * File to be used for anything Morytania related. @@ -43,7 +44,7 @@ class MorytaniaListeners : InteractionListener { findLocalNPC(player, NPCs.ULIZIUS_1054)?.sendChat("Oh my! You're still alive!", 2) } } else { - if (player.questRepository.hasStarted("Nature Spirit")) { + if (player.questRepository.hasStarted(Quests.NATURE_SPIRIT)) { core.game.global.action.DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendNPCDialogue( diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/BookcaseDialogueFile.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/BookcaseDialogueFile.kt index a5d0843da..f188633d9 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/BookcaseDialogueFile.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/BookcaseDialogueFile.kt @@ -1,5 +1,6 @@ package content.region.morytania.quest.creatureoffenkenstrain +import content.data.Quests import content.global.handlers.iface.BookInterface import content.global.handlers.iface.BookLine import content.global.handlers.iface.Page @@ -46,7 +47,7 @@ class BookcaseEastDialogueFile : DialogueFile() { 4 -> sendDialogue(player!!, "The book is appallingly dull.").also { stage = END_DIALOGUE } } 2 -> { - if (getQuestStage(player!!, CreatureOfFenkenstrain.questName) == 2) { + if (getQuestStage(player!!, Quests.CREATURE_OF_FENKENSTRAIN) == 2) { sendItemDialogue(player!!, Items.OBSIDIAN_AMULET_4188, "You find an obsidian amulet in the secret compartment.").also { addItemOrDrop(player!!, Items.OBSIDIAN_AMULET_4188, 1) stage = END_DIALOGUE diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt index 0959d87e6..dd7dccc9b 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrain.kt @@ -6,8 +6,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items - -val CREATURE_OF_FENKENSTRAIN = "Creature of Fenkenstrain" +import content.data.Quests /** * Creature of Fenkenstrain Quest @@ -27,10 +26,9 @@ val CREATURE_OF_FENKENSTRAIN = "Creature of Fenkenstrain" * 100 - Stoped Fenkenstrain by stealing ring of charos */ @Initializable -class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, 0, 1, 9) { +class CreatureOfFenkenstrain : Quest(Quests.CREATURE_OF_FENKENSTRAIN, 41, 40, 2, 399, 0, 1, 9) { companion object { - const val questName = "Creature of Fenkenstrain" const val attributeArms = "/save:quest:creatureoffenkenstrain-arms" const val attributeLegs = "/save:quest:creatureoffenkenstrain-legs" const val attributeTorso = "/save:quest:creatureoffenkenstrain-torso" @@ -46,7 +44,7 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, var line = 12 var stage = getStage(player) - var started = getQuestStage(player, questName) > 0 + var started = getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) > 0 if(!started){ line(player, "I can start this quest by reading the signpost in the", line++, false) @@ -56,8 +54,8 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, line(player, "Level 20 Crafting", line++, hasLevelStat(player, Skills.CRAFTING, 20)) line(player, "Level 25 Theiving", line++, hasLevelStat(player, Skills.THIEVING, 25)) line(player, "I also need to have completed the following quests:", line++, false) - line(player, "Priest in Peril", line++, isQuestComplete(player, "Priest in Peril")) - line(player, "Restless Ghost", line++, isQuestComplete(player, "The Restless Ghost")) + line(player, "Priest in Peril", line++, isQuestComplete(player, Quests.PRIEST_IN_PERIL)) + line(player, "Restless Ghost", line++, isQuestComplete(player, Quests.THE_RESTLESS_GHOST)) limitScrolling(player, line, true) } else { line(player, "I read the signpost in Canifis, which tells of a butler", line++, true) @@ -132,8 +130,8 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, return arrayOf( hasLevelStat(player, Skills.CRAFTING, 20), hasLevelStat(player, Skills.THIEVING, 25), - isQuestComplete(player, "Priest in Peril"), - isQuestComplete(player, "The Restless Ghost"), + isQuestComplete(player, Quests.PRIEST_IN_PERIL), + isQuestComplete(player, Quests.THE_RESTLESS_GHOST), ).all { it } } @@ -171,10 +169,10 @@ class CreatureOfFenkenstrain : Quest("Creature of Fenkenstrain", 41, 40, 2, 399, override fun updateVarps(player: Player) { // This is a bit of a hack. I didn't manage to align the quest with the varp, // so I had to include both stage 3 and 4 to varp value 3 to show the creature. - if(getQuestStage(player, questName) == 4) { + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 4) { setVarp(player, fenkenstrainVarp, 3, true) } - if(getQuestStage(player, questName) >= 8) { + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) >= 8) { setVarp(player, fenkenstrainVarp, 8, true) } } diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt index 81cf396b5..7a0aea3bc 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/CreatureOfFenkenstrainListeners.kt @@ -1,5 +1,6 @@ package content.region.morytania.quest.creatureoffenkenstrain +import content.data.Quests import core.api.* import core.game.dialogue.FacialExpression import core.game.global.action.DoorActionHandler @@ -60,7 +61,7 @@ class CreatureOfFenkenstrainListeners : InteractionListener { // 1: Reading Signpost to start the quest on(Items.NULL_5164, SCENERY, "read") { player, _ -> - if (getQuestStage(player, CreatureOfFenkenstrain.questName) < 7 ) { + if (getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) < 7 ) { sendDialogueLines( player, "The signpost has a note pinned onto it. The note says:", @@ -75,8 +76,11 @@ class CreatureOfFenkenstrainListeners : InteractionListener { "'AAARRGGGHHHHH!!!!!'", ) } - if(getQuest(player, CreatureOfFenkenstrain.questName).hasRequirements(player) && getQuestStage(player, CreatureOfFenkenstrain.questName) == 0) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 1) + if(getQuest(player, Quests.CREATURE_OF_FENKENSTRAIN).hasRequirements(player) && getQuestStage( + player, + Quests.CREATURE_OF_FENKENSTRAIN + ) == 0) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 1) } return@on true } @@ -195,7 +199,7 @@ class CreatureOfFenkenstrainListeners : InteractionListener { on(Items.NULL_5167, SCENERY, "search") { player, node -> val scenery = node.asScenery() if(getAttribute(player, CreatureOfFenkenstrain.attributeUnlockedMemorial, false) || - getQuestStage(player, CreatureOfFenkenstrain.questName) > 2) { + getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) > 2) { animateScenery(player, scenery, 1620) var dest: Location? = null if(scenery.location.equals(Location(3505, 3571))) { @@ -226,7 +230,7 @@ class CreatureOfFenkenstrainListeners : InteractionListener { on(Items.NULL_5167, SCENERY, "push") { player, node -> val scenery = node.asScenery() if (getAttribute(player, CreatureOfFenkenstrain.attributeUnlockedMemorial, false) || - getQuestStage(player, CreatureOfFenkenstrain.questName) > 2) { + getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) > 2) { animateScenery(player, scenery, 1620) var dest: Location? = null if(scenery.location.equals(Location(3505, 3571))) { @@ -252,7 +256,7 @@ class CreatureOfFenkenstrainListeners : InteractionListener { // 5: Garden Shed Door on(Scenery.DOOR_5174, SCENERY, "open") { player, node -> if (getAttribute(player, CreatureOfFenkenstrain.attributeUnlockedShed, false) || - getQuestStage(player, CreatureOfFenkenstrain.questName) >= 5) { + getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) >= 5) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else if (inInventory(player, Items.SHED_KEY_4186)) { if (removeItem(player, Items.SHED_KEY_4186)) { @@ -268,7 +272,7 @@ class CreatureOfFenkenstrainListeners : InteractionListener { // 5: Garden Shed Door onUseWith(SCENERY, Items.SHED_KEY_4186, Scenery.DOOR_5174) { player, used, with -> if (getAttribute(player, CreatureOfFenkenstrain.attributeUnlockedShed, false) || - getQuestStage(player, CreatureOfFenkenstrain.questName) >= 5) { + getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) >= 5) { DoorActionHandler.handleAutowalkDoor(player, with.asScenery()) } else if (removeItem(player, used)) { DoorActionHandler.handleAutowalkDoor(player, with.asScenery()) @@ -342,8 +346,8 @@ class CreatureOfFenkenstrainListeners : InteractionListener { return@on true } if (removeItem(player, Items.CONDUCTOR_4201)) { - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 4) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 5) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 4) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 5) } sendDialogue(player, "You repair the lightning conductor not one moment too soon - a tremendous bold of lightning melts the new lightning conductor, and power blazes throughout the castle, if only briefly.") val scenery = node.asScenery() @@ -355,7 +359,10 @@ class CreatureOfFenkenstrainListeners : InteractionListener { // 6: Enter jail above on(Scenery.DOOR_5172, SCENERY, "open") { player, node -> - if (inInventory(player, Items.TOWER_KEY_4185) || getQuestStage(player, CreatureOfFenkenstrain.questName) > 7) { + if (inInventory(player, Items.TOWER_KEY_4185) || getQuestStage( + player, + Quests.CREATURE_OF_FENKENSTRAIN + ) > 7) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else { sendMessage(player, "The door is locked.") @@ -373,10 +380,10 @@ class CreatureOfFenkenstrainListeners : InteractionListener { // 7: Pickpocket Ring of Charos from Fenkenstrain on(NPCs.DR_FENKENSTRAIN_1670, NPC, "pickpocket") { player, node -> - if (getQuestStage(player, CreatureOfFenkenstrain.questName) == 7) { + if (getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 7) { sendMessage(player, "You steal the Ring of Charos from Fenkenstrain.") - finishQuest(player, CreatureOfFenkenstrain.questName) - } else if (getQuestStage(player, CreatureOfFenkenstrain.questName) > 7 && hasAnItem(player, Items.RING_OF_CHAROS_4202).container == null) { + finishQuest(player, Quests.CREATURE_OF_FENKENSTRAIN) + } else if (getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) > 7 && hasAnItem(player, Items.RING_OF_CHAROS_4202).container == null) { // Allow Fenkenstrain to be pickpocketed beyond the quest if the ring is lost. addItemOrDrop(player, Items.RING_OF_CHAROS_4202, 1) sendMessage(player, "You steal the Ring of Charos from Fenkenstrain.") diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/DrFenkenstrainDialogue.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/DrFenkenstrainDialogue.kt index a4fcea45d..c6e848f86 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/DrFenkenstrainDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/DrFenkenstrainDialogue.kt @@ -1,5 +1,6 @@ package content.region.morytania.quest.creatureoffenkenstrain +import content.data.Quests import core.api.* import core.game.dialogue.* import core.game.node.entity.player.Player @@ -65,13 +66,13 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(CREATURE_OF_FENKENSTRAIN, 0) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 0) .npcl("Have you come to apply for the job?") .playerl(FacialExpression.THINKING, "What job?") .npcl("I've posted a note on the signpost in Canifis about it. Go take a look at it first.") .end() - b.onQuestStages(CREATURE_OF_FENKENSTRAIN, 1) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 1) .npcl("Have you come to apply for the job?") .options().let { optionBuilder -> val continuePath = b.placeholder() @@ -127,12 +128,12 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { .npcl("I need you to get me enough dead body parts for me to stitch together a complete body, which I plan to bring to life.") .playerl("Right...okay...if you insist.") .endWith { _, player -> - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 1) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 2) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 1) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 2) } } - b.onQuestStages(CreatureOfFenkenstrain.questName, 2) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 2) .options().let { optionBuilder -> val continuePath = b.placeholder() @@ -184,12 +185,12 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { .npcl("Oh bother! I haven't got a needle or thread!") .npcl("Go and get me a needle, and I'll need 5 lots of thread.") .endWith { _, player -> - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 2) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 3) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 2) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 3) } } - b.onQuestStages(CreatureOfFenkenstrain.questName, 3) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 3) .npcl("Where are my needle and thread, @name?") // Dialogue path to look for 1 needle. .let{ builder -> return@let hasPart(builder, Item(Items.NEEDLE_1733, 1), CreatureOfFenkenstrain.attributeNeedle, "Ah, a needle. Wonderful.") } @@ -219,19 +220,19 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { .playerl("Repair the lightning conductor, right. Can I have a break, soon? By law I'm entitled to 15 minutes every-") .npcl("Repair the conductor and BEGONE!!") .endWith { _, player -> - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 3) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 4) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 3) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 4) } } - b.onQuestStages(CreatureOfFenkenstrain.questName, 4) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 4) .playerl(FacialExpression.THINKING, "How do I repair the lighting conductor?") .npcl("Oh, it would be easier to do it myself! If you find a conductor mould you should be able to cast a new one.") .npcl("Remember this, @name, my experiment will only work with a conductor made from silver.") .end() - b.onQuestStages(CreatureOfFenkenstrain.questName, 5) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 5) .playerl("So did it work, then?") .npcl("Yes, I'm afraid it did, @name - all too well.") .playerl(FacialExpression.SUSPICIOUS, "I can't see it anywhere.") @@ -244,19 +245,19 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { .playerl(FacialExpression.SUSPICIOUS, "What do you want me to do about it?") .npcl("Destroy it!!! Take the key to the Tower and take back the life I never should have granted!!!") .endWith() { df, player -> - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 5) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 6) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 5) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 6) } addItemOrDrop(player, Items.TOWER_KEY_4185) } - b.onQuestStages(CreatureOfFenkenstrain.questName, 6) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 6) .npcl("So have you destroyed it?!!?") .playerl("Not yet.") .npcl("Please, hurry - save me!!!!") .end() - b.onQuestStages(CreatureOfFenkenstrain.questName, 7) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 7) .npcl("So have you destroyed it?!!?") .playerl("Never, now that he has told me the truth!") .npcl("Oh my, oh my, this is exactly what I feared!") @@ -265,7 +266,7 @@ class DrFenkenstrainDialogueFile : DialogueBuilderFile() { .npcl("No! I refuse to release you! You must help me build another creature to destroy this dreadful mistake!!") .end() - b.onQuestStages(CreatureOfFenkenstrain.questName, 8, 100) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 8, 100) .npcl("theyrecomingtogetme theyrecomingtogetme...") .playerl("It is all you deserve. Lord Rologarth is master of this castle once more. Let him protect you - if he wants to.") .npcl("theyrecomingtogetme theyrecomingtogetme...") diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/GardenerGhostDialogue.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/GardenerGhostDialogue.kt index 712ab5100..70387d2c8 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/GardenerGhostDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/GardenerGhostDialogue.kt @@ -1,12 +1,10 @@ package content.region.morytania.quest.creatureoffenkenstrain +import content.data.Quests import core.api.* import core.game.dialogue.* import core.game.node.entity.player.Player -import core.game.node.item.Item import core.plugin.Initializable -import core.tools.END_DIALOGUE -import core.tools.START_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs import java.util.* @@ -41,7 +39,7 @@ class GardenerGhostDialogueFile : DialogueBuilderFile() { b.onPredicate { player -> !player.equipment.containsAtLeastOneItem(Items.GHOSTSPEAK_AMULET_552) } .npcl("Wooo wooo wooooo.") .end() - b.onQuestStages(CreatureOfFenkenstrain.questName, *(0 .. 8).toIntArray(), 100) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, *(0..8).toIntArray(), 100) .options().let { optionBuilder -> optionBuilder.option("Tell me about Fenkenstrain.") .playerl("Can you tell me anything about Fenkenstrain?") @@ -57,14 +55,20 @@ class GardenerGhostDialogueFile : DialogueBuilderFile() { .npcl("Don't worry yerself. I'm not worried about bein' dead. Worse things could happen, I suppose.") .npcl("One thing I do know is, there ain't no lord of the castle anymore, 'cept for old Fenky. Makes ya think a bit, don't it?") .end() - optionBuilder.optionIf("Do you know where the key to the shed is?") { player -> return@optionIf getQuestStage(player, CreatureOfFenkenstrain.questName) == 4 } + optionBuilder.optionIf("Do you know where the key to the shed is?") { player -> return@optionIf getQuestStage( + player, + Quests.CREATURE_OF_FENKENSTRAIN + ) == 4 } .item(Items.GHOSTSPEAK_AMULET_552, "You feel power emanate from the Amulet of Ghostspeak", "and the air around you vibrates with the ghostly voice", "of the headless gardener.") .npcl("Got it right 'ere in my pocket. Here you go.") .iteml(4186, "The headless gardener hands you a rusty key.") .endWith { _, player -> addItemOrDrop(player, Items.SHED_KEY_4186) } - optionBuilder.optionIf("Do you know where I can find a lightning conductor mould is?") { player -> return@optionIf getQuestStage(player, CreatureOfFenkenstrain.questName) == 4 } + optionBuilder.optionIf("Do you know where I can find a lightning conductor mould is?") { player -> return@optionIf getQuestStage( + player, + Quests.CREATURE_OF_FENKENSTRAIN + ) == 4 } .item(Items.GHOSTSPEAK_AMULET_552, "You feel power emanate from the Amulet of Ghostspeak", "and the air around you vibrates with the ghostly voice", "of the headless gardener.") .npcl("A conductor mould, you say? Let me see...") .npcl("There used to be a bloke 'ere, sort of an 'andyman 'e was. Did everything 'round the place - fixed what was broke, swept the chimneys and the like. He would 'ave had a mould, I imagine.") @@ -80,7 +84,10 @@ class GardenerGhostDialogueFile : DialogueBuilderFile() { .playerl("Would you show me where the place was?") .npcl("Well, oi s'pose oi've got ten minutes to spare.") .endWith { df, player -> (df.npc!! as GardenerGhostNPC).startFollowing(player) } - optionBuilder.optionIf("What's your name?") { player -> return@optionIf getQuestStage(player, CreatureOfFenkenstrain.questName) < 4 } + optionBuilder.optionIf("What's your name?") { player -> return@optionIf getQuestStage( + player, + Quests.CREATURE_OF_FENKENSTRAIN + ) < 4 } .playerl("What's your name?") .item(Items.GHOSTSPEAK_AMULET_552, "You feel power emanate from the Amulet of Ghostspeak", "and the air around you vibrates with the ghostly voice", "of the headless gardener.") .npcl("Me name? It's been a moivellous long while, mate, since I had any use for such a thing as a name.") diff --git a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/LordRologarthDialogue.kt b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/LordRologarthDialogue.kt index de32db2a3..6fd066de5 100644 --- a/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/LordRologarthDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/creatureoffenkenstrain/LordRologarthDialogue.kt @@ -1,11 +1,11 @@ package content.region.morytania.quest.creatureoffenkenstrain +import content.data.Quests import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs @@ -27,7 +27,7 @@ class LordRologarthDialogue (player: Player? = null) : DialoguePlugin(player) { class LordRologarthDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { - b.onQuestStages(CreatureOfFenkenstrain.questName, 6) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 6) .playerl("I am commanded to destroy you, creature!") .npcl("Oh that's *hic* not very *hic* nice ...") .playerl("Are you feeling ok?") @@ -49,11 +49,11 @@ class LordRologarthDialogueFile : DialogueBuilderFile() { .playerl("That's it - I'm leaving this dreadful place, whether I get paid or not. Is there anything I can do for you before I leave?") .npcl("Only one - please stop Fenkenstrain from carrying on his experiments, once and for all, so that no other poor soul has to endure suffering such as that of my people and I.") .endWith() { df, player -> - if(getQuestStage(player, CreatureOfFenkenstrain.questName) == 6) { - setQuestStage(player, CreatureOfFenkenstrain.questName, 7) + if(getQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN) == 6) { + setQuestStage(player, Quests.CREATURE_OF_FENKENSTRAIN, 7) } } - b.onQuestStages(CreatureOfFenkenstrain.questName, 7) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 7) .playerl(FacialExpression.THINKING, "Do you know how I can stop Fenkenstrain's experiments?") .npcl("Take the Ring of Charos from him.") .playerl(FacialExpression.THINKING, "What is this ring?") @@ -61,7 +61,7 @@ class LordRologarthDialogueFile : DialogueBuilderFile() { .npcl("The Ring of Charos has many powers, but Fenkenstrain has bent them to his down evil purposes. Without the power of the ring, he will not be able to raise the dead from their sleep.") .npcl("It has one other, extremely important use - it confuses the werewolves' senses, making them believe that they smell one of their own kind. Without the ring, Fenkenstrain will be at their mercy.") .end() - b.onQuestStages(CreatureOfFenkenstrain.questName, 8, 100) + b.onQuestStages(Quests.CREATURE_OF_FENKENSTRAIN, 8, 100) .npcl("How goes it, friend?") .playerl("I stole the Ring of Charos from Fenkenstrain.") .npcl("I saw him climb up into the Tower to hide. It doesn't matter - soon the werewolves will come for him, and his experiments will be forever ceased.") diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NSDrezelDialogue.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NSDrezelDialogue.kt index 4ff9d60c4..8bfa2330f 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NSDrezelDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NSDrezelDialogue.kt @@ -11,11 +11,12 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE import org.rs09.consts.Sounds +import content.data.Quests class NSDrezelDialogue : DialogueFile() { var questStage = 0 override fun handle(componentID: Int, buttonID: Int) { - questStage = player!!.questRepository.getStage("Nature Spirit") + questStage = player!!.questRepository.getStage(Quests.NATURE_SPIRIT) if(questStage <= 5){ when(stage){ @@ -51,12 +52,12 @@ class NSDrezelDialogue : DialogueFile() { if(questStage == 0){ repeat(3) { addItemOrDrop(player!!, Items.MEAT_PIE_2327, 1) } repeat(3) { addItemOrDrop(player!!, Items.APPLE_PIE_2323, 1) } - player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, 5) + player!!.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player!!, 5) } stage++ } 23 -> npcl(FacialExpression.NEUTRAL, "Please take this food to Filliman, he'll probably appreciate a bit of cooked food. Now, he's never revealed where he lives in the swamps but I guess he'd be to the south, search for him won't you?").also { stage++ } - 24 -> playerl(FacialExpression.FRIENDLY, "I'll do my very best, don't worry, if he's in there and he's still alive I'll definitely find him.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Nature Spirit").start(player!!) } + 24 -> playerl(FacialExpression.FRIENDLY, "I'll do my very best, don't worry, if he's in there and he's still alive I'll definitely find him.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest(Quests.NATURE_SPIRIT).start(player!!) } } } @@ -85,7 +86,7 @@ class NSDrezelDialogue : DialogueFile() { } else if(questStage == 40){ - npcl(FacialExpression.NEUTRAL, "There you go my friend, you're now blessed. It's funny, now I look at you, there seems to be something of the faith about you. Anyway, good luck with your quest!").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, 45) } + npcl(FacialExpression.NEUTRAL, "There you go my friend, you're now blessed. It's funny, now I look at you, there seems to be something of the faith about you. Anyway, good luck with your quest!").also { stage = END_DIALOGUE; player!!.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player!!, 45) } } else { @@ -106,7 +107,7 @@ private class BlessingPulse(val drezel: NPC, val player: Player) : Pulse(){ when(ticks){ 0 -> animate(drezel, 1162).also { spawnProjectile(drezel, player, 268); playAudio(player, Sounds.PRAYER_RECHARGE_2674) } 2 -> visualize(player, Animation(645), Graphics(267, 100)) - 4 -> unlock(player).also { player.questRepository.getQuest("Nature Spirit").setStage(player, 40); return true } + 4 -> unlock(player).also { player.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player, 40); return true } } ticks++ return false diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt index c8e5a1b4a..0be90563f 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt @@ -17,9 +17,9 @@ import core.game.shops.Shops import core.game.interaction.InteractionListener import core.game.interaction.IntType import content.region.morytania.handlers.MortMyreGhastNPC -import core.tools.SystemLogger import core.tools.END_DIALOGUE import core.tools.Log +import content.data.Quests class NSListeners : InteractionListener { @@ -63,7 +63,7 @@ class NSListeners : InteractionListener { } on(GROTTO_ENTRANCE, IntType.SCENERY, "enter"){ player, node -> - val questStage = player.questRepository.getQuest("Nature Spirit").getStage(player) + val questStage = player.questRepository.getQuest(Quests.NATURE_SPIRIT).getStage(player) if(questStage < 55) { val npc = core.game.node.entity.npc.NPC.create(NPCs.FILLIMAN_TARLOCK_1050, Location.create(3440, 3336, 0)) npc.init() @@ -76,7 +76,7 @@ class NSListeners : InteractionListener { } on(GROTTO_ALTAR, IntType.SCENERY, "search"){ player, node -> - val stage = player.questRepository.getStage("Nature Spirit") + val stage = player.questRepository.getStage(Quests.NATURE_SPIRIT) if(stage == 55){ openDialogue(player, FillimanCompletionDialogue(), NPC(NPCs.FILLIMAN_TARLOCK_1050)) return@on true @@ -101,7 +101,7 @@ class NSListeners : InteractionListener { } on(WISHING_WELL, IntType.SCENERY, "make-wish"){ player, node -> - if(player.questRepository.isComplete("Nature Spirit") && player.questRepository.isComplete("Wolf Whistle")) + if(player.questRepository.isComplete(Quests.NATURE_SPIRIT) && player.questRepository.isComplete(Quests.WOLF_WHISTLE)) Shops.openId(player, 241) else sendDialogue(player, "You can't do that yet.") @@ -141,7 +141,7 @@ class NSListeners : InteractionListener { on(intArrayOf(DRUID_POUCH, DRUID_POUCH_EMPTY), IntType.ITEM, "fill"){ player, node -> - if(player.questRepository.getStage("Nature Spirit") >= 75) { + if(player.questRepository.getStage(Quests.NATURE_SPIRIT) >= 75) { if (amountInInventory(player, PEAR) >= 3) { if (node.id != Items.DRUID_POUCH_2958) { removeItem(player, node, Container.INVENTORY) @@ -183,7 +183,7 @@ class NSListeners : InteractionListener { } onUseWith(IntType.NPC, Items.SECATEURS_5329, NPCs.NATURE_SPIRIT_1051) {player, used, with -> - if (!hasRequirement(player, "Fairytale I - Growing Pains")) + if (!hasRequirement(player, Quests.FAIRYTALE_I_GROWING_PAINS)) return@onUseWith true if (amountInInventory(player, Items.COINS_995) < 40000) { sendDialogue(player, "You need 40,000 coins to do this.") @@ -253,7 +253,7 @@ class CompleteSpellPulse(val player: Player) : Pulse(2){ override fun pulse(): Boolean { when(counter++){ 0 -> repeat(6) { spawnProjectile(locations[it], dest, 268, 0, 1000, 0, 40, 20) } - 1 -> player.questRepository.getQuest("Nature Spirit").setStage(player, 60) + 1 -> player.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player, 60) 2 -> player.teleport(player.location.transform(0,0,1)) 3 -> openDialogue(player, NPCs.NATURE_SPIRIT_1051, findLocalNPC(player, NPCs.NATURE_SPIRIT_1051) as NPC).also { unlock(player); return true } } diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NSTarlockDialogue.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NSTarlockDialogue.kt index cfdd8ea17..d7bdaba72 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NSTarlockDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NSTarlockDialogue.kt @@ -6,7 +6,6 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player -import core.game.node.entity.player.link.quest.Quest import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.update.flag.context.Graphics @@ -14,6 +13,7 @@ import core.plugin.Initializable import org.rs09.consts.Items import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests @Initializable class NSTarlockDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -25,7 +25,7 @@ class NSTarlockDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC - val quest = player.questRepository.getQuest("Nature Spirit") + val quest = player.questRepository.getQuest(Quests.NATURE_SPIRIT) questStage = quest.getStage(player) if(questStage > 10 && !inEquipment(player, Items.GHOSTSPEAK_AMULET_552)){ @@ -234,7 +234,7 @@ class NSTarlockDialogue(player: Player? = null) : DialoguePlugin(player) { } fun setQuest(stage: Int){ - player.questRepository.getQuest("Nature Spirit").setStage(player, stage) + player.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player, stage) } } \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritDialogue.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritDialogue.kt index fe4913223..bdf92adea 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritDialogue.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritDialogue.kt @@ -12,11 +12,12 @@ import core.plugin.Initializable import org.rs09.consts.Items import org.rs09.consts.NPCs import core.tools.END_DIALOGUE +import content.data.Quests @Initializable class NatureSpiritDialogue(player: Player? = null) : DialoguePlugin(player){ - val questStage = player?.questRepository?.getStage("Nature Spirit") ?: 0 + val questStage = player?.questRepository?.getStage(Quests.NATURE_SPIRIT) ?: 0 override fun newInstance(player: Player?): DialoguePlugin { return NatureSpiritDialogue(player) } @@ -114,7 +115,7 @@ class NatureSpiritDialogue(player: Player? = null) : DialoguePlugin(player){ //killed all dem buggers bruv 350 -> npcl(FacialExpression.NEUTRAL, "Many thanks my friend, you have completed your quest!").also { stage++ } - 351 -> end().also { player.questRepository.getQuest("Nature Spirit").finish(player) } + 351 -> end().also { player.questRepository.getQuest(Quests.NATURE_SPIRIT).finish(player) } } return true @@ -146,7 +147,7 @@ class NatureSpiritDialogue(player: Player? = null) : DialoguePlugin(player){ if(removeItem(player, Items.SILVER_SICKLE_2961, Container.INVENTORY)){ addItem(player, Items.SILVER_SICKLEB_2963) unlock(player) - player.questRepository.getQuest("Nature Spirit").setStage(player, 70) + player.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player, 70) openDialogue(player, NPCs.NATURE_SPIRIT_1051, findLocalNPC(player, NPCs.NATURE_SPIRIT_1051) as NPC) sendMessage(player, "Your sickle has been blessed! You can bless a new sickle by dipping it into the grotto waters.") } @@ -158,6 +159,6 @@ class NatureSpiritDialogue(player: Player? = null) : DialoguePlugin(player){ } fun setQuest(stage: Int){ - player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, stage) + player!!.questRepository.getQuest(Quests.NATURE_SPIRIT).setStage(player!!, stage) } } \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt index 152254698..87d7107b0 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NatureSpiritQuest.kt @@ -6,9 +6,10 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items +import content.data.Quests @Initializable -class NatureSpiritQuest : Quest("Nature Spirit", 95, 94, 2, 307, 0, 1, 110 ) { +class NatureSpiritQuest : Quest(Quests.NATURE_SPIRIT, 95, 94, 2, 307, 0, 1, 110 ) { override fun newInstance(`object`: Any?): Quest { return this } @@ -21,9 +22,9 @@ class NatureSpiritQuest : Quest("Nature Spirit", 95, 94, 2, 307, 0, 1, 110 ) { line(player, "I can start this quest by speaking to !!Drezel?? in the temple.", line++) line(player, /* The "to" is [sic] */"to !!Saradomin?? at the mouth of the river !!Salve??.", line++) line(player, "I first need to complete :", line++) - line(player, "!!The Restless Ghost.??", line++, isQuestComplete(player, "The Restless Ghost")) - line(player, "!!Priest in Peril.??", line++, isQuestComplete(player, "Priest in Peril")) - if (isQuestComplete(player, "The Restless Ghost") && isQuestComplete(player, "Priest in Peril")) { + line(player, "!!The Restless Ghost.??", line++, isQuestComplete(player, Quests.THE_RESTLESS_GHOST)) + line(player, "!!Priest in Peril.??", line++, isQuestComplete(player, Quests.PRIEST_IN_PERIL)) + if (isQuestComplete(player, Quests.THE_RESTLESS_GHOST) && isQuestComplete(player, Quests.PRIEST_IN_PERIL)) { line(player, "I've completed all the quest requirements.", line++) } line(player, "In order to complete this quest !!level 18 crafting?? would be", line++, getStatLevel(player, Skills.CRAFTING) >= 18) @@ -31,7 +32,7 @@ class NatureSpiritQuest : Quest("Nature Spirit", 95, 94, 2, 307, 0, 1, 110 ) { if (getStatLevel(player, Skills.CRAFTING) >= 18) { line(player, "I have a suitable crafting level for this quest.", line++) } - if (isQuestComplete(player, "The Restless Ghost") && isQuestComplete(player, "Priest in Peril") && getStatLevel(player, Skills.CRAFTING) >= 18) { + if (isQuestComplete(player, Quests.THE_RESTLESS_GHOST) && isQuestComplete(player, Quests.PRIEST_IN_PERIL) && getStatLevel(player, Skills.CRAFTING) >= 18) { line(player, "I have all the requirements for this quest.", line++) } } else if (stage < 100) { diff --git a/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java b/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java index 844cc01c2..b8d7628f1 100644 --- a/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java +++ b/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java @@ -6,6 +6,7 @@ import core.plugin.Initializable; import core.game.node.entity.player.Player; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the quarter master dialogue. @@ -42,7 +43,7 @@ public final class QuarterMasterDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; npc("Hi, would you like to see my wares?"); - if (!hasRequirement(player, "Regicide")) { + if (!hasRequirement(player, Quests.REGICIDE)) { end(); return true; } diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/ElunedDialogue.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/ElunedDialogue.java index 283f98467..67b9ddad7 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/ElunedDialogue.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/ElunedDialogue.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import org.rs09.consts.Items; +import content.data.Quests; /** * Handles Eluned's Dialogue for Roving Elves. @@ -28,7 +29,7 @@ public class ElunedDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); switch (stage) { case 500: end(); @@ -180,7 +181,7 @@ public class ElunedDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); if (quest.getStage(player) == 10) { interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hey there... Islwyn said you may be able to help me.", "He told me you know how to consecrate ground for an", "elven burial. I need to reconsecrate Glarial's resting", "place."); stage = 1; diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java index b24862a1f..9dbb4a6e0 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/IslwynDialogue.java @@ -7,6 +7,7 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.GroundItemManager; import core.game.node.item.Item; +import content.data.Quests; /** * Handles Islwyn's dialogue for Roving Elves. @@ -29,7 +30,7 @@ public class IslwynDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); switch (stage) { case 500: end(); @@ -355,8 +356,8 @@ public class IslwynDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); - final Quest waterfall = player.getQuestRepository().getQuest("Waterfall"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); + final Quest waterfall = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); if (quest.getStage(player) == 0 && waterfall.isCompleted(player)) { interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there."); stage = 0; diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/MossGiantGuardianNPC.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/MossGiantGuardianNPC.java index 842f3cc9b..82685174f 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/MossGiantGuardianNPC.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/MossGiantGuardianNPC.java @@ -13,6 +13,7 @@ import core.game.node.item.Item; import core.game.world.map.Location; import core.plugin.Plugin; import core.plugin.ClassScanner; +import content.data.Quests; /** * The level 84 Moss Giant in Glarial's tomb. @@ -47,7 +48,7 @@ public final class MossGiantGuardianNPC extends AbstractNPC { super.finalizeDeath(killer); if (killer instanceof Player) { final Player player = (Player) killer; - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); if (quest.getStage(player) == 15 && !player.getInventory().contains(RovingElves.CONSECRATION_SEED.getId(), 1)) { player.getPacketDispatch().sendMessages("A small grey seed drops on the ground."); GroundItemManager.create(new Item(RovingElves.CONSECRATION_SEED.getId()), getLocation(), player); diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElves.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElves.java index 52546a877..91d68130e 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElves.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElves.java @@ -6,6 +6,7 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; import core.plugin.ClassScanner; +import content.data.Quests; /** * The Roving Elves quest. @@ -43,7 +44,7 @@ public class RovingElves extends Quest { * Constructs a new {@Code RovingElves} {@Code Object} */ public RovingElves() { - super("Roving Elves", 105, 104, 1, 402, 0, 1, 6); + super(Quests.ROVING_ELVES, 105, 104, 1, 402, 0, 1, 6); } @Override diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java index e24874c99..144b624c1 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.List; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles all the agility obstacles for Roving Elves. @@ -96,7 +97,7 @@ public final class RovingElvesObstacles extends OptionHandler { switch (node.getId()) { case 8742: - if (!hasRequirement(player, "Mourning's End Part I")) + if (!hasRequirement(player, Quests.MOURNINGS_END_PART_I)) return true; player.teleport(player.getLocation().transform(EAST_WEST, 2)); break; diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesPlugin.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesPlugin.java index 243e4823a..38616e8d4 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesPlugin.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesPlugin.java @@ -12,6 +12,7 @@ import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; +import content.data.Quests; /** * Master plugin file for Roving Elves. @@ -39,7 +40,7 @@ public final class RovingElvesPlugin extends OptionHandler { @SuppressWarnings("static-access") @Override public boolean handle(final Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest("Roving Elves"); + final Quest quest = player.getQuestRepository().getQuest(Quests.ROVING_ELVES); if (quest == null) { player.sendMessage("Error! RovingElves quest cannot be found, please contact an admin!"); return true; diff --git a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java index e25b2405e..c240e190b 100644 --- a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java +++ b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java @@ -28,6 +28,7 @@ import core.plugin.ClassScanner; import core.tools.RandomFunction; import static core.api.ContentAPIKt.hasRequirement; +import content.data.Quests; /** * Handles the chaos tunnels. @@ -233,7 +234,7 @@ public final class ChaosTunnelZone extends MapZone implements Plugin { */ private void teleport(Player player, Scenery object) { if (object.getLocation().getX() == 3142 && object.getLocation().getY() == 5545) { - if (hasRequirement(player, "What Lies Below")) + if (hasRequirement(player, Quests.WHAT_LIES_BELOW)) commenceBorkBattle(player); return; } diff --git a/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt b/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt index 83b64acc2..5568d5460 100644 --- a/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt +++ b/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt @@ -5,6 +5,7 @@ import core.game.node.entity.player.Player import core.game.interaction.InterfaceListener import core.game.world.GameWorld import core.api.* +import content.data.Quests /** * Handles the corporeal beast warning interface @@ -16,7 +17,7 @@ class CorporealBeastWarningInterface : InterfaceListener { override fun defineInterfaceListeners() { on(COMPONENT_ID,17){player,component,_,_,_,_ -> - if (!hasRequirement(player, "Summer's End")) + if (!hasRequirement(player, Quests.SUMMERS_END)) return@on true if(player.getAttribute("corp-beast-cave-delay",0) <= GameWorld.ticks) { player.properties.teleportLocation = player.location.transform(4, 0, 0).also { close(player,component) } diff --git a/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java b/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java index 40597b85b..26bb09c1a 100644 --- a/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java +++ b/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java @@ -16,6 +16,7 @@ import core.plugin.Plugin; import org.rs09.consts.Sounds; import static core.api.ContentAPIKt.*; +import content.data.Quests; /** * Represents a plugin used to handle wilderness nodes. @@ -49,7 +50,7 @@ public final class WildernessPlugin extends OptionHandler { ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location.create(3239, 3606, 0), "You climb up the ladder to the surface."); break; case 39188: - if (!hasRequirement(player, "Defender of Varrock")) + if (!hasRequirement(player, Quests.DEFENDER_OF_VARROCK)) break; ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, Location.create(3241, 9991, 0), "You descend into the cavern below."); break; diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 908accc6d..f10fff1c3 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -1,6 +1,7 @@ package core.api import com.moandjiezana.toml.Toml +import content.data.Quests import content.data.consumables.* import content.data.skill.SkillingTool import content.global.handlers.iface.ge.StockMarket @@ -1909,14 +1910,14 @@ fun getQuestPoints(player: Player): Int { /** * Gets the stage for the given quest for the given player */ -fun getQuestStage(player: Player, quest: String): Int { +fun getQuestStage(player: Player, quest: Quests): Int { return player.questRepository.getStage(quest) } /** * Sets the stage for the given quest for the given player */ -fun setQuestStage(player: Player, quest: String, stage: Int) { +fun setQuestStage(player: Player, quest: Quests, stage: Int) { player.questRepository.setStage(QuestRepository.getQuests()[quest]!!, stage) player.questRepository.syncronizeTab(player) } @@ -1924,14 +1925,14 @@ fun setQuestStage(player: Player, quest: String, stage: Int) { /** * Check if a quest is in progress */ -fun isQuestInProgress(player: Player, quest: String, startStage: Int, endStage: Int): Boolean { +fun isQuestInProgress(player: Player, quest: Quests, startStage: Int, endStage: Int): Boolean { return player.questRepository.getStage(quest) in startStage..endStage } /** * Check if a quest is complete */ -fun isQuestComplete(player: Player, quest: String): Boolean { +fun isQuestComplete(player: Player, quest: Quests): Boolean { return player.questRepository.getStage(quest) == 100 } @@ -1941,7 +1942,7 @@ fun isQuestComplete(player: Player, quest: String): Boolean { * @param quest The quest name string * @return the quest object */ -fun getQuest(player: Player, quest: String): Quest { +fun getQuest(player: Player, quest: Quests): Quest { return player.questRepository.getQuest(quest) } @@ -1949,7 +1950,7 @@ fun getQuest(player: Player, quest: String): Quest { /** * Check if a player meets the requirements to start a quest, and then starts it if they do. Returns success bool */ -fun startQuest(player: Player, quest: String): Boolean { +fun startQuest(player: Player, quest: Quests): Boolean { val quest = player.questRepository.getQuest(quest) val canStart = quest.hasRequirements(player) if (!canStart) return false @@ -1960,7 +1961,7 @@ fun startQuest(player: Player, quest: String): Boolean { /** * Finishes a quest, gives rewards, marks as completed, etc */ -fun finishQuest(player: Player, quest: String) { +fun finishQuest(player: Player, quest: Quests) { player.questRepository.getQuest(quest).finish(player) } @@ -2078,7 +2079,7 @@ fun announceIfRare(player: Player, item: Item) { } } -fun hasRequirement (player: Player, req: QuestReq, message: Boolean = true) : Boolean { +fun hasRequirement(player: Player, req: QuestReq, message: Boolean = true) : Boolean { var (isMet, unmetReqs) = req.evaluate(player) val messageList = ArrayList() @@ -2099,9 +2100,9 @@ fun hasRequirement (player: Player, req: QuestReq, message: Boolean = true) : Bo 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.") + messageList.add ("This requires completion of ${(unmetReqs[0] as QuestReq).questReq.quest} to access.") } else { - messageList.add ("You need the pre-reqs for ${req.questReq.questName} to access this.") + messageList.add ("You need the pre-reqs for ${req.questReq.quest} to access this.") messageList.add ("Please check the page in your quest journal for more info.") } @@ -2113,8 +2114,8 @@ fun hasRequirement (player: Player, req: QuestReq, message: Boolean = true) : Bo } @JvmOverloads -fun hasRequirement (player: Player, quest: String, message: Boolean = true) : Boolean { - val questReq = QuestRequirements.values().filter { it.questName.equals(quest, true) }.firstOrNull() ?: return false +fun hasRequirement(player: Player, quest: Quests, message: Boolean = true) : Boolean { + val questReq = QuestRequirements.values().firstOrNull { it.quest == quest } ?: return false return hasRequirement(player, QuestReq(questReq), message) } @@ -2809,15 +2810,15 @@ fun getCredits(player: Player) : Int { } /** - * Asserts that a quest is required, and sends the player "You must have completed the $questName quest $message" + * Asserts that a quest is required, and sends the player "You must have completed the $quest quest $message" * @param player the player we are checking - * @param questName the name of the quest we are checking for - * @param message the text appended to "You must have completed the $questName quest ..." if the quest is not complete. + * @param quest the quest we are checking for + * @param message the text appended to "You must have completed the $quest quest ..." if the quest is not complete. * @return whether or not the quest has been completed */ -fun requireQuest(player: Player, questName: String, message: String) : Boolean { - if (!isQuestComplete(player, questName)) { - sendMessage(player, "You must have completed the $questName quest $message") +fun requireQuest(player: Player, quest: Quests, message: String) : Boolean { + if (!isQuestComplete(player, quest)) { + sendMessage(player, "You must have completed the $quest quest $message") return false } return true diff --git a/Server/src/main/core/game/bots/Script.java b/Server/src/main/core/game/bots/Script.java index cda961420..9c5da330a 100644 --- a/Server/src/main/core/game/bots/Script.java +++ b/Server/src/main/core/game/bots/Script.java @@ -1,5 +1,6 @@ package core.game.bots; +import content.data.Quests; import core.game.node.entity.player.Player; import core.game.node.item.Item; @@ -13,7 +14,7 @@ public abstract class Script { public ArrayList inventory = new ArrayList<>(20); public ArrayList equipment = new ArrayList<>(20); public Map skills = new HashMap<>(); - public ArrayList quests = new ArrayList<>(20); + public ArrayList quests = new ArrayList<>(20); public Player bot; @@ -31,7 +32,7 @@ public abstract class Script { for (Map.Entry skill : skills.entrySet()) { setLevel(skill.getKey(), skill.getValue()); } - for (String quest : quests) { + for (Quests quest : quests) { bot.getQuestRepository().setStage(bot.getQuestRepository().getQuest(quest), 100); } for (Item i : equipment) { diff --git a/Server/src/main/core/game/dialogue/DialogueBuilder.kt b/Server/src/main/core/game/dialogue/DialogueBuilder.kt index cdf781cb9..5b1f542c5 100644 --- a/Server/src/main/core/game/dialogue/DialogueBuilder.kt +++ b/Server/src/main/core/game/dialogue/DialogueBuilder.kt @@ -1,5 +1,6 @@ package core.game.dialogue +import content.data.Quests import core.api.splitLines import core.game.node.entity.player.Player import core.tools.END_DIALOGUE @@ -311,7 +312,7 @@ class DialogueBuilder(var target: DialogueBuilderFile, var clauseIndex: Int = -1 fun defaultDialogue(): DialogueBuilder { return onPredicate({ _ -> return@onPredicate true}) } - fun onQuestStages(name: String, vararg stages: Int): DialogueBuilder { + fun onQuestStages(name: Quests, vararg stages: Int): DialogueBuilder { return onPredicate() { player -> val questStage = player.questRepository.getStage(name) return@onPredicate stages.contains(questStage) diff --git a/Server/src/main/core/game/global/action/DoorActionHandler.java b/Server/src/main/core/game/global/action/DoorActionHandler.java index 98a886839..028030824 100644 --- a/Server/src/main/core/game/global/action/DoorActionHandler.java +++ b/Server/src/main/core/game/global/action/DoorActionHandler.java @@ -1,5 +1,6 @@ package core.game.global.action; +import content.data.Quests; import core.game.node.entity.Entity; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.diary.DiaryType; @@ -84,10 +85,6 @@ public final class DoorActionHandler { return; } DoorConfigLoader.Door d = DoorConfigLoader.Companion.forId(object.getId()); - if (d != null && !d.getQuestRequirement().equals("")) { - if (!hasRequirement(player, d.getQuestRequirement())) - return; - } if (d == null || d.isAutoWalk()) { handleAutowalkDoor(player, object); return; diff --git a/Server/src/main/core/game/node/entity/combat/graves/GravePurchaseInterface.kt b/Server/src/main/core/game/node/entity/combat/graves/GravePurchaseInterface.kt index fb2f2927e..86a589f17 100644 --- a/Server/src/main/core/game/node/entity/combat/graves/GravePurchaseInterface.kt +++ b/Server/src/main/core/game/node/entity/combat/graves/GravePurchaseInterface.kt @@ -43,7 +43,7 @@ class GravePurchaseInterface : InterfaceListener { val cost = selectedType.cost val requirement = selectedType.requiredQuest - if (requirement.isNotEmpty() && !isQuestComplete(player, requirement)) { + if (requirement != null && !isQuestComplete(player, requirement)) { sendDialogue(player, "That gravestone requires completion of $requirement.") return@on true } diff --git a/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt b/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt index 7d4f7bc5b..1a9105873 100644 --- a/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt +++ b/Server/src/main/core/game/node/entity/combat/graves/GraveType.kt @@ -1,8 +1,9 @@ package core.game.node.entity.combat.graves import org.rs09.consts.NPCs +import content.data.Quests -enum class GraveType(val npcId: Int, val cost: Int, val durationMinutes: Int, val isMembers: Boolean, val requiredQuest: String = "", val text: String) { +enum class GraveType(val npcId: Int, val cost: Int, val durationMinutes: Int, val isMembers: Boolean, val requiredQuest: Quests? = null, val text: String) { MEM_PLAQUE(NPCs.GRAVE_MARKER_6565, 0, 2, false, text = "In memory of @name,
who died here."), FLAG(NPCs.GRAVE_MARKER_6568, 50, 2, false, text = MEM_PLAQUE.text), SMALL_GS(NPCs.GRAVESTONE_6571, 500, 2, false, text = "In loving memory of our dear friend @name,
who died in this place @mins ago."), @@ -12,9 +13,9 @@ enum class GraveType(val npcId: Int, val cost: Int, val durationMinutes: Int, va SARA_SYMBOL(NPCs.SARADOMIN_SYMBOL_6583, 50000, 4, true, text = "@name,
an enlightened servant of Saradomin,
perished in this place."), ZAM_SYMBOL(NPCs.ZAMORAK_SYMBOL_6586, 50000, 4, true, text = "@name,
a most bloodthirsty follower of Zamorak,
perished in this place."), GUTH_SYMBOL(NPCs.GUTHIX_SYMBOL_6589, 50000, 4, true, text = "@name,
who walked with the Balance of Guthix,
perished in this place."), - BAND_SYMBOL(NPCs.BANDOS_SYMBOL_6592, 50000, 4, true, requiredQuest = "Land of the Goblins", text = "@name,
a vicious warrior dedicated to Bandos,
perished in this place. "), - ARMA_SYMBOL(NPCs.ARMADYL_SYMBOL_6595, 50000, 4, true, requiredQuest = "Temple of Ikov", text = "@name,
a follower of the Law of Armadyl,
perished in this place."), - ZARO_SYMBOL(NPCs.MEMORIAL_STONE_6598, 50000, 4, true, requiredQuest = "Desert Treasure", text = "@name,
servant of the Unknown Power,
perished in this place."), + BAND_SYMBOL(NPCs.BANDOS_SYMBOL_6592, 50000, 4, true, requiredQuest = Quests.LAND_OF_THE_GOBLINS, text = "@name,
a vicious warrior dedicated to Bandos,
perished in this place. "), + ARMA_SYMBOL(NPCs.ARMADYL_SYMBOL_6595, 50000, 4, true, requiredQuest = Quests.TEMPLE_OF_IKOV, text = "@name,
a follower of the Law of Armadyl,
perished in this place."), + ZARO_SYMBOL(NPCs.MEMORIAL_STONE_6598, 50000, 4, true, requiredQuest = Quests.DESERT_TREASURE, text = "@name,
servant of the Unknown Power,
perished in this place."), ANGEL_DEATH(NPCs.MEMORIAL_STONE_6601, 500000, 5, true, text = "Ye frail mortals who gaze upon this sight,
forget not the fate of @name, once mighty, now
surrendered to the inescapable grasp of destiny.
Requiescat in pace."); companion object { diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index 0217cdbc6..4fcc49823 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -14,12 +14,10 @@ import core.ServerConstants; import core.game.interaction.InteractionListeners; import content.global.handlers.iface.RulesAndInfo; import core.tools.Log; -import core.tools.SystemLogger; import core.game.world.GameWorld; import core.game.world.repository.Repository; import core.game.world.update.UpdateSequence; import core.game.node.entity.player.link.SpellBookManager; -import core.game.node.item.GroundItemManager; import java.util.ArrayList; import java.util.Date; @@ -30,6 +28,7 @@ import java.util.stream.IntStream; import static core.api.ContentAPIKt.*; import static core.tools.GlobalsKt.colorize; +import content.data.Quests; /** @@ -158,10 +157,10 @@ public final class LoginConfiguration { } SpellBookManager.SpellBook currentSpellBook = SpellBookManager.SpellBook.forInterface(player.getSpellBookManager().getSpellBook()); - if (currentSpellBook == SpellBookManager.SpellBook.ANCIENT && !hasRequirement(player, "Desert Treasure")) { + if (currentSpellBook == SpellBookManager.SpellBook.ANCIENT && !hasRequirement(player, Quests.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")) { + } else if (currentSpellBook == SpellBookManager.SpellBook.LUNAR && !hasRequirement(player, Quests.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); } diff --git a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt index 4338de79f..3220e5ea2 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt @@ -6,6 +6,7 @@ import core.api.* import core.game.node.entity.player.Player import core.game.node.item.Item import org.rs09.consts.Items +import content.data.Quests /** * Runs one-time save-version-related hooks. @@ -38,7 +39,7 @@ class SaveVersionHooks : LoginListener { } // Unlock Surok's Theme if eligible - if (getQuestStage(player, "What Lies Below") > 70) { + if (getQuestStage(player, Quests.WHAT_LIES_BELOW) > 70) { player.musicPlayer.unlock(250, false) } diff --git a/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java b/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java index 6452a8c95..00f281939 100644 --- a/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java +++ b/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java @@ -1,5 +1,6 @@ package core.game.node.entity.player.link.emote; +import content.data.Quests; import core.game.container.impl.EquipmentContainer; import core.game.node.entity.player.info.Rights; import core.game.world.map.Direction; @@ -106,7 +107,7 @@ public enum Emotes { public void play(Player player) { if(player.getLocation().getRegionId() == 13206 && !player.getAttribute("mistag-greeted", false)) { RegionManager.getLocalNpcs(player).forEach(npc -> { - if (npc.getId() == 2084 && npc.getLocation().withinDistance(player.getLocation(), 3) && player.getQuestRepository().getQuest("Lost Tribe").getStage(player) == 45) { + if (npc.getId() == 2084 && npc.getLocation().withinDistance(player.getLocation(), 3) && player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 45) { player.getDialogueInterpreter().open(2084,npc,"greeting"); player.setAttribute("/save:mistag-greeted",true); } diff --git a/Server/src/main/core/game/node/entity/player/link/quest/Quest.java b/Server/src/main/core/game/node/entity/player/link/quest/Quest.java index b4fab393c..364d0b95e 100644 --- a/Server/src/main/core/game/node/entity/player/link/quest/Quest.java +++ b/Server/src/main/core/game/node/entity/player/link/quest/Quest.java @@ -1,5 +1,6 @@ package core.game.node.entity.player.link.quest; +import content.data.Quests; import core.game.component.Component; import core.game.node.entity.player.Player; import core.plugin.Plugin; @@ -50,9 +51,9 @@ public abstract class Quest implements Plugin { public static final int REWARD_COMPONENT = 277; /** - * The name of the quest. + * The quest as a Quests item (currently only used for the quest's name). */ - private final String name; + private final Quests quest; /** * The index id of the quest. @@ -76,7 +77,7 @@ public abstract class Quest implements Plugin { /** * Constructs a new {@link Quest} - * @param name of the quest. Prereqs reference this + * @param quest of the quest. Prereqs reference this * @param index of the quest, usually buttonId + 1 * @param buttonId of the quest on the quest list in game * @param questPoints rewarded after completing quest @@ -97,8 +98,8 @@ public abstract class Quest implements Plugin { * if (VARPBIT[451] > 1) return 2; if (VARPBIT[451] == 0) return 0; return 1; }; if (arg0 == 88)
* Use 5 numbers: {0, 451, 0, 1, 2} -> {Ignore, VARPBIT, return 0, return 1, return 2}
*/ - public Quest(String name, int index, int buttonId, int questPoints, int...configs) { - this.name = name; + public Quest(Quests quest, int index, int buttonId, int questPoints, int...configs) { + this.quest = quest; this.index = index; this.buttonId = buttonId; this.questPoints = questPoints; @@ -131,7 +132,7 @@ public abstract class Quest implements Plugin { for (int i = 0; i < 311; i++) { player.getPacketDispatch().sendString("" , JOURNAL_COMPONENT, i); } - player.getPacketDispatch().sendString("" + getName() + "", JOURNAL_COMPONENT, 2); + player.getPacketDispatch().sendString("" + getQuest() + "", JOURNAL_COMPONENT, 2); } @@ -140,8 +141,8 @@ public abstract class Quest implements Plugin { * @param player The player. */ public void finish(Player player) { - if(player.getQuestRepository().isComplete(name)) { - throw new IllegalStateException("Tried to complete quest " + name + " twice, which is not allowed!"); + if(player.getQuestRepository().isComplete(quest)) { + throw new IllegalStateException("Tried to complete quest " + quest + " twice, which is not allowed!"); } for (int i = 0; i < 18; i++) { if (i == 9 || i == 3 || i == 6) { @@ -157,7 +158,7 @@ public abstract class Quest implements Plugin { return true; })); player.getPacketDispatch().sendString("" + player.getQuestRepository().getPoints() + "", 277, 7); - player.getPacketDispatch().sendString("You have completed the " + getName() + " Quest!", 277, 4); + player.getPacketDispatch().sendString("You have completed the " + getQuest() + " Quest!", 277, 4); player.getPacketDispatch().sendMessage("Congratulations! Quest complete!"); int questJingles[] = {152, 153, 154}; playJingle(player, questJingles[new Random().nextInt(3)]); @@ -255,7 +256,7 @@ public abstract class Quest implements Plugin { */ public int[] getConfig(Player player, int stage) { if (configs.length < 4) { - throw new IndexOutOfBoundsException("Quest -> " + name + " configs array length was not valid. config length = " + configs.length + "!"); + throw new IndexOutOfBoundsException("Quest -> " + quest + " configs array length was not valid. config length = " + configs.length + "!"); } if (configs.length >= 5) { // {questVarpId, questVarbitId, valueToSet} @@ -308,8 +309,8 @@ public abstract class Quest implements Plugin { * Gets the name. * @return the name. */ - public String getName() { - return name; + public Quests getQuest() { + return quest; } /** @@ -346,7 +347,7 @@ public abstract class Quest implements Plugin { @Override public String toString() { - return "Quest [name=" + name + ", index=" + index + ", buttonId=" + buttonId + ", questPoints=" + questPoints + ", configs=" + Arrays.toString(configs) + "]"; + return "Quest [name=" + quest + ", index=" + index + ", buttonId=" + buttonId + ", questPoints=" + questPoints + ", configs=" + Arrays.toString(configs) + "]"; } } diff --git a/Server/src/main/core/game/node/entity/player/link/quest/QuestRepository.java b/Server/src/main/core/game/node/entity/player/link/quest/QuestRepository.java index 29f38e8a7..02ccf6b29 100644 --- a/Server/src/main/core/game/node/entity/player/link/quest/QuestRepository.java +++ b/Server/src/main/core/game/node/entity/player/link/quest/QuestRepository.java @@ -1,9 +1,9 @@ package core.game.node.entity.player.link.quest; +import content.data.Quests; import core.game.node.entity.player.Player; import core.tools.Log; -import core.tools.SystemLogger; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -25,7 +25,7 @@ public final class QuestRepository { /** * The static mapping of instanced quests. */ - private static final Map QUESTS = new TreeMap<>(); + private static final Map QUESTS = new TreeMap<>(); /** * The mapping of quest indexes with related stages. @@ -100,7 +100,7 @@ public final class QuestRepository { if(oldStage < stage) { quests.put(quest.getIndex(), stage); } else { - log(this.getClass(), Log.WARN, String.format("Nonmonotonic QuestRepository.setStage call for player \"%s\", quest \"%s\", old stage %d, new stage %d", player.getName(), quest.getName(), oldStage, stage)); + log(this.getClass(), Log.WARN, String.format("Nonmonotonic QuestRepository.setStage call for player \"%s\", quest \"%s\", old stage %d, new stage %d", player.getName(), quest.getQuest(), oldStage, stage)); } } @@ -198,51 +198,49 @@ public final class QuestRepository { /** * Checks if the quest is complete. * - * @param name The name of the quest. + * @param quest The quest. * @return {@code True} if so. */ - public boolean isComplete(String name) { - Quest quest = getQuest(name); - if (quest == null) { - log(this.getClass(), Log.ERR, "Error can't check if quest is complete for " + name); + public boolean isComplete(Quests quest) { + Quest theQuest = getQuest(quest); + if (theQuest == null) { + log(this.getClass(), Log.ERR, "Error can't check if quest is complete for " + quest); return false; } - return quest.getStage(player) >= 100; + return theQuest.getStage(player) >= 100; } /** * Checks if the quest has at least started. * - * @param name The name of the quest. + * @param quest The quest by id. * @return {@code True} if so. */ - public boolean hasStarted(String name) { - Quest quest = getQuest(name); + public boolean hasStarted(Quests quest) { + Quest theQuest = getQuest(quest); if (quest == null) { - log(this.getClass(), Log.ERR, "Error can't check if quest is complete for " + name); + log(this.getClass(), Log.ERR, "Error can't check if quest is complete for " + quest); return false; } - return quest.getStage(player) > 0; + return theQuest.getStage(player) > 0; } /** - * Gets the stage of quest by name. - * - * @param name The name of the quest. + * Gets the stage of quest by id. + * @param quest The quest. * @return The stage. */ - public int getStage(String name) { - var quest = QUESTS.get(name); - if (quest == null) { + public int getStage(Quests quest) { + var theQuest = QUESTS.get(quest); + if (theQuest == null) { return 0; } - return getStage(quest); + return getStage(theQuest); } /** * Gets the stage of a quest. - * * @param quest The quest. * @return The stage. */ @@ -251,13 +249,12 @@ public final class QuestRepository { } /** - * Gets the quest by name. - * - * @param name The name. + * Gets the quest by id. + * @param quest The quest. * @return The quest. */ - public Quest getQuest(String name) { - return QUESTS.get(name); + public Quest getQuest(Quests quest) { + return QUESTS.get(quest); } /** @@ -284,7 +281,7 @@ public final class QuestRepository { * @param quest The quest. */ public static void register(Quest quest) { - QUESTS.put(quest.getName(), quest); + QUESTS.put(quest.getQuest(), quest); } /** @@ -292,7 +289,7 @@ public final class QuestRepository { * * @return the quests. */ - public static Map getQuests() { + public static Map getQuests() { return QUESTS; } diff --git a/Server/src/main/core/game/requirement/Requirement.kt b/Server/src/main/core/game/requirement/Requirement.kt index da5a94a71..d43b68dac 100644 --- a/Server/src/main/core/game/requirement/Requirement.kt +++ b/Server/src/main/core/game/requirement/Requirement.kt @@ -7,6 +7,7 @@ import core.game.node.entity.skill.Skills import kotlin.math.min import java.util.ArrayList +import content.data.Quests interface Requirement { abstract fun evaluate (player: Player) : Pair> @@ -22,7 +23,7 @@ open class SkillReq (val skillId: Int, val level: Int, val soft: Boolean = false open class QuestReq (val questReq: QuestRequirements, val stageRequired: Int = 100) : Requirement { override fun evaluate (player: Player) : Pair> { - val quest = QuestRepository.getQuests()[questReq.questName] + val quest = QuestRepository.getQuests()[questReq.quest] val unmetRequirements = ArrayList() var isMet = true if (quest == null) { @@ -57,144 +58,144 @@ open class QPCumulative (val amount: Int) : Requirement { } } -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)), - ALL_FIRED_UP ("All Fired Up", QuestReq(PRIEST), SkillReq(Skills.FIREMAKING, 43)) +enum class QuestRequirements(val quest: Quests, vararg val requirements: Requirement) { + COOK_ASSIST (Quests.COOKS_ASSISTANT), + DEMON_SLAYER (Quests.DEMON_SLAYER), + DORIC_QUEST (Quests.DORICS_QUEST), + DRAGON_SLAYER (Quests.DRAGON_SLAYER, QPReq(32)), + ERNEST (Quests.ERNEST_THE_CHICKEN), + GOBLIN_DIP (Quests.GOBLIN_DIPLOMACY), + IMP_CATCHER (Quests.IMP_CATCHER), + KNIGHT_SWORD (Quests.THE_KNIGHTS_SWORD, SkillReq(Skills.MINING, 10, true)), + PIRATE_T (Quests.PIRATES_TREASURE), + ALI_RESCUE (Quests.PRINCE_ALI_RESCUE), + RESTLESS_GHOST (Quests.THE_RESTLESS_GHOST), + ROMEO (Quests.ROMEO_JULIET), + RUNE_MYST (Quests.RUNE_MYSTERIES), + SHEEP (Quests.SHEEP_SHEARER), + ARRAV (Quests.SHIELD_OF_ARRAV), + VAMPIRE (Quests.VAMPIRE_SLAYER), + DORIC (Quests.DORICS_QUEST), + RUNE_MYSTERIES(Quests.RUNE_MYSTERIES), + BLACK_KNIGHT(Quests.BLACK_KNIGHTS_FORTRESS, QPReq(12)), + WITCH_POTION (Quests.WITCHS_POTION), + DRUIDIC_RITUAL (Quests.DRUIDIC_RITUAL), + LOST_CITY (Quests.LOST_CITY, SkillReq(Skills.CRAFTING, 31, true), SkillReq(Skills.WOODCUTTING, 36, true)), + WITCH_HOUSE (Quests.WITCHS_HOUSE), + MERLIN (Quests.MERLINS_CRYSTAL), + HERO (Quests.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 (Quests.SCORPION_CATCHER, SkillReq(Skills.PRAYER, 31)), + FAMILY_CREST (Quests.FAMILY_CREST, SkillReq(Skills.MINING, 40, true), SkillReq(Skills.SMITHING, 40, true), SkillReq(Skills.MAGIC, 59, true), SkillReq(Skills.CRAFTING, 40, true)), + FISHING_CONTEST (Quests.FISHING_CONTEST, SkillReq(Skills.FISHING, 10)), + TOTEM (Quests.TRIBAL_TOTEM, SkillReq(Skills.THIEVING, 21)), + MONK (Quests.MONKS_FRIEND), + IKOV (Quests.TEMPLE_OF_IKOV, SkillReq(Skills.THIEVING, 42, true), SkillReq(Skills.RANGE, 40)), + CLOCK_TOWER (Quests.CLOCK_TOWER), + GRAIL (Quests.HOLY_GRAIL, QuestReq (MERLIN), SkillReq (Skills.ATTACK, 20)), + GNOME_VILLAGE (Quests.TREE_GNOME_VILLAGE), + FIGHT_ARENA (Quests.FIGHT_ARENA), + HAZEEL (Quests.HAZEEL_CULT), + SHEEP_HERDER (Quests.SHEEP_HERDER), + PLAGUE_CITY (Quests.PLAGUE_CITY), + SEA_SLUG (Quests.SEA_SLUG, SkillReq(Skills.FIREMAKING, 30, true)), + WATERFALL (Quests.WATERFALL_QUEST), + POTION (Quests.JUNGLE_POTION, SkillReq(Skills.HERBLORE, 3, true), QuestReq(DRUIDIC_RITUAL)), + GRAND_TREE (Quests.THE_GRAND_TREE, SkillReq(Skills.AGILITY, 25, true)), + BIOHAZARD (Quests.BIOHAZARD, QuestReq(PLAGUE_CITY)), + UNDERGROUND_PASS (Quests.UNDERGROUND_PASS, SkillReq (Skills.RANGE, 25), QuestReq(BIOHAZARD), QuestReq(PLAGUE_CITY)), + OBSERVATORY (Quests.OBSERVATORY_QUEST), + TOURIST (Quests.THE_TOURIST_TRAP, SkillReq (Skills.FLETCHING, 10, true), SkillReq(Skills.SMITHING, 20, true)), + WATCHTOWER (Quests.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 (Quests.DWARF_CANNON), + MURDER_MYS (Quests.MURDER_MYSTERY), + DIG_SITE (Quests.THE_DIG_SITE, SkillReq(Skills.AGILITY, 10, true), SkillReq (Skills.HERBLORE, 10, true), SkillReq (Skills.THIEVING, 25, true)), + GERTRUDE (Quests.GERTRUDES_CAT), + SHILO (Quests.SHILO_VILLAGE, QuestReq(POTION), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.AGILITY, 32, true)), + LEGEND (Quests.LEGENDS_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 (Quests.DEATH_PLATEAU), + TROLL_STRONGHOLD (Quests.TROLL_STRONGHOLD, QuestReq(DEATH_PLATEAU), SkillReq(Skills.AGILITY, 15, true)), + EADGAR (Quests.EADGARS_RUSE, QuestReq (DRUIDIC_RITUAL), QuestReq (TROLL_STRONGHOLD), SkillReq(Skills.HERBLORE, 31, true)), + CHOMPY (Quests.BIG_CHOMPY_BIRD_HUNTING, SkillReq (Skills.FLETCHING, 5, true), SkillReq (Skills.COOKING, 30, true), SkillReq(Skills.RANGE, 30, false)), + ELEMENTAL_W1 (Quests.ELEMENTAL_WORKSHOP_I, SkillReq(Skills.MINING, 20, true), SkillReq(Skills.SMITHING, 20, true), SkillReq(Skills.CRAFTING, 20, true)), + PRIEST (Quests.PRIEST_IN_PERIL), + NATURE_SPIRIT (Quests.NATURE_SPIRIT, QuestReq(PRIEST), QuestReq(RESTLESS_GHOST)), + REGICIDE (Quests.REGICIDE, QuestReq (UNDERGROUND_PASS), SkillReq (Skills.CRAFTING, 10), SkillReq(Skills.AGILITY, 56, true)), + TAI_BWO (Quests.TAI_BWO_WANNAI_TRIO, SkillReq (Skills.AGILITY, 15, true), SkillReq(Skills.COOKING, 30), SkillReq(Skills.FISHING, 65, true), QuestReq(POTION)), + SHADES (Quests.SHADES_OF_MORTTON, QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.HERBLORE, 15, true), SkillReq(Skills.FIREMAKING, 5, true)), + FREM_TRIALS (Quests.THE_FREMENNIK_TRIALS, SkillReq(Skills.FLETCHING, 25, true), SkillReq(Skills.WOODCUTTING, 40, true), SkillReq(Skills.CRAFTING, 40, true)), + HORROR_DEEP (Quests.HORROR_FROM_THE_DEEP, SkillReq(Skills.AGILITY, 35, true)), + THRONE (Quests.THRONE_OF_MISCELLANIA, QuestReq(HERO), QuestReq(FREM_TRIALS)), + MONKEY (Quests.MONKEY_MADNESS, QuestReq(GRAND_TREE), QuestReq(GNOME_VILLAGE)), + MINE (Quests.HAUNTED_MINE, QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 35, true)), + TROLL_ROMANCE (Quests.TROLL_ROMANCE, QuestReq(TROLL_STRONGHOLD), SkillReq(Skills.AGILITY, 28, true)), + SEARCH_MYREQUE (Quests.IN_SEARCH_OF_THE_MYREQUE, QuestReq(NATURE_SPIRIT), SkillReq(Skills.AGILITY, 25, true)), + FENKENSTRAIN (Quests.CREATURE_OF_FENKENSTRAIN, QuestReq(PRIEST), QuestReq(RESTLESS_GHOST), SkillReq(Skills.THIEVING, 25, true), SkillReq(Skills.CRAFTING, 20, true)), + ROVING_ELVES (Quests.ROVING_ELVES, QuestReq(REGICIDE), QuestReq(WATERFALL), SkillReq(Skills.AGILITY, 56, true)), + GHOSTS_AHOY (Quests.GHOSTS_AHOY, QuestReq(PRIEST), QuestReq(RESTLESS_GHOST), SkillReq(Skills.AGILITY, 25, true), SkillReq(Skills.COOKING, 20, true)), + FAVOR (Quests.ONE_SMALL_FAVOUR, 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 (Quests.MOUNTAIN_DAUGHTER, SkillReq(Skills.AGILITY, 20, true)), + BETWEEN_ROCK (Quests.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 (Quests.THE_FEUD, SkillReq(Skills.THIEVING, 30)), + GOLEM (Quests.THE_GOLEM, SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.THIEVING, 25, true)), + DESERT (Quests.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 (Quests.ICTHLARINS_LITTLE_HELPER, QuestReq (GERTRUDE)), + TEARS_OF_GUTHIX (Quests.TEARS_OF_GUTHIX, QPReq(43), SkillReq(Skills.FIREMAKING, 49, true), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.MINING, 20, true)), + LOST_TRIBE (Quests.THE_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 (Quests.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 (Quests.RECRUITMENT_DRIVE, QuestReq (BLACK_KNIGHT), QuestReq(DRUIDIC_RITUAL)), + MEP_1 (Quests.MOURNINGS_END_PART_I, SkillReq(Skills.RANGE, 60), SkillReq(Skills.THIEVING, 50), QuestReq(ROVING_ELVES), QuestReq(CHOMPY), QuestReq(SHEEP_HERDER)), + FORGETTABLE (Quests.FORGETTABLE_TALE, SkillReq (Skills.COOKING, 22, true), SkillReq(Skills.FARMING, 17, true), QuestReq(GIANT_DWARF), QuestReq(FISHING_CONTEST)), + GARDEN (Quests.GARDEN_OF_TRANQUILITY, QuestReq(FENKENSTRAIN), SkillReq(Skills.FARMING, 25)), + TWO_CATS (Quests.A_TAIL_OF_TWO_CATS, QuestReq(ICTHLARIN)), + WANTED (Quests.WANTED, QPReq(32), QuestReq(RECRUITMENT_DRIVE), QuestReq(LOST_TRIBE), QuestReq(PRIEST)), + MEP_2 (Quests.MOURNINGS_END_PART_II, QuestReq(MEP_1)), + ZOGRE (Quests.ZOGRE_FLESH_EATERS, QuestReq(CHOMPY), QuestReq(POTION), SkillReq(Skills.SMITHING, 4, true), SkillReq(Skills.HERBLORE, 8, true), SkillReq(Skills.RANGE, 30)), + RUM_DEAL (Quests.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 (Quests.SHADOW_OF_THE_STORM, SkillReq(Skills.CRAFTING, 30, true), QuestReq(GOLEM), QuestReq(DEMON_SLAYER)), + HISTORY (Quests.MAKING_HISTORY, QuestReq(PRIEST), QuestReq(RESTLESS_GHOST)), + RATCATCHERS (Quests.RATCATCHERS, QuestReq(ICTHLARIN), QuestReq(GIANT_DWARF)), + SPIRITS_ELID (Quests.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 (Quests.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 (Quests.THE_HAND_IN_THE_SAND, SkillReq(Skills.THIEVING, 17, true), SkillReq(Skills.CRAFTING, 49, true)), + ENAKHRA (Quests.ENAKHRAS_LAMENT, SkillReq(Skills.CRAFTING, 50, true), SkillReq(Skills.FIREMAKING, 45, true), SkillReq(Skills.PRAYER, 43, true), SkillReq(Skills.MAGIC, 39, true)), + CABIN_FEVER (Quests.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 (Quests.FAIRYTALE_I_GROWING_PAINS, QuestReq(LOST_CITY), QuestReq(NATURE_SPIRIT)), + RFD (Quests.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 (Quests.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 (Quests.A_SOULS_BANE), + BONE_MAN_1 (Quests.RAG_AND_BONE_MAN), + SWAN (Quests.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 (Quests.ROYAL_TROUBLE, SkillReq(Skills.AGILITY, 40, true), SkillReq(Skills.SLAYER, 40, true), QuestReq(THRONE)), + DEATH_DORGESHUUN (Quests.DEATH_TO_THE_DORGESHUUN, QuestReq(LOST_TRIBE), SkillReq(Skills.AGILITY, 23, true), SkillReq(Skills.THIEVING, 23, true)), + FAIRYTALE_2 (Quests.FAIRYTALE_II_CURE_A_QUEEN, QuestReq(FAIRYTALE_1), SkillReq(Skills.THIEVING, 40), SkillReq(Skills.FARMING, 49, true), SkillReq(Skills.HERBLORE, 57, true)), + LUNAR_DIPLOMACY (Quests.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 (Quests.THE_EYES_OF_GLOUPHRIE, QuestReq(GRAND_TREE), SkillReq(Skills.CONSTRUCTION, 5), SkillReq(Skills.MAGIC, 46)), + HALLOWVALE (Quests.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 (Quests.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 (Quests.ELEMENTAL_WORKSHOP_II, QuestReq(ELEMENTAL_W1), SkillReq(Skills.MAGIC, 20, true), SkillReq(Skills.SMITHING, 30, true)), + ARM_ADVENTURE (Quests.MY_ARMS_BIG_ADVENTURE, SkillReq(Skills.FARMING, 29, true), SkillReq(Skills.WOODCUTTING, 10), QuestReq(EADGAR), QuestReq(FEUD), QuestReq(POTION)), + ENL_JOURNEY (Quests.ENLIGHTENED_JOURNEY, QPReq(20), SkillReq(Skills.FIREMAKING, 20, true), SkillReq(Skills.FARMING, 30, true), SkillReq(Skills.CRAFTING, 36, true)), + EAGLE (Quests.EAGLES_PEAK, SkillReq(Skills.HUNTER, 27, true)), + ANMA (Quests.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 (Quests.CONTACT, QuestReq(ALI_RESCUE), QuestReq(ICTHLARIN)), + COLD_WAR (Quests.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 (Quests.THE_FREMENNIK_ISLES, QuestReq(FREM_TRIALS), SkillReq(Skills.CONSTRUCTION, 20, true)), + BRAIN_ROBBERY (Quests.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 (Quests.WHAT_LIES_BELOW, QuestReq(RUNE_MYSTERIES), SkillReq(Skills.RUNECRAFTING, 35)), + OLAF (Quests.OLAFS_QUEST, QuestReq(FREM_TRIALS), SkillReq(Skills.FIREMAKING, 40, true), SkillReq(Skills.WOODCUTTING, 50, true)), + ANOTHER_SLICE (Quests.ANOTHER_SLICE_OF_HAM, SkillReq(Skills.ATTACK, 15), SkillReq(Skills.PRAYER, 25), QuestReq(DEATH_DORGESHUUN), QuestReq(GIANT_DWARF), QuestReq(DIG_SITE)), + DREAM_MENTOR (Quests.DREAM_MENTOR, QuestReq(LUNAR_DIPLOMACY), QuestReq(EADGAR)), + GRIM_TALES (Quests.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 (Quests.KINGS_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 (Quests.TOWER_OF_LIFE, SkillReq(Skills.CONSTRUCTION, 10)), + BONE_MAN_2 (Quests.RAG_AND_BONE_MAN, SkillReq(Skills.SLAYER, 40, true), SkillReq(Skills.DEFENCE, 20), QuestReq(BONE_MAN_1), QuestReq(FREM_TRIALS), QuestReq(FENKENSTRAIN), QuestReq(ZOGRE), QuestReq(WATERFALL)), + LAND_GOBLINS (Quests.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 (Quests.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 (Quests.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 (Quests.SPIRIT_OF_SUMMER, QuestReq(RESTLESS_GHOST), SkillReq(Skills.CONSTRUCTION, 40), SkillReq(Skills.FARMING, 26), SkillReq(Skills.PRAYER, 35), SkillReq(Skills.SUMMONING, 19)), + SUMMERS_END (Quests.SUMMERS_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 (Quests.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 (Quests.SMOKING_KILLS, QuestReq(RESTLESS_GHOST), QuestReq(ICTHLARIN), SkillReq(Skills.CRAFTING, 25), SkillReq(Skills.SLAYER, 35)), + WHILE_GUTHIX_SLEEPS (Quests.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)), + ALL_FIRED_UP (Quests.ALL_FIRED_UP, QuestReq(PRIEST), SkillReq(Skills.FIREMAKING, 43)) } diff --git a/Server/src/main/core/game/shops/Shops.kt b/Server/src/main/core/game/shops/Shops.kt index b96bc5f7c..0a649a891 100644 --- a/Server/src/main/core/game/shops/Shops.kt +++ b/Server/src/main/core/game/shops/Shops.kt @@ -20,6 +20,7 @@ import org.rs09.consts.Components import org.rs09.consts.Items import org.rs09.consts.NPCs import java.io.FileReader +import content.data.Quests /** * The "controller" class for shops. Handles opening shops from various NPC interactions and updating stock, etc. @@ -149,7 +150,7 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe } on(NPCs.FUR_TRADER_1316, IntType.NPC, "trade") { player, node -> - if (!isQuestComplete(player, "Fremennik Trials")) { + if (!isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)) { sendNPCDialogue(player, NPCs.FUR_TRADER_1316, "I don't sell to outerlanders.", core.game.dialogue.FacialExpression.ANNOYED).also { END_DIALOGUE } } else { shopsByNpc[node.id]?.openFor(player) @@ -158,7 +159,7 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe } on(NPCs.CANDLE_MAKER_562, IntType.NPC, "trade") { player, node -> - if (getQuestStage(player, "Merlin's Crystal") > 60) { + if (getQuestStage(player, Quests.MERLINS_CRYSTAL) > 60) { openId(player, 56) } else { shopsByNpc[node.id]?.openFor(player) diff --git a/Server/src/main/core/game/system/command/sets/QuestCommandSet.kt b/Server/src/main/core/game/system/command/sets/QuestCommandSet.kt index 5eda9179b..69ae5c1c5 100644 --- a/Server/src/main/core/game/system/command/sets/QuestCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/QuestCommandSet.kt @@ -57,7 +57,7 @@ class QuestCommandSet : CommandSet(Privilege.ADMIN){ questObject.reset(player) } questObject.updateVarps(player) - notify(player, "Setting " + questObject.name + " to stage $stage") + notify(player, "Setting " + questObject.quest + " to stage $stage") } } @@ -82,7 +82,7 @@ class QuestCommandSet : CommandSet(Privilege.ADMIN){ player.packetDispatch.sendString("" + "Available Quests" + "", 275, 2) for (q in QuestRepository.getQuests().toSortedMap().values) { // Add a space to beginning and end of string for the strikethrough - player.packetDispatch.sendString("" + (if (q.isCompleted(player)) " " else "") + q.name + " ", 275, lineId++) + player.packetDispatch.sendString("" + (if (q.isCompleted(player)) " " else "") + q.quest + " ", 275, lineId++) } } @@ -105,7 +105,7 @@ class QuestCommandSet : CommandSet(Privilege.ADMIN){ stage in 1..99 -> "ff8400" else -> "ff0000" } - admin.packetDispatch.sendString("${q.name}", 275, lineId++) + admin.packetDispatch.sendString("${q.quest}", 275, lineId++) admin.packetDispatch.sendString("Index: ${q.index} | Stage: ${lookupUser.questRepository.getStage(q)}", 275, lineId++) admin.packetDispatch.sendString(" ", 275, lineId++) } diff --git a/Server/src/main/core/game/system/config/DoorConfigLoader.kt b/Server/src/main/core/game/system/config/DoorConfigLoader.kt index 4839e713c..04d23c978 100644 --- a/Server/src/main/core/game/system/config/DoorConfigLoader.kt +++ b/Server/src/main/core/game/system/config/DoorConfigLoader.kt @@ -31,14 +31,12 @@ class DoorConfigLoader { door.isFence = e["fence"].toString().toBoolean() door.isMetal = e["metal"].toString().toBoolean() door.isAutoWalk = e["autowalk"]?.toString()?.toBoolean() ?: false - door.questRequirement = e["questRequirement"]?.toString() ?: "" DOORS[door.id] = door val replacedDoor = Door(door.replaceId) replacedDoor.replaceId = door.id replacedDoor.isFence = door.isFence replacedDoor.isMetal = door.isMetal replacedDoor.isAutoWalk = door.isAutoWalk - replacedDoor.questRequirement = door.questRequirement DOORS[door.replaceId] = replacedDoor count++ } diff --git a/Server/src/test/kotlin/QuestTests.kt b/Server/src/test/kotlin/QuestTests.kt index f400e1bb2..0a4fa7bc8 100644 --- a/Server/src/test/kotlin/QuestTests.kt +++ b/Server/src/test/kotlin/QuestTests.kt @@ -1,3 +1,4 @@ +import content.data.Quests import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.player.link.quest.QuestRepository import org.junit.jupiter.api.Assertions @@ -10,7 +11,7 @@ class QuestTests { testPlayer = TestUtils.getMockPlayer("test") } - class TestQuest : Quest("Test Quest", 0, 0, 1, 1, 0, 1, 2) { + class TestQuest : Quest(Quests.TEST_QUEST, 0, 0, 1, 1, 0, 1, 2) { override fun newInstance(`object`: Any?): Quest { return this } @@ -25,13 +26,13 @@ class QuestTests { @Test fun registerShouldMakeQuestImmediatelyAvailable() { QuestRepository.register(testQuest) - Assertions.assertNotNull(QuestRepository.getQuests()[testQuest.name]) + Assertions.assertNotNull(QuestRepository.getQuests()[testQuest.quest]) } @Test fun registerShouldMakeQuestImmediatelyAvailableToInstances() { QuestRepository.register(testQuest) val instance = QuestRepository(testPlayer) - Assertions.assertNotNull(instance.getQuest(testQuest.name)) + Assertions.assertNotNull(instance.getQuest(testQuest.quest)) } @Test fun getStageOnUnstartedQuestShouldNotThrowException() { @@ -54,8 +55,8 @@ class QuestTests { Assertions.assertThrows(IllegalStateException::class.java, { QuestRepository.register(testQuest) val repo = QuestRepository(testPlayer) - repo.getQuest("Test Quest").finish(testPlayer) - repo.getQuest("Test Quest").finish(testPlayer) + repo.getQuest(Quests.TEST_QUEST).finish(testPlayer) + repo.getQuest(Quests.TEST_QUEST).finish(testPlayer) }, "Quest completed twice without throwing an exception or threw wrong exception!") } } \ No newline at end of file From 718d7e39e148d91cd55cad64fbd8b74c131f1ca1 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Feb 2025 21:32:27 -0700 Subject: [PATCH 199/306] Cracking safes the the Rogue's Den now repeats The repetition will stop if you move away, get low health, or run out of inventory space. --- .../handlers/scenery/ThievingGuidePlugin.java | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java b/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java index 71efac4a5..4d306fc5e 100644 --- a/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java +++ b/Server/src/main/content/global/handlers/scenery/ThievingGuidePlugin.java @@ -81,24 +81,33 @@ public class ThievingGuidePlugin extends OptionHandler { player.getDialogueInterpreter().sendDialogues(2266, null, "And where do you think you're going? A little too eager", "I think. Come and talk to me before you go wandering", "around in there."); break; case "crack": - if (player.getSkills().getLevel(Skills.THIEVING) < 50) { - player.getPacketDispatch().sendMessage("You need to be level " + level + " thief to crack this safe."); - return true; - } - if (player.getInventory().freeSlots() == 0) { - player.getPacketDispatch().sendMessage("Not enough inventory space."); - return true; - } - final boolean success = success(player, Skills.THIEVING); - player.lock(4); - player.getPacketDispatch().sendMessage("You start cracking the safe."); - player.animate(animations[success ? 1 : 0]); + GameWorld.getPulser().submit(new Pulse(3, player) { @Override public boolean pulse() { + if (player.getSkills().getLevel(Skills.THIEVING) < 50) { + player.getPacketDispatch().sendMessage("You need to be level " + level + " thief to crack this safe."); + return true; + } + if (player.getInventory().freeSlots() == 0) { + player.getPacketDispatch().sendMessage("Not enough inventory space."); + return true; + } + if (player.getSkills().getLifepoints() <= 6) { + player.getPacketDispatch().sendMessage("You're too injured to be dealing with traps right now."); + return true; + } + if (player.getLocation().getDistance(node.getLocation()) >= 1) { + return true; + } + + final boolean success = success(player, Skills.THIEVING); + //player.lock(4); + player.getPacketDispatch().sendMessage("You start cracking the safe."); + player.animate(animations[success ? 1 : 0]); if (success) { handleSuccess(player, (Scenery) node); - return true; + return false; } final boolean trapped = RandomFunction.random(3) == 1; if (trapped) { @@ -109,11 +118,12 @@ public class ThievingGuidePlugin extends OptionHandler { @Override public boolean pulse() { player.animate(new Animation(-1, Priority.HIGH)); - return true; + return false; } }); } - return true; + + return false; } }); break; From 8e822234fb014479da82d10274e082ec56c5b095 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 7 Feb 2025 16:40:10 -0700 Subject: [PATCH 200/306] Implemented shared banks aka clan banks Players can talk to a banker to enable clan banks. When enabled, any banking function will use the primary bank of the owner of the clan chat the player is in. This only works while the bank owner is online; if they are offline the player will fallback to their own bank. --- .../content/global/dialogue/BankerDialogue.kt | 60 +++++++++++++++---- .../game/container/impl/BankContainer.java | 20 +++++++ .../core/game/node/entity/player/Player.java | 11 +++- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/Server/src/main/content/global/dialogue/BankerDialogue.kt b/Server/src/main/content/global/dialogue/BankerDialogue.kt index e913ce4f0..7b857da7d 100644 --- a/Server/src/main/content/global/dialogue/BankerDialogue.kt +++ b/Server/src/main/content/global/dialogue/BankerDialogue.kt @@ -45,18 +45,7 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin 2 -> showTopics( Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to access my bank account, please.", 10), - IfTopic( - core.game.dialogue.FacialExpression.FRIENDLY, - "I'd like to switch to my ${getBankAccountName(player, true)} bank account.", - 13, - hasActivatedSecondaryBankAccount(player) - ), - IfTopic( - core.game.dialogue.FacialExpression.FRIENDLY, - "I'd like to open a secondary bank account.", - 20, - !hasActivatedSecondaryBankAccount(player) - ), + Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to switch my default bank account.", 7), Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to check my PIN settings.", 11), Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to collect items.", 12), Topic(core.game.dialogue.FacialExpression.ASKING, "What is this place?", 3), @@ -78,6 +67,53 @@ class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin "Leave your valuables with us if you want to keep them safe." ).also { stage = END_DIALOGUE } + 7 -> showTopics( + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to turn on the Clan bank, please.", + 8, + !(player.getAttribute("clanbank:enabled",false)) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to turn off the Clan bank, please.", + 9, + player.getAttribute("clanbank:enabled",false) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to switch to my ${getBankAccountName(player, true)} bank account.", + 13, + hasActivatedSecondaryBankAccount(player) + ), + IfTopic( + core.game.dialogue.FacialExpression.FRIENDLY, + "I'd like to open a secondary bank account.", + 20, + !hasActivatedSecondaryBankAccount(player) + ), + ) + + 8 -> { + player.setAttribute("/save:clanbank:enabled", true) + + npcl( + core.game.dialogue.FacialExpression.FRIENDLY, + "The Clan bank has been enabled. " + + "If the Clan owner is online, you will access their primary bank account instead of your own." + ).also { stage = 2 } + } + + 9 -> { + player.removeAttribute("clanbank:enabled") + + npcl( + core.game.dialogue.FacialExpression.FRIENDLY, + "The Clan bank has been disabled. " + + "You will now always open your personal bank account." + ).also { stage = 2 } + } + 10 -> { openBankAccount(player) end() diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index f8f994d4d..42421e0eb 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -43,6 +43,11 @@ public final class BankContainer extends Container { */ private Player player; + /** + * Snowscape. The player reference. + */ + private Player owner; + /** * The bank listener. */ @@ -76,6 +81,7 @@ public final class BankContainer extends Container { super(SIZE, ContainerType.ALWAYS_STACK, SortType.HASH); super.register(listener = new BankListener(player)); this.player = player; + this.owner = player; } /** @@ -110,6 +116,18 @@ public final class BankContainer extends Container { ); } + /** + * Snowscape custom. Sets the current player. Used for clan banks. + * @param newplayer The new player assigned to the bank. + */ + public void setPlayer(Player newPlayer) { + // Only modify if the bank is not open, otherwise the player who is accessing it will suddenly be unable to deposit/withdraw + if (!isOpen()) { + this.player = newPlayer; + this.listener.player = newPlayer; + } + } + /** * Open the bank. */ @@ -195,6 +213,8 @@ public final class BankContainer extends Container { player.getInterfaceManager().closeSingleTab(); player.removeAttribute("search"); player.getPacketDispatch().sendRunScript(571, ""); + //Snowscape. Set the player back to the owner of the account. + setPlayer(this.owner); } /** diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index a23d472c7..8a09b46ac 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -1048,11 +1048,20 @@ public class Player extends Entity { return equipment; } - /** + /** Snowscape modifications: Added check for clan bank * Gets the current active bank. * @return Current active bank. */ public BankContainer getBank() { + if (getAttribute("clanbank:enabled",false)) { + Player target = Repository.getPlayerByName(this.getCommunication().getCurrentClan()); + if (target != null) { + target.getBankPrimary().setPlayer(this); + return target.getBankPrimary(); + } + } + //The primary bank.player is changed back to the owner when a player closes it, but if something else, like dialogue, runs a getbank() function then it's never changed back. So this manually changes it when checking our own bank. + bank.setPlayer(this); return useSecondaryBank ? bankSecondary : bank; } From d0fdf08d13ab32ceb8b95eb66ab804230348c8e4 Mon Sep 17 00:00:00 2001 From: Elbarto 2 <25245812-elbarto2@users.noreply.gitlab.com> Date: Tue, 11 Feb 2025 12:18:57 +0000 Subject: [PATCH 201/306] Added Plant Cure, Compost and Supercompost to the ::farmkit admin command --- README.md | 2 +- .../main/core/game/system/command/sets/DevelopmentCommandSet.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 63fff0083..caf98bfe5 100644 --- a/README.md +++ b/README.md @@ -149,4 +149,4 @@ These credits can be spent in the 2009Scape Reward Shop. It's important to be cl Testers are not the only people who can gain credits - other ways of earning credits can be found on [the 2009Scape website](https://2009scape.org/site/game_guide/credits.html). -Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded. +Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded. \ No newline at end of file diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index 24766719d..538bbb43c 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -32,7 +32,7 @@ import core.game.world.repository.Repository @Initializable class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { - val farmKitItems = arrayListOf(Items.RAKE_5341, Items.SPADE_952, Items.SEED_DIBBER_5343, Items.WATERING_CAN8_5340, Items.SECATEURS_5329, Items.GARDENING_TROWEL_5325) + val farmKitItems = arrayListOf(Items.RAKE_5341, Items.SPADE_952, Items.SEED_DIBBER_5343, Items.WATERING_CAN8_5340, Items.SECATEURS_5329, Items.GARDENING_TROWEL_5325,Items.COMPOST_6032, Items.SUPERCOMPOST_6034, Items.PLANT_CURE_6036) val runeKitItems = arrayListOf(Items.AIR_RUNE_556, Items.EARTH_RUNE_557, Items.FIRE_RUNE_554, Items.WATER_RUNE_555, Items.MIND_RUNE_558, Items.BODY_RUNE_559, Items.DEATH_RUNE_560, Items.NATURE_RUNE_561, Items.CHAOS_RUNE_562, Items.LAW_RUNE_563, Items.COSMIC_RUNE_564, Items.BLOOD_RUNE_565, Items.SOUL_RUNE_566, Items.ASTRAL_RUNE_9075) override fun defineCommands() { /** From 8b1763c3bae0e7afa010352f01f77d210f0015cc Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 11 Feb 2025 12:47:06 +0000 Subject: [PATCH 202/306] Improved inventory handling for Jossik --- .../fremennik/dialogue/JossikDialogue.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Server/src/main/content/region/fremennik/dialogue/JossikDialogue.java b/Server/src/main/content/region/fremennik/dialogue/JossikDialogue.java index 4fed3f6b9..2af173c7d 100644 --- a/Server/src/main/content/region/fremennik/dialogue/JossikDialogue.java +++ b/Server/src/main/content/region/fremennik/dialogue/JossikDialogue.java @@ -10,8 +10,11 @@ import core.plugin.Initializable; import java.util.ArrayList; import java.util.List; +import static core.api.ContentAPIKt.addItemOrDrop; +import static core.api.ContentAPIKt.hasAnItem; + /** - * Handles the dialogue for jossik. + * Handles the dialogue for Jossik. * @author Vexia */ @Initializable @@ -71,23 +74,24 @@ public class JossikDialogue extends DialoguePlugin { case 20: boolean missing = false; for (GodBook book : GodBook.values()) { - if (player.getSavedData().getGlobalData().hasCompletedGodBook(book) && !player.hasItem(book.getBook())) { + if (player.getSavedData().getGlobalData().hasCompletedGodBook(book) && hasAnItem(player, book.getBook().getId(), true).getContainer() == null) { + // i.e.: if you have a completed book on file but you lost it missing = true; - player.getInventory().add(book.getBook(), player); - npc("As a matter of fact, I did! This book washed up on the", "beach, and I recognised it as yours!"); + addItemOrDrop(player, book.getBook().getId(), 1); } } int damaged = player.getSavedData().getGlobalData().getGodBook(); - if (damaged != -1 && !player.hasItem(GodBook.values()[damaged].getDamagedBook())) { + if (damaged != -1 && hasAnItem(player, GodBook.values()[damaged].getDamagedBook().getId(), true).getContainer() == null) { + // i.e.: if you have an uncompleted book on file but you lost it missing = true; - player.getInventory().add(GodBook.values()[damaged].getDamagedBook(), player); - npc("As a matter of fact, I did! This book washed up on the", "beach, and I recognised it as yours!"); + addItemOrDrop(player, GodBook.values()[damaged].getDamagedBook().getId(), 1); } if (missing) { + npc("As a matter of fact, I did! This book washed up on the", "beach, and I recognised it as yours!"); stage = 23; return true; } - uncompleted = new ArrayList<>(5); + uncompleted = new ArrayList<>(3); for (GodBook book : GodBook.values()) { if (!player.getSavedData().getGlobalData().hasCompletedGodBook(book)) { uncompleted.add(book); @@ -95,12 +99,12 @@ public class JossikDialogue extends DialoguePlugin { } boolean hasUncompleted = false; for (GodBook book : GodBook.values()) { - if (player.hasItem(book.getDamagedBook())) { + if (hasAnItem(player,book.getDamagedBook().getId(), true).getContainer() != null) { + // i.e.: you have an uncompleted book on file and you still have it -> do not allow the player to get a new one, GL #2035 hasUncompleted = true; } } - if (uncompleted.size() == 0 || hasUncompleted) {// all - // completed. + if (uncompleted.isEmpty() || hasUncompleted) {// all completed. npc("No, sorry adventurer, I haven't."); stage = 23; return true; From 867c3324660894ae266c50598abb9511f2ababad Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Tue, 11 Feb 2025 12:50:41 +0000 Subject: [PATCH 203/306] Populated Gnome Stronghold area --- Server/data/configs/npc_configs.json | 48 +++++++-------- Server/data/configs/npc_spawns.json | 90 ++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 44 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index c8ee4ef73..d462378c8 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -2810,53 +2810,51 @@ "attack_level": "47" }, { - "examine": "Small", + "examine": "Small, even by gnome standards.", "melee_animation": "191", "range_animation": "0", - "defence_animation": "0", + "defence_animation": "193", "weakness": "9", "magic_animation": "0", "death_animation": "196", "name": "Gnome child", "defence_level": "1", "safespot": null, - "lifepoints": "1", + "lifepoints": "2", "strength_level": "1", "id": "159", "range_level": "1", "attack_level": "1" }, { - "examine": "Seems to crawl the caves.", - "melee_animation": "266", - "range_animation": "266", - "attack_speed": "5", - "defence_animation": "267", - "weakness": "9", - "magic_animation": "266", - "death_animation": "265", - "name": "Gnome child", - "defence_level": "23", - "safespot": null, - "lifepoints": "21", - "strength_level": "23", - "id": "160", - "bonuses": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", - "range_level": "1", - "attack_level": "23" - }, - { - "examine": "Small", + "examine": "Small, even by gnome standards.", "melee_animation": "191", "range_animation": "0", - "defence_animation": "0", + "defence_animation": "193", "weakness": "9", "magic_animation": "0", "death_animation": "196", "name": "Gnome child", "defence_level": "1", "safespot": null, - "lifepoints": "1", + "lifepoints": "2", + "strength_level": "1", + "id": "160", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Small, even by gnome standards.", + "melee_animation": "191", + "range_animation": "0", + "defence_animation": "193", + "weakness": "9", + "magic_animation": "0", + "death_animation": "196", + "name": "Gnome child", + "defence_level": "1", + "safespot": null, + "lifepoints": "2", "strength_level": "1", "id": "161", "range_level": "1", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 51afed861..97b54e590 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -193,7 +193,7 @@ }, { "npc_id": "59", - "loc_data": "{3082,3362,0,1,4}-{2602,9640,0,1,0}-{2603,9635,0,1,0}-{2603,9638,0,1,0}-{2605,9637,0,1,0}-{2605,9639,0,1,0}-{2606,9635,0,1,0}-{2606,9646,0,1,0}-{2607,9637,0,1,0}-{2607,9641,0,1,0}-{2607,9644,0,1,0}-{2607,9648,0,1,0}-{2608,9635,0,1,0}-{2608,9642,0,1,0}-{2609,9639,0,1,0}-{2609,9643,0,1,0}-{3102,9881,0,1,3}-{3095,9883,0,1,2}-{3182,3244,0,1,1}-{3162,3223,0,1,7}-{3164,3242,0,1,0}-{3169,3246,0,1,0}-{3170,3250,0,1,0}-{3166,3247,0,1,0}-{3164,3249,0,1,0}-{3157,3226,0,1,0}-{3163,3227,0,1,0}-{3165,3223,0,1,0}-{3194,3236,0,1,0}-{3146,3347,0,1,3}-{2648,9766,0,1,4}-{2653,9761,0,1,3}-{2483,2877,0,1,3}-{2481,2876,0,1,4}-{2457,2867,0,1,4}-{2481,2847,0,1,0}-{2475,2854,0,1,3}-{2482,2873,0,1,3}-{2485,2876,0,1,2}-{2449,2865,0,1,1}-{2461,2880,0,1,5}-{2489,2935,0,1,7}-{2492,2907,0,1,1}-{2487,2894,0,1,2}-{2487,2888,0,1,7}-{2478,2916,0,1,5}-{2485,2902,0,1,3}-{2487,2902,0,1,2}-{2489,2894,0,1,2}-{2490,2905,0,1,7}-{2490,2917,0,1,5}-{2484,2890,0,1,1}-{2491,2927,0,1,1}-{3250,3239,0,1,1}-{3241,3241,0,1,1}-{3249,3249,0,1,1}-{3218,9890,0,1,3}-{3220,9887,0,1,0}-{3218,9887,0,1,1}-{3218,9889,0,1,5}-{3213,9890,0,1,1}-{2496,2890,0,1,4}-{2503,2889,0,1,1}-{2497,2939,0,1,2}-" + "loc_data": "{3082,3362,0,1,4}-{2602,9640,0,1,0}-{2603,9635,0,1,0}-{2603,9638,0,1,0}-{2605,9637,0,1,0}-{2605,9639,0,1,0}-{2606,9635,0,1,0}-{2606,9646,0,1,0}-{2607,9637,0,1,0}-{2607,9641,0,1,0}-{2607,9644,0,1,0}-{2607,9648,0,1,0}-{2608,9635,0,1,0}-{2608,9642,0,1,0}-{2609,9639,0,1,0}-{2609,9643,0,1,0}-{3102,9881,0,1,3}-{3095,9883,0,1,2}-{3182,3244,0,1,1}-{3162,3223,0,1,7}-{3164,3242,0,1,0}-{3169,3246,0,1,0}-{3170,3250,0,1,0}-{3166,3247,0,1,0}-{3164,3249,0,1,0}-{3157,3226,0,1,0}-{3163,3227,0,1,0}-{3165,3223,0,1,0}-{3194,3236,0,1,0}-{3146,3347,0,1,3}-{2648,9766,0,1,4}-{2653,9761,0,1,3}-{2483,2877,0,1,3}-{2481,2876,0,1,4}-{2457,2867,0,1,4}-{2481,2847,0,1,0}-{2475,2854,0,1,3}-{2482,2873,0,1,3}-{2485,2876,0,1,2}-{2449,2865,0,1,1}-{2461,2880,0,1,5}-{2489,2935,0,1,7}-{2492,2907,0,1,1}-{2487,2894,0,1,2}-{2487,2888,0,1,7}-{2478,2916,0,1,5}-{2485,2902,0,1,3}-{2487,2902,0,1,2}-{2489,2894,0,1,2}-{2490,2905,0,1,7}-{2490,2917,0,1,5}-{2484,2890,0,1,1}-{2491,2927,0,1,1}-{3250,3239,0,1,1}-{3241,3241,0,1,1}-{3249,3249,0,1,1}-{3218,9890,0,1,3}-{3220,9887,0,1,0}-{3218,9887,0,1,1}-{3218,9889,0,1,5}-{3213,9890,0,1,1}-{2496,2890,0,1,4}-{2503,2889,0,1,1}-{2497,2939,0,1,2}-{2369,3374,0,1,0}-{2372,3379,0,1,0}-{2378,3366,0,1,0}-{2379,3378,0,1,0}-{2387,3370,0,1,0}-{2394,3365,0,1,0}-{2402,3386,0,1,0}-{2405,3381,0,1,0}-{2407,3387,0,1,0}-{2412,3384,0,1,0}-" }, { "npc_id": "60", @@ -217,15 +217,15 @@ }, { "npc_id": "66", - "loc_data": "{2526,3169,0,1,6}-{2528,3164,0,1,6}-{2529,3169,0,1,1}-{2537,3170,0,1,1}-{2507,3204,0,1,5}-{2506,3205,0,1,6}-{2540,3226,0,1,6}-" + "loc_data": "{2417,3493,1,1,0}-{2418,3495,1,1,0}-{2383,3452,0,1,0}-{2401,3417,0,1,0}-{2402,3422,0,1,0}-{2402,3441,0,1,0}-{2403,3430,0,1,0}-{2408,3441,0,1,0}-{2409,3430,0,1,0}-{2423,3426,0,1,0}-{2427,3428,0,1,0}-{2427,3440,0,1,0}-{2526,3168,0,1,0}-{2529,3163,0,1,0}-{2530,3172,0,1,0}-{2536,3169,0,1,0}-{2435,3460,0,1,0}-{2440,3470,0,1,0}-{2447,3502,0,1,0}-{2457,3462,0,1,0}-{2478,3502,0,1,0}-{2449,3492,1,1,0}-{2450,3490,1,1,0}-{2474,3490,1,1,0}-{2482,3492,1,1,0}-{2482,3498,1,1,0}-{2399,3356,0,1,0}-" }, { "npc_id": "67", - "loc_data": "{2507,3200,0,1,6}-{2516,3212,0,1,1}-" + "loc_data": "{2556,3226,0,1,0}-{2456,3425,0,1,0}-{2459,3421,0,1,0}-{2462,3431,0,1,0}-{2394,3500,1,1,0}-{2417,3483,1,1,0}-{2377,3442,0,1,0}-{2380,3425,0,1,0}-{2383,3433,0,1,0}-{2405,3447,0,1,0}-{2406,3440,0,1,0}-{2393,3451,1,1,0}-{2408,3437,1,1,0}-{2521,3169,0,1,0}-{2521,3171,0,1,0}-{2033,5530,1,1,0}-{2437,3478,0,1,0}-{2442,3465,0,1,0}-{2456,3467,0,1,0}-{2471,3496,0,1,0}-{2474,3508,0,1,0}-{2475,3471,0,1,0}-{2479,3468,0,1,0}-{2486,3470,0,1,0}-{2492,3474,0,1,0}-{2443,3464,1,1,0}-{2443,3502,1,1,0}-{2448,3496,1,1,0}-{2449,3506,1,1,0}-{2457,3498,1,1,0}-{2474,3498,1,1,0}-{2480,3502,1,1,0}-{2481,3482,1,1,0}-{2490,3503,1,1,0}-{2400,3356,0,1,0}-" }, { "npc_id": "68", - "loc_data": "{2518,3209,0,1,3}-{2533,3209,0,1,5}-{2530,3212,0,1,1}-" + "loc_data": "{2400,3514,1,1,0}-{2418,3485,1,1,0}-{2378,3423,0,1,0}-{2393,3435,0,1,0}-{2394,3425,0,1,0}-{2395,3449,0,1,0}-{2403,3433,0,1,0}-{2420,3429,0,1,0}-{2420,3438,0,1,0}-{2522,3172,0,1,0}-{2433,3474,0,1,0}-{2433,3492,0,1,0}-{2458,3497,0,1,0}-{2464,3505,0,1,0}-{2476,3458,0,1,0}-{2445,3502,1,1,0}-{2453,3488,1,1,0}-{2475,3502,1,1,0}-{2465,3490,2,1,0}-{2401,3357,0,1,0}-" }, { "npc_id": "73", @@ -345,7 +345,7 @@ }, { "npc_id": "105", - "loc_data": "{3100,3594,0,1,6}-{3107,3608,0,1,2}-{3099,3602,0,1,0}-{2632,3280,0,1,1}-{2633,3274,0,1,3}-{2696,3329,0,1,4}-{2708,3336,0,1,4}-{3230,3500,0,1,5}-{2988,3671,0,1,0}-{3001,3674,0,1,0}-{2497,3164,0,1,2}-" + "loc_data": "{3100,3594,0,1,6}-{3107,3608,0,1,2}-{3099,3602,0,1,0}-{2632,3280,0,1,1}-{2633,3274,0,1,3}-{2696,3329,0,1,4}-{2708,3336,0,1,4}-{3230,3500,0,1,5}-{2988,3671,0,1,0}-{3001,3674,0,1,0}-{2497,3164,0,1,2}-{2387,3376,0,1,0}-{2398,3366,0,1,0}-{2412,3378,0,1,0}-{2419,3372,0,1,0}-" }, { "npc_id": "106", @@ -389,7 +389,7 @@ }, { "npc_id": "117", - "loc_data": "{3118,9845,0,1,4}-{3111,9844,0,1,6}-{3123,9845,0,1,3}-{3114,9833,0,1,3}-{3110,9841,0,1,1}-{3119,9839,0,1,1}-{3097,9832,0,1,0}-{3101,9832,0,1,1}-{3107,9829,0,1,3}-{3115,9831,0,1,4}-{3109,9835,0,1,4}-{2904,9734,0,1,0}-{2548,3146,0,1,1}-{2542,3145,0,1,4}-{2503,3150,0,1,4}-{3300,3649,0,1,0}-{3044,10321,0,1,2}-{3044,10316,0,1,4}-{3045,10308,0,1,4}-{3048,10317,0,1,2}-" + "loc_data": "{2369,3404,0,1,0}-{3118,9845,0,1,4}-{3111,9844,0,1,6}-{3123,9845,0,1,3}-{3114,9833,0,1,3}-{3110,9841,0,1,1}-{3119,9839,0,1,1}-{3097,9832,0,1,0}-{3101,9832,0,1,1}-{3107,9829,0,1,3}-{3115,9831,0,1,4}-{3109,9835,0,1,4}-{2904,9734,0,1,0}-{2548,3146,0,1,1}-{2542,3145,0,1,4}-{2503,3150,0,1,4}-{3300,3649,0,1,0}-{3044,10321,0,1,2}-{3044,10316,0,1,4}-{3045,10308,0,1,4}-{3048,10317,0,1,2}-" }, { "npc_id": "118", @@ -489,19 +489,39 @@ }, { "npc_id": "153", - "loc_data": "{2415,4466,0,0,0}-{2419,4427,0,0,0}-{2421,4468,0,0,0}-{2426,4431,0,0,0}-{2245,3147,0,1,4}-{2246,3143,0,1,0}-{2242,3140,0,1,3}-{2247,3149,0,1,1}-{2500,3492,0,1,4}-" + "loc_data": "{2540,9820,0,1,0}-{2543,9813,0,1,0}-{2546,9817,0,1,0}-{2464,4421,0,1,0}-{2466,4423,0,1,0}-{2486,4464,0,1,0}-{2556,3444,0,1,0}-{3082,3077,0,1,0}-{3092,3082,0,1,0}-{3109,3090,0,1,0}-{3112,3093,0,1,0}-{2249,3260,0,1,0}-{2250,3257,0,1,0}-{2250,3259,0,1,0}-{2252,3261,0,1,0}-{2253,3256,0,1,0}-{2262,3226,0,1,0}-{2264,3225,0,1,0}-{2266,3229,0,1,0}-{2268,3227,0,1,0}-{2269,3222,0,1,0}-{2269,3224,0,1,0}-{2270,3223,0,1,0}-{2270,3226,0,1,0}-{3200,5954,0,1,0}-{3202,5958,0,1,0}-{3204,5955,0,1,0}-{3204,5959,0,1,0}-{3231,5967,0,1,0}-{3236,5974,0,1,0}-{3237,5968,0,1,0}-{3240,5992,0,1,0}-{3240,5994,0,1,0}-{3242,5990,0,1,0}-{3242,5993,0,1,0}-{3244,5994,0,1,0}-{3246,5989,0,1,0}-{2196,3191,0,1,0}-{2197,3189,0,1,0}-{2198,3181,0,1,0}-{2198,3187,0,1,0}-{2199,3183,0,1,0}-{2199,3187,0,1,0}-{2200,3185,0,1,0}-{2201,3185,0,1,0}-{2204,3180,0,1,0}-{2324,4599,0,1,0}-{2325,4597,0,1,0}-{2326,4589,0,1,0}-{2326,4595,0,1,0}-{2327,4591,0,1,0}-{2327,4595,0,1,0}-{2328,4593,0,1,0}-{2329,4593,0,1,0}-{2332,4588,0,1,0}-{2176,3202,0,1,0}-{2178,3206,0,1,0}-{2180,3203,0,1,0}-{2180,3207,0,1,0}-{2207,3215,0,1,0}-{2212,3222,0,1,0}-{2213,3216,0,1,0}-{2216,3240,0,1,0}-{2216,3242,0,1,0}-{2218,3238,0,1,0}-{2218,3241,0,1,0}-{2220,3242,0,1,0}-{2222,3237,0,1,0}-{2437,3425,0,1,0}-{2438,3422,0,1,0}-{2450,3419,0,1,0}-{2415,4466,0,1,0}-{2419,4427,0,1,0}-{2421,4468,0,1,0}-{2426,4431,0,1,0}-{3175,3226,0,1,0}-{3178,3228,0,1,0}-{3179,3226,0,1,0}-{3182,3251,0,1,0}-{3183,3254,0,1,0}-{2697,6204,0,1,0}-{2698,6201,0,1,0}-{2698,6203,0,1,0}-{2700,6205,0,1,0}-{2701,6200,0,1,0}-{2710,6170,0,1,0}-{2712,6169,0,1,0}-{2714,6173,0,1,0}-{2716,6171,0,1,0}-{2717,6166,0,1,0}-{2717,6168,0,1,0}-{2718,6167,0,1,0}-{2718,6170,0,1,0}-{2478,3373,0,1,0}-{2479,3381,0,1,0}-{2481,3384,0,1,0}-{2490,3371,0,1,0}-{2689,6083,0,1,0}-{2689,6088,0,1,0}-{2690,6094,0,1,0}-{2691,6084,0,1,0}-{2692,6081,0,1,0}-{2692,6090,0,1,0}-{2693,6083,0,1,0}-{2693,6085,0,1,0}-{2693,6090,0,1,0}-{2694,6083,0,1,0}-{2694,6086,0,1,0}-{2695,6082,0,1,0}-{2695,6085,0,1,0}-{2695,6088,0,1,0}-{2695,6091,0,1,0}-{2695,6121,0,1,0}-{2698,6121,0,1,0}-{2699,6082,0,1,0}-{2699,6085,0,1,0}-{2700,6084,0,1,0}-{2701,6085,0,1,0}-{2702,6081,0,1,0}-{2702,6083,0,1,0}-{2703,6119,0,1,0}-{2704,6117,0,1,0}-{2705,6121,0,1,0}-{2730,6091,0,1,0}-{2732,6095,0,1,0}-{2734,6090,0,1,0}-{2735,6094,0,1,0}-{2735,6097,0,1,0}-{2738,6098,0,1,0}-{2416,3404,0,1,0}-{2424,3410,0,1,0}-{2430,3405,0,1,0}-{1906,5223,0,1,0}-{1907,5221,0,1,0}-{3273,6012,0,1,0}-{3274,6009,0,1,0}-{3274,6011,0,1,0}-{3276,6013,0,1,0}-{3277,6008,0,1,0}-{3286,5978,0,1,0}-{3288,5977,0,1,0}-{3290,5981,0,1,0}-{3292,5979,0,1,0}-{3293,5974,0,1,0}-{3293,5976,0,1,0}-{3294,5975,0,1,0}-{3294,5978,0,1,0}-{2828,5091,0,1,0}-{2832,5108,0,1,0}-{2835,5079,0,1,0}-{2846,5067,0,1,0}-{2850,5111,0,1,0}-{2853,5086,0,1,0}-{2864,5071,0,1,0}-{2549,3139,0,1,0}-{2241,3139,0,1,0}-{2241,3144,0,1,0}-{2242,3150,0,1,0}-{2243,3140,0,1,0}-{2244,3137,0,1,0}-{2244,3146,0,1,0}-{2245,3139,0,1,0}-{2245,3141,0,1,0}-{2245,3146,0,1,0}-{2246,3139,0,1,0}-{2246,3142,0,1,0}-{2247,3138,0,1,0}-{2247,3141,0,1,0}-{2247,3144,0,1,0}-{2247,3147,0,1,0}-{2247,3177,0,1,0}-{2250,3177,0,1,0}-{2251,3138,0,1,0}-{2251,3141,0,1,0}-{2252,3140,0,1,0}-{2253,3141,0,1,0}-{2254,3137,0,1,0}-{2254,3139,0,1,0}-{2255,3175,0,1,0}-{2256,3173,0,1,0}-{2257,3177,0,1,0}-{2282,3147,0,1,0}-{2284,3151,0,1,0}-{2286,3146,0,1,0}-{2287,3150,0,1,0}-{2287,3153,0,1,0}-{2290,3154,0,1,0}-" }, { "npc_id": "154", - "loc_data": "{2568,3470,0,1,5}-{2394,4453,0,0,0}-{2394,4457,0,0,0}-{2406,4447,0,0,0}-{2523,3164,0,1,4}-{2534,3173,0,1,3}-{2538,3160,0,1,3}-{2246,3144,0,1,4}-{2245,3147,0,1,4}-{2240,3147,0,1,3}-{2247,3142,0,1,5}-" + "loc_data": "{2475,4459,0,1,0}-{2480,4458,0,1,0}-{2481,4454,0,1,0}-{2488,4465,0,1,0}-{3125,3084,0,1,0}-{2268,3228,0,1,0}-{3202,5955,0,1,0}-{3206,5953,0,1,0}-{3231,5976,0,1,0}-{3233,5974,0,1,0}-{3235,5970,0,1,0}-{3241,5996,0,1,0}-{3242,5988,0,1,0}-{3244,5992,0,1,0}-{2180,3173,0,1,0}-{2193,3187,0,1,0}-{2196,3184,0,1,0}-{2200,3181,0,1,0}-{2200,3188,0,1,0}-{2203,3189,0,1,0}-{2308,4581,0,1,0}-{2321,4595,0,1,0}-{2324,4592,0,1,0}-{2328,4589,0,1,0}-{2328,4596,0,1,0}-{2331,4597,0,1,0}-{2178,3203,0,1,0}-{2182,3201,0,1,0}-{2207,3224,0,1,0}-{2209,3222,0,1,0}-{2211,3218,0,1,0}-{2217,3244,0,1,0}-{2218,3236,0,1,0}-{2220,3240,0,1,0}-{2446,3396,0,1,0}-{2470,3397,0,1,0}-{2394,4453,0,1,0}-{2394,4457,0,1,0}-{2406,4447,0,1,0}-{2422,3489,0,1,0}-{2716,6172,0,1,0}-{2688,6092,0,1,0}-{2690,6087,0,1,0}-{2690,6095,0,1,0}-{2692,6082,0,1,0}-{2692,6088,0,1,0}-{2692,6123,0,1,0}-{2693,6081,0,1,0}-{2694,6125,0,1,0}-{2695,6087,0,1,0}-{2697,6086,0,1,0}-{2697,6087,0,1,0}-{2698,6081,0,1,0}-{2698,6124,0,1,0}-{2700,6083,0,1,0}-{2702,6084,0,1,0}-{2726,6085,0,1,0}-{2727,6081,0,1,0}-{2729,6083,0,1,0}-{2732,6084,0,1,0}-{2378,3418,0,1,0}-{2380,3422,0,1,0}-{2393,3442,0,1,0}-{2397,3440,0,1,0}-{2423,3399,0,1,0}-{2425,3406,0,1,0}-{2427,3402,0,1,0}-{1908,5222,0,1,0}-{3292,5980,0,1,0}-{2831,5070,0,1,0}-{2843,5106,0,1,0}-{2844,5080,0,1,0}-{2860,5079,0,1,0}-{2866,5104,0,1,0}-{2868,5096,0,1,0}-{2240,3148,0,1,0}-{2242,3143,0,1,0}-{2242,3151,0,1,0}-{2244,3138,0,1,0}-{2244,3144,0,1,0}-{2244,3179,0,1,0}-{2245,3137,0,1,0}-{2246,3181,0,1,0}-{2247,3143,0,1,0}-{2249,3142,0,1,0}-{2249,3143,0,1,0}-{2250,3137,0,1,0}-{2250,3180,0,1,0}-{2252,3139,0,1,0}-{2254,3140,0,1,0}-{2278,3141,0,1,0}-{2279,3137,0,1,0}-{2281,3139,0,1,0}-{2284,3140,0,1,0}-" }, { "npc_id": "155", - "loc_data": "{2561,3471,0,1,0}-{3235,3222,0,0,0}-{3255,3226,0,0,0}-" + "loc_data": "{3093,3086,0,1,0}-{3097,3085,0,1,0}-{3129,3091,0,1,0}-{3135,3084,0,1,0}-{2190,3180,0,1,0}-{2318,4588,0,1,0}-{2374,3469,0,1,0}-{2376,3466,0,1,0}-{3254,3230,0,1,0}-{1986,5564,0,1,0}-{2434,3516,0,1,0}-{2479,3501,0,1,0}-" + }, + { + "npc_id": "156", + "loc_data": "{2371,3460,0,1,0}-{2372,3456,0,1,0}-{2422,3467,0,1,0}-{2725,6127,0,1,0}-{2444,3491,0,1,0}-{2277,3183,0,1,0}-" }, { "npc_id": "157", - "loc_data": "{2502,3521,0,1,5}-" + "loc_data": "{2180,2798,0,1,0}-{2209,2812,0,1,0}-{2217,2780,0,1,0}-{1921,5931,0,1,0}-{1947,5908,0,1,0}-{1955,5949,0,1,0}-{1973,5888,0,1,0}-{1975,5918,0,1,0}-{1988,5870,0,1,0}-{2017,5884,0,1,0}-{2025,5852,0,1,0}-{2182,2979,0,1,0}-{2211,2963,0,1,0}-{1931,6038,0,1,0}-{1983,6037,0,1,0}-{2153,2810,0,1,0}-{2172,2806,0,1,0}-{1961,5882,0,1,0}-{1980,5878,0,1,0}-{2242,2788,0,1,0}-{2248,2858,0,1,0}-{2256,2828,0,1,0}-{2284,2874,0,1,0}-{2255,3216,0,1,0}-{2262,3210,0,1,0}-{2271,3204,0,1,0}-{2294,3219,0,1,0}-{2296,3206,0,1,0}-{2298,3201,0,1,0}-{2056,5930,0,1,0}-{2064,5900,0,1,0}-{2092,5946,0,1,0}-{2050,5860,0,1,0}-{3201,5986,0,1,0}-{3254,5972,0,1,0}-{3255,5986,0,1,0}-{3256,6008,0,1,0}-{3257,5973,0,1,0}-{3257,5975,0,1,0}-{3260,5974,0,1,0}-{3261,5977,0,1,0}-{3262,5957,0,1,0}-{2194,3158,0,1,0}-{2216,3188,0,1,0}-{2217,3190,0,1,0}-{2220,3158,0,1,0}-{2222,3141,0,1,0}-{2229,3138,0,1,0}-{2231,3181,0,1,0}-{2236,3155,0,1,0}-{2278,2956,0,1,0}-{2322,4566,0,1,0}-{2344,4596,0,1,0}-{2345,4598,0,1,0}-{2348,4566,0,1,0}-{2350,4549,0,1,0}-{2357,4546,0,1,0}-{2359,4589,0,1,0}-{2364,4563,0,1,0}-{2177,3234,0,1,0}-{2230,3220,0,1,0}-{2231,3234,0,1,0}-{2232,3256,0,1,0}-{2233,3221,0,1,0}-{2233,3223,0,1,0}-{2236,3222,0,1,0}-{2237,3225,0,1,0}-{2238,3205,0,1,0}-{2479,3396,0,1,0}-{2102,2942,0,1,0}-{2108,2919,0,1,0}-{2104,2873,0,1,0}-{2122,6032,0,1,0}-{1912,5945,0,1,0}-{3143,3210,0,1,0}-{3155,3253,0,1,0}-{3163,3261,0,1,0}-{3168,3258,0,1,0}-{2086,6028,0,1,0}-{2703,6160,0,1,0}-{2710,6154,0,1,0}-{2719,6148,0,1,0}-{2742,6163,0,1,0}-{2744,6150,0,1,0}-{2746,6145,0,1,0}-{2314,2960,0,1,0}-{2723,6105,0,1,0}-{2739,6123,0,1,0}-{2744,6108,0,1,0}-{2326,2894,0,1,0}-{2333,2920,0,1,0}-{3279,5968,0,1,0}-{3286,5962,0,1,0}-{3295,5956,0,1,0}-{3318,5971,0,1,0}-{3320,5958,0,1,0}-{3322,5953,0,1,0}-{2134,5966,0,1,0}-{2141,5992,0,1,0}-{2123,2966,0,1,0}-{2175,2965,0,1,0}-{1910,6014,0,1,0}-{1916,5991,0,1,0}-{2540,3167,0,1,0}-{2110,2955,0,1,0}-{1990,6051,0,1,0}-{2019,6035,0,1,0}-{2447,3467,0,1,0}-{2448,3469,0,1,0}-{1918,6027,0,1,0}-{2275,3161,0,1,0}-{2291,3179,0,1,0}-{2296,3164,0,1,0}-{2113,2859,0,1,0}-{2139,2836,0,1,0}-{2147,2877,0,1,0}-{2165,2816,0,1,0}-{2167,2846,0,1,0}-" + }, + { + "npc_id": "158", + "loc_data": "{2693,9776,0,1,0}-{2697,9773,0,1,0}-{2697,9779,0,1,0}-{2700,9770,0,1,0}-{2700,9774,0,1,0}-{2700,9777,0,1,0}-{2701,9781,0,1,0}-{2703,9770,0,1,0}-{2703,9774,0,1,0}-{2703,9779,0,1,0}-{2705,9757,0,1,0}-{2705,9760,0,1,0}-{2705,9766,0,1,0}-{2706,9753,0,1,0}-{2706,9763,0,1,0}-{2706,9772,0,1,0}-{2707,9756,0,1,0}-{2707,9761,0,1,0}-{2708,9758,0,1,0}-" + }, + { + "npc_id": "159", + "loc_data": "{2392,3475,0,1,0}-{2394,3506,0,1,0}-{2396,3471,0,1,0}-{2405,3499,0,1,0}-{2416,3487,0,1,0}-{2413,3445,1,1,0}-{2415,3435,1,1,0}-{2416,3416,1,1,0}-{2424,3434,1,1,0}-{2483,3500,1,1,0}-" + }, + { + "npc_id": "160", + "loc_data": "{2424,3430,1,1,0}-{2474,3500,1,1,0}-" + }, + { + "npc_id": "161", + "loc_data": "{2409,3436,1,1,0}-{2484,3501,1,1,0}-" }, { "npc_id": "162", @@ -509,16 +529,32 @@ }, { "npc_id": "163", - "loc_data": "{2465,9899,0,1,6}-{2477,9896,0,1,6}-{2469,9887,0,1,6}-{2463,9893,0,1,6}-" + "loc_data": "{2451,3414,0,1,0}-{2459,3395,0,1,0}-{2459,3438,0,1,0}-{2462,3395,0,1,0}-{2445,3429,1,1,0}-{2409,3470,1,1,0}-{2416,3466,1,1,0}-{2420,3466,1,1,0}-{2461,9895,0,1,0}-{2465,9894,0,1,0}-{2465,9899,0,1,0}-{2459,3385,0,1,0}-{2463,3385,0,1,0}-{2392,3454,0,1,0}-{2394,3436,0,1,0}-{2408,3452,0,1,0}-{2421,3413,0,1,0}-{2442,3489,0,1,0}-{2450,3485,0,1,0}-{2451,3507,0,1,0}-{2453,3490,0,1,0}-{2459,3503,0,1,0}-{2461,3509,0,1,0}-{2464,3465,0,1,0}-{2464,3468,0,1,0}-{2468,3465,0,1,0}-{2468,3468,0,1,0}-{2468,3506,0,1,0}-{2472,3484,0,1,0}-{2475,3490,0,1,0}-{2475,3502,0,1,0}-{2477,3512,0,1,0}-{2481,3485,0,1,0}-{2482,3501,0,1,0}-{2467,3495,1,1,0}-{2473,3495,1,1,0}-{2448,3497,2,1,0}-{2463,3480,2,1,0}-{2465,3497,2,1,0}-{2465,3510,2,1,0}-{2466,3480,2,1,0}-" + }, + { + "npc_id": "164", + "loc_data": "{2459,3392,0,1,0}-{2461,3422,0,1,0}-{2462,3392,0,1,0}-{2460,3382,0,1,0}-{2462,3382,0,1,0}-{2410,3416,0,1,0}-{2420,3435,0,1,0}-{2420,3447,0,1,0}-{2427,3410,0,1,0}-{2012,5535,2,1,0}-{2023,5544,2,1,0}-{2441,3497,0,1,0}-{2447,3510,0,1,0}-{2461,3487,0,1,0}-{2464,3472,0,1,0}-{2464,3489,0,1,0}-{2467,3489,0,1,0}-{2468,3472,0,1,0}-{2473,3503,0,1,0}-{2478,3497,0,1,0}-{2464,3496,1,1,0}-{2448,3495,2,1,0}-{2460,3487,2,1,0}-{2467,3494,2,1,0}-{2467,3510,2,1,0}-{2471,3496,2,1,0}-{2483,3495,2,1,0}-{2483,3497,2,1,0}-" }, { "npc_id": "166", "loc_data": "{2448,3427,1,0,6}-{2448,3424,1,0,6}-{2443,3424,1,0,3}-{2443,3425,1,0,3}-{2450,3480,1,0,1}-{2449,3480,1,0,1}-{2448,3480,1,0,1}-{2440,3488,1,0,4}-{2440,3487,1,0,4}-" }, + { + "npc_id": "168", + "loc_data": "{2434,3436,0,1,0}-{2437,3451,0,1,0}-{2438,3427,0,1,0}-{2441,3411,0,1,0}-{2466,3449,0,1,0}-{2470,3399,0,1,0}-{2472,3400,0,1,0}-{2473,3412,0,1,0}-{2476,3454,0,1,0}-{2482,3397,0,1,0}-{2489,3401,0,1,0}-{2479,3407,1,1,0}-{2379,3482,0,1,0}-{2381,3496,0,1,0}-{2384,3497,0,1,0}-{2391,3476,0,1,0}-{2410,3496,0,1,0}-{2421,3481,0,1,0}-{2397,3514,1,1,0}-{2398,3451,1,1,0}-{2414,3447,1,1,0}-{2438,3465,0,1,0}-{2442,3505,0,1,0}-{2448,3486,0,1,0}-{2449,3487,0,1,0}-{2450,3489,0,1,0}-{2450,3505,0,1,0}-{2454,3465,0,1,0}-{2449,3486,1,1,0}-{2457,3488,1,1,0}-{2476,3488,1,1,0}-{2450,3496,2,1,0}-{2467,3488,2,1,0}-{2470,3503,2,1,0}-{2481,3498,2,1,0}-" + }, + { + "npc_id": "169", + "loc_data": "{2439,3433,0,1,0}-{2441,3449,0,1,0}-{2442,3428,0,1,0}-{2446,3403,0,1,0}-{2450,3416,0,1,0}-{2468,3441,0,1,0}-{2480,3408,0,1,0}-{2480,3406,1,1,0}-{2486,3400,1,1,0}-{2378,3482,0,1,0}-{2383,3496,0,1,0}-{2402,3507,0,1,0}-{2406,3476,0,1,0}-{2422,3485,0,1,0}-{2382,3506,1,1,0}-{2418,3472,1,1,0}-{2392,3450,1,1,0}-{2415,3415,1,1,0}-{2416,3434,1,1,0}-{2423,3425,1,1,0}-{2424,3442,1,1,0}-{2448,3489,0,1,0}-{2450,3488,0,1,0}-{2463,3508,0,1,0}-{2473,3489,0,1,0}-{2474,3457,0,1,0}-{2479,3503,0,1,0}-{2486,3467,0,1,0}-{2437,3463,1,1,0}-{2448,3489,1,1,0}-{2482,3508,1,1,0}-" + }, { "npc_id": "170", "loc_data": "{2890,3175,0,1,4}-" }, + { + "npc_id": "171", + "loc_data": "{2409,9817,0,1,0}-" + }, { "npc_id": "175", "loc_data": "{3084,3495,0,1,4}-{3179,3215,0,1,0}-{3182,3365,0,1,6}-{2994,9549,0,1,6}-{2993,9551,0,1,6}-{2995,9555,0,1,6}-{2999,9548,0,1,0}-" @@ -1315,6 +1351,14 @@ "npc_id": "478", "loc_data": "{2509,3255,0,1,3}-{2503,3254,1,1,3}-" }, + { + "npc_id": "479", + "loc_data": "{1970,5522,3,1,0}-{2384,3481,0,1,0}-{2388,3473,0,1,0}-{2418,3474,3,1,0}-{2415,3433,3,1,0}-{2466,3500,2,1,0}-" + }, + { + "npc_id": "480", + "loc_data": "{1964,5522,3,1,0}-{2458,3417,1,1,0}-{2460,3417,1,1,0}-{2409,3507,0,1,0}-{2412,3474,3,1,0}-{2463,3504,2,1,0}-" + }, { "npc_id": "481", "loc_data": "{2499,3266,0,0,4}-" @@ -2737,7 +2781,7 @@ }, { "npc_id": "1043", - "loc_data": "{3459,3457,0,0,0}-{3460,3462,0,0,0}-{3462,3459,0,0,0}-{3463,3490,0,0,0}-{3464,3511,0,0,0}-{3465,3466,0,0,0}-{3466,3495,0,0,0}-{3466,3497,0,0,0}-{3467,3485,0,0,0}-{3467,3497,0,0,0}-{3467,3509,0,0,0}-{3469,3470,0,0,0}-{3470,3469,0,0,0}-{3471,3477,0,0,0}-{3474,3505,0,0,0}-{3476,3507,0,0,0}-{3479,3511,0,0,0}-{3480,3468,0,0,0}-{3480,3470,0,0,0}-{3482,3469,0,0,0}-{3483,3511,0,0,0}-{3484,3464,0,0,0}-{3485,3509,0,0,0}-{3490,3461,0,0,0}-{3491,3460,0,0,0}-{3494,3461,0,0,0}-{3494,3512,0,0,0}-{3498,3461,0,0,0}-{3499,3513,0,0,0}-{3501,3513,0,0,0}-{3502,3464,0,0,0}-{3504,3463,0,0,0}-{3506,3512,0,0,0}-{3506,3515,0,0,0}-{3507,3515,0,0,0}-{3509,3512,0,0,0}-{3511,3488,0,0,0}-{3513,3467,0,0,0}-{3513,3487,0,0,0}-{3513,3489,0,0,0}-{3513,3503,0,0,0}-{3514,3490,0,0,0}-{3515,3495,0,0,0}-{3515,3499,0,0,0}-{3516,3469,0,0,0}-" + "loc_data": "{3726,3381,0,0,0}-{3745,3359,0,0,0}-{3749,3365,0,0,0}-{3750,3354,0,0,0}-{3757,3363,0,0,0}-{3763,3337,0,0,0}-{3459,3457,0,0,0}-{3460,3462,0,0,0}-{3462,3459,0,0,0}-{3463,3490,0,0,0}-{3464,3511,0,0,0}-{3465,3466,0,0,0}-{3466,3495,0,0,0}-{3466,3497,0,0,0}-{3467,3485,0,0,0}-{3467,3497,0,0,0}-{3467,3509,0,0,0}-{3469,3470,0,0,0}-{3470,3469,0,0,0}-{3471,3477,0,0,0}-{3474,3505,0,0,0}-{3476,3507,0,0,0}-{3479,3511,0,0,0}-{3480,3468,0,0,0}-{3480,3470,0,0,0}-{3482,3469,0,0,0}-{3483,3511,0,0,0}-{3484,3464,0,0,0}-{3485,3509,0,0,0}-{3490,3461,0,0,0}-{3491,3460,0,0,0}-{3494,3461,0,0,0}-{3494,3512,0,0,0}-{3498,3461,0,0,0}-{3499,3513,0,0,0}-{3501,3513,0,0,0}-{3502,3464,0,0,0}-{3504,3463,0,0,0}-{3506,3512,0,0,0}-{3506,3515,0,0,0}-{3507,3515,0,0,0}-{3509,3512,0,0,0}-{3511,3488,0,0,0}-{3513,3467,0,0,0}-{3513,3487,0,0,0}-{3513,3489,0,0,0}-{3513,3503,0,0,0}-{3514,3490,0,0,0}-{3515,3495,0,0,0}-{3515,3499,0,0,0}-{3516,3469,0,0,0}-{3409,3369,0,0,0}-{3420,3349,0,0,0}-{3430,3340,0,0,0}-{3435,3330,0,0,0}-{3435,3359,0,0,0}-{3437,3374,0,0,0}-{3446,3385,0,0,0}-{3447,3388,0,0,0}-{3450,3370,0,0,0}-{3450,3387,0,0,0}-{3451,3336,0,0,0}-{3452,3355,0,0,0}-{3726,3289,0,0,0}-{3732,3291,0,0,0}-{3737,3280,0,0,0}-{3745,3285,0,0,0}-{3418,3420,0,0,0}-{3424,3452,0,0,0}-{3428,3409,0,0,0}-{3433,3416,0,0,0}-{3434,3394,0,0,0}-{3436,3407,0,0,0}-{3438,3414,0,0,0}-{3439,3449,0,0,0}-{3446,3439,0,0,0}-{3454,3410,0,0,0}-{3454,3423,0,0,0}-{2852,4561,0,0,0}-{2853,4566,0,0,0}-{2856,4568,0,0,0}-{2864,4561,0,0,0}-{2864,4563,0,0,0}-" }, { "npc_id": "1044", @@ -3248,9 +3292,17 @@ "loc_data": "{2194,3140,0,1,5}-" }, { - "npc_id": "1213", + "npc_id": "1211", "loc_data": "{2914,3418,0,0,6}-" }, + { + "npc_id": "1212", + "loc_data": "{2247,3226,0,0,0}-{2249,3227,0,0,0}-{2249,3258,0,0,0}-{2251,3260,0,0,0}-{2259,3211,0,0,0}-{2267,3223,0,0,0}-{2267,3225,0,0,0}-{2298,3262,0,0,0}-{3202,5990,0,0,0}-{3232,5977,0,0,0}-{3234,5969,0,0,0}-{3237,5995,0,0,0}-{3242,5997,0,0,0}-{3244,5995,0,0,0}-{3245,5995,0,0,0}-{2194,3189,0,0,0}-{2196,3187,0,0,0}-{2196,3189,0,0,0}-{2206,3164,0,0,0}-{2209,3164,0,0,0}-{2216,3142,0,0,0}-{2218,3139,0,0,0}-{2178,3238,0,0,0}-{2208,3225,0,0,0}-{2210,3217,0,0,0}-{2213,3243,0,0,0}-{2218,3245,0,0,0}-{2220,3243,0,0,0}-{2221,3243,0,0,0}-{2695,6170,0,0,0}-{2697,6171,0,0,0}-{2697,6202,0,0,0}-{2699,6204,0,0,0}-{2707,6155,0,0,0}-{2715,6167,0,0,0}-{2715,6169,0,0,0}-{2746,6206,0,0,0}-{2729,6086,0,0,0}-{2731,6080,0,0,0}-{2731,6089,0,0,0}-{2744,6139,0,0,0}-{3271,5978,0,0,0}-{3273,5979,0,0,0}-{3273,6010,0,0,0}-{3275,6012,0,0,0}-{3283,5963,0,0,0}-{3291,5975,0,0,0}-{3291,5977,0,0,0}-{3322,6014,0,0,0}-{2281,3142,0,0,0}-{2283,3136,0,0,0}-{2283,3145,0,0,0}-{2296,3195,0,0,0}-" + }, + { + "npc_id": "1213", + "loc_data": "{2248,3225,0,0,0}-{2248,3227,0,0,0}-{2251,3257,0,0,0}-{2253,3259,0,0,0}-{2268,3224,0,0,0}-{2291,3262,0,0,0}-{3204,5988,0,0,0}-{3232,5979,0,0,0}-{3234,5967,0,0,0}-{3234,5976,0,0,0}-{3238,5996,0,0,0}-{3239,5997,0,0,0}-{3243,5996,0,0,0}-{2192,3188,0,0,0}-{2192,3191,0,0,0}-{2194,3190,0,0,0}-{2208,3163,0,0,0}-{2209,3163,0,0,0}-{2216,3136,0,0,0}-{2216,3140,0,0,0}-{2180,3236,0,0,0}-{2208,3227,0,0,0}-{2210,3215,0,0,0}-{2210,3224,0,0,0}-{2214,3244,0,0,0}-{2215,3245,0,0,0}-{2219,3244,0,0,0}-{2696,6169,0,0,0}-{2696,6171,0,0,0}-{2699,6201,0,0,0}-{2701,6203,0,0,0}-{2716,6168,0,0,0}-{2739,6206,0,0,0}-{2730,6084,0,0,0}-{3272,5977,0,0,0}-{3272,5979,0,0,0}-{3275,6009,0,0,0}-{3277,6011,0,0,0}-{3292,5976,0,0,0}-{3315,6014,0,0,0}-{2282,3140,0,0,0}-" + }, { "npc_id": "1214", "loc_data": "{2891,3676,0,0,1}-" @@ -4157,7 +4209,7 @@ }, { "npc_id": "1752", - "loc_data": "{2510,3228,0,1,3}-" + "loc_data": "{2437,3442,0,1,0}-{2449,3421,0,1,0}-{2457,3394,0,1,0}-{2464,3394,0,1,0}-{2480,3406,0,1,0}-{2432,3387,0,1,0}-{2442,3388,0,1,0}-{2453,3363,0,1,0}-{2463,3375,0,1,0}-{2381,3428,0,1,0}-{2392,3405,0,1,0}-{2413,3397,0,1,0}-{2415,3408,0,1,0}-{2463,3456,0,1,0}-{2468,3456,0,1,0}-" }, { "npc_id": "1754", @@ -7941,23 +7993,23 @@ }, { "npc_id": "4689", - "loc_data": "{2902,9736,0,1,0}-" + "loc_data": "{2369,3401,0,1,0}-{2902,9736,0,1,0}-" }, { "npc_id": "4690", - "loc_data": "{3104,3875,0,1,2}-{2912,9731,0,1,0}-{3256,3624,0,1,5}-{3308,3661,0,1,2}-" + "loc_data": "{2372,3401,0,1,0}-{3104,3875,0,1,2}-{2912,9731,0,1,0}-{3256,3624,0,1,5}-{3308,3661,0,1,2}-" }, { "npc_id": "4691", - "loc_data": "{3110,3854,0,1,0}-" + "loc_data": "{2371,3398,0,1,0}-{3110,3854,0,1,0}-" }, { "npc_id": "4692", - "loc_data": "{3116,3858,0,1,0}-" + "loc_data": "{2372,3395,0,1,0}-{3116,3858,0,1,0}-" }, { "npc_id": "4693", - "loc_data": "{3094,3849,0,1,0}-{2912,9741,0,1,0}-{2906,9736,0,1,0}-" + "loc_data": "{2369,3394,0,1,0}-{3094,3849,0,1,0}-{2912,9741,0,1,0}-{2906,9736,0,1,0}-" }, { "npc_id": "4694", From b5784c5782c97994d088dc30f3295e2d7d00a9d4 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Tue, 11 Feb 2025 12:59:25 +0000 Subject: [PATCH 204/306] Implemented Quiz Master random event --- Server/data/configs/npc_spawns.json | 4 + .../main/content/global/ame/RandomEvents.kt | 2 + .../events/quizmaster/QuizMasterBorders.kt | 37 +++++ .../quizmaster/QuizMasterDialogueFile.kt | 132 ++++++++++++++++++ .../ame/events/quizmaster/QuizMasterNPC.kt | 67 +++++++++ 5 files changed, 242 insertions(+) create mode 100644 Server/src/main/content/global/ame/events/quizmaster/QuizMasterBorders.kt create mode 100644 Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt create mode 100644 Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 97b54e590..98df5d25d 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -5599,6 +5599,10 @@ "npc_id": "2462", "loc_data": "{2596,4773,0,1,2}-{2602,4771,0,1,6}-{2596,4780,0,1,4}-" }, + { + "npc_id": "2477", + "loc_data": "{1952,4768,1,0,6}-" + }, { "npc_id": "2479", "loc_data": "{3420,4777,0,0,0}-" diff --git a/Server/src/main/content/global/ame/RandomEvents.kt b/Server/src/main/content/global/ame/RandomEvents.kt index 13d7390ea..9ab78c468 100644 --- a/Server/src/main/content/global/ame/RandomEvents.kt +++ b/Server/src/main/content/global/ame/RandomEvents.kt @@ -13,6 +13,7 @@ import content.global.ame.events.pillory.PilloryNPC import content.global.ame.events.rickturpentine.RickTurpentineNPC import content.global.ame.events.rivertroll.RiverTrollRENPC import content.global.ame.events.rockgolem.RockGolemRENPC +import content.global.ame.events.quizmaster.QuizMasterNPC import content.global.ame.events.sandwichlady.SandwichLadyRENPC import content.global.ame.events.shade.ShadeRENPC import content.global.ame.events.strangeplant.StrangePlantNPC @@ -55,6 +56,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n FREAKY_FORESTER(npc = FreakyForesterNPC(), skillIds = intArrayOf(Skills.WOODCUTTING)), PILLORY(npc = PilloryNPC(), skillIds = intArrayOf(Skills.THIEVING)), TREE_SPIRIT(npc = TreeSpiritRENPC(), skillIds = intArrayOf(Skills.WOODCUTTING)), + QUIZ_MASTER(npc = QuizMasterNPC()), RIVER_TROLL(RiverTrollRENPC(), skillIds = intArrayOf(Skills.FISHING)), ROCK_GOLEM(RockGolemRENPC(), skillIds = intArrayOf(Skills.MINING)), SHADE(ShadeRENPC(), skillIds = intArrayOf(Skills.PRAYER)), diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterBorders.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterBorders.kt new file mode 100644 index 000000000..860d4d7dc --- /dev/null +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterBorders.kt @@ -0,0 +1,37 @@ +package content.global.ame.events.quizmaster + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction +import org.rs09.consts.NPCs + +class QuizMasterBorders : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf(getRegionBorders(7754)) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12) + face(entity, Location(1952, 4768, 1)) + animate(entity,2378) + openDialogue(entity, QuizMasterDialogueFile(), NPC(NPCs.QUIZ_MASTER_2477)) + } + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + entity.interfaceManager.restoreTabs() + //closeOverlay(entity) + } + } + +} \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt new file mode 100644 index 000000000..aba73764c --- /dev/null +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt @@ -0,0 +1,132 @@ +package content.global.ame.events.quizmaster + +import core.ServerConstants +import core.api.* +import core.api.utils.WeightBasedTable +import core.api.utils.WeightedItem +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.interaction.QueueStrength +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.tools.END_DIALOGUE +import org.rs09.consts.Components +import org.rs09.consts.Items + +class QuizMasterDialogueFile : DialogueFile() { + companion object { + const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191 + const val QUIZMASTER_ATTRIBUTE_RETURN_LOC = "/save:original-loc" + const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct" + const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer" + + /* + // Golden Models: + 8828 ADAMANT_BATTLEAXE_1371 + 8829 SALMON_329 + 8830 TROUT_333 + 8831 NECKLACE + 8832 WOODEN_SHIELD_1171 + 8833 BRONZE_MED_HELM_1139 + 8834 RING + 8835 SECATEURS_5329 + 8836 BRONZE_SWORD_1277 + 8837 GARDENING_TROWEL_5325 + */ + val sets = arrayOf( + intArrayOf(8828, 8829, 8829), + intArrayOf(8831, 8837, 8835), + intArrayOf(8830, 8832, 8833), + intArrayOf(8835, 8834, 8831), + intArrayOf(8837, 8836, 8828), + ) + + fun randomQuestion(player: Player): Int { + val randomSet = intArrayOf(*sets.random()) + val answer = intArrayOf(*randomSet)[0] + randomSet.shuffle() + val correctButton = randomSet.indexOf(answer) + 2 // buttons are 3,4,5 + + player.packetDispatch.sendModelOnInterface(randomSet[0], QUIZMASTER_INTERFACE, 6, 512) + player.packetDispatch.sendModelOnInterface(randomSet[1], QUIZMASTER_INTERFACE, 7, 512) + player.packetDispatch.sendModelOnInterface(randomSet[2], QUIZMASTER_INTERFACE, 8, 512) + player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 6, 512,0,0) + player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 7, 512,0,0) + player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 8, 512,0,0) + + return correctButton + } + + // Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas. + val tableRoll = WeightBasedTable.create( + WeightedItem(Items.LAMP_6796, 1, 1, 1.0, false), + WeightedItem(Items.CABBAGE_1965, 1, 1, 1.0, false), + WeightedItem(Items.DIAMOND_1601, 1, 1, 1.0, false), + WeightedItem(Items.BUCKET_1925, 1, 1, 1.0, false), + WeightedItem(Items.FLIER_956, 1, 1, 1.0, false), + WeightedItem(Items.OLD_BOOT_685, 1, 1, 1.0, false), + WeightedItem(Items.BODY_RUNE_559, 1, 1, 1.0, false), + WeightedItem(Items.ONION_1957, 1, 1, 1.0, false), + WeightedItem(Items.MITHRIL_SCIMITAR_1329, 1, 1, 1.0, false), + WeightedItem(Items.CASKET_405, 1, 1, 1.0, false), + WeightedItem(Items.STEEL_PLATEBODY_1119, 1, 1, 1.0, false), + WeightedItem(Items.NATURE_RUNE_561, 20, 20, 1.0, false), + ) + } + + + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npc(FacialExpression.FRIENDLY,"WELCOME to the GREATEST QUIZ SHOW in the", "whole of ${ServerConstants.SERVER_NAME}:", "O D D O N E O U T").also { stage++ } + 1 -> player(FacialExpression.THINKING, "I'm sure I didn't ask to take part in a quiz show...").also { stage++ } + 2 -> npc(FacialExpression.FRIENDLY,"Please welcome our newest contestant:", "${player?.username}!", "Just pick the O D D O N E O U T.", "Four questions right, and then you win!").also { stage++ } + 3 -> { + setAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, randomQuestion(player!!)) + player!!.interfaceManager.openChatbox(QUIZMASTER_INTERFACE) + stage++ + } + 4-> { + if (buttonID == getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, 0)) { + // Correct Answer + setAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) + 1) + if (getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) >= 4) { + npc(FacialExpression.FRIENDLY,"CONGRATULATIONS!", "You are a WINNER!", "Please choose your PRIZE!") + stage = 5 + } else { + npc(FacialExpression.FRIENDLY,"Wow, you're a smart one!", "You're absolutely RIGHT!", "Okay, next question!") + stage = 3 + } + } else { + // Wrong Answer + npc(FacialExpression.FRIENDLY,"WRONG!", "That's just WRONG!", "Okay, next question!") + stage = 3 + } + } + // Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas. + 5 -> options("1000 Coins", "Random Item").also { stage++ } + 6 -> { + resetAnimator(player!!) + teleport(player!!, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + when (buttonID) { + 1 -> { + queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int -> + addItemOrDrop(player!!, Items.COINS_995, 1000) + return@queueScript stopExecuting(player!!) + } + } + 2 -> { + queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int -> + addItemOrDrop(player!!, tableRoll.roll()[0].id) + return@queueScript stopExecuting(player!!) + } + } + } + removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC) + removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT) + removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER) + stage = END_DIALOGUE + end() + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt new file mode 100644 index 000000000..d1c6f12e9 --- /dev/null +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt @@ -0,0 +1,67 @@ +package content.global.ame.events.quizmaster + +import content.global.ame.RandomEventNPC +import core.api.* +import core.api.utils.WeightBasedTable +import core.game.interaction.QueueStrength +import core.game.node.entity.npc.NPC +import core.game.system.timer.impl.AntiMacro +import core.game.world.map.Location +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.NPCs +import org.rs09.consts.Sounds + +/** + * Quiz Master NPC: + * + * https://www.youtube.com/watch?v=EFAWSiPTfcM + * https://www.youtube.com/watch?v=caWn7pE2mkE + * https://www.youtube.com/watch?v=Bc1gAov2o4w + * https://www.youtube.com/watch?v=oHU8-MUarxE + * https://www.youtube.com/watch?v=wvjYiF4v9tI + * https://www.youtube.com/watch?v=dC6rlSnXEfw + */ +class QuizMasterNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.QUIZ_MASTER_2477) { + override fun init() { + super.init() + sendChat("Hey ${player.username}! It's your lucky day!") + queueScript(player, 4, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + lock(player, 6) + sendGraphics(Graphics(1576, 0, 0), player.location) + animate(player,8939) + playAudio(player, Sounds.TELEPORT_ALL_200) + return@queueScript delayScript(player, 3) + } + 1 -> { + if (getAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, null) == null) { + setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, player.location) + } + setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) + //MazeInterface.initMaze(player) + teleport(player, Location(1952, 4764, 1)) + AntiMacro.terminateEventNpc(player) + sendGraphics(Graphics(1577, 0, 0), player.location) + animate(player,8941) + sendMessage(player, "Answer four questions correctly in a row to be teleported back where you came from.") + sendMessage(player, "You will need to relog in if you lose the quiz dialog.") // Inauthentic, but there to notify the player in case. + return@queueScript delayScript(player, 6) + } + 2 -> { + face(player, Location(1952, 4768, 1)) + animate(player,2378) + // This is not needed as when you enter the QuizMasterBorders, it should fire off the dialogue + // openDialogue(player, QuizMasterDialogueFile(), this.asNpc()) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + + } + } + + override fun talkTo(npc: NPC) { + openDialogue(player, QuizMasterDialogueFile(), this.asNpc()) + } +} \ No newline at end of file From 612ccc677678902e7f6270574c1f5a07be44cc75 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Tue, 11 Feb 2025 13:03:30 +0000 Subject: [PATCH 205/306] Implemented Maze random event --- .../main/content/global/ame/RandomEvents.kt | 2 + .../global/ame/events/maze/MazeInterface.kt | 279 ++++++++++++++++++ .../content/global/ame/events/maze/MazeNPC.kt | 58 ++++ .../game/global/action/DoorActionHandler.java | 4 +- .../main/core/net/packet/PacketProcessor.kt | 6 + 5 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 Server/src/main/content/global/ame/events/maze/MazeInterface.kt create mode 100644 Server/src/main/content/global/ame/events/maze/MazeNPC.kt diff --git a/Server/src/main/content/global/ame/RandomEvents.kt b/Server/src/main/content/global/ame/RandomEvents.kt index 9ab78c468..9addefbe4 100644 --- a/Server/src/main/content/global/ame/RandomEvents.kt +++ b/Server/src/main/content/global/ame/RandomEvents.kt @@ -8,6 +8,7 @@ import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC import content.global.ame.events.evilbob.EvilBobNPC import content.global.ame.events.evilchicken.EvilChickenNPC import content.global.ame.events.freakyforester.FreakyForesterNPC +import content.global.ame.events.maze.MazeNPC import content.global.ame.events.genie.GenieNPC import content.global.ame.events.pillory.PilloryNPC import content.global.ame.events.rickturpentine.RickTurpentineNPC @@ -45,6 +46,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985,1,1,0.1), WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1) )), + MAZE(npc = MazeNPC()), DRILL_DEMON(npc = SeargentDamienNPC()), EVIL_CHICKEN(npc = EvilChickenNPC()), STRANGE_PLANT(npc = StrangePlantNPC()), diff --git a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt new file mode 100644 index 000000000..8a317e57a --- /dev/null +++ b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt @@ -0,0 +1,279 @@ +package content.global.ame.events.maze + +import core.api.* +import core.api.utils.WeightBasedTable +import core.api.utils.WeightedItem +import core.game.event.EventHook +import core.game.event.TickEvent +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.player.Player +import core.game.node.scenery.SceneryBuilder +import core.game.system.task.Pulse +import core.game.world.GameWorld.Pulser +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.game.world.map.zone.ZoneRestriction +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.* + +class MazeInterface : InteractionListener, EventHook, MapArea { + companion object { + const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209 + const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0] + const val MAZE_ATTRIBUTE_RETURN_LOC = "/save:original-loc" + const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left" + const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened" + + val STARTING_POINTS = arrayOf( + Location(2928, 4553, 0), + Location(2917, 4553, 0), + Location(2908, 4555, 0), + Location(2891, 4589, 0), + Location(2891, 4595, 0), + Location(2891, 4595, 0), + Location(2926, 4597, 0), + Location(2931, 4597, 0), + // There's 2 more, but there isn't a door for them... + ) + + val REWARD_ITEM = intArrayOf( + Items.COINS_995, + Items.FEATHER_314, + Items.IRON_ARROW_884, + Items.CHAOS_RUNE_562, + Items.STEEL_ARROW_886, + Items.DEATH_RUNE_560, + Items.COAL_454, + Items.NATURE_RUNE_561, + Items.MITHRIL_ORE_448 + ) + + val ITEM_DIVISOR = arrayOf( + 1.0, + 2.0, + 3.0, + 9.0, + 12.0, + 18.0, + 45.0, + 162.0, + 180.0, + ) + + val CHEST_REWARDS = WeightBasedTable.create( + WeightedItem(Items.AIR_RUNE_556,15,15,1.0), + WeightedItem(Items.WATER_RUNE_555,10,10,1.0), + WeightedItem(Items.EARTH_RUNE_557,10,10,1.0), + WeightedItem(Items.FIRE_RUNE_554,10,10,1.0), + WeightedItem(Items.BRONZE_ARROW_882,20,20,1.0), + WeightedItem(Items.BRONZE_BOLTS_877,10,10,1.0), + WeightedItem(Items.IRON_ARROW_884,15,15,1.0), + WeightedItem(Items.ATTACK_POTION2_123,1,1,1.0), + WeightedItem(Items.STRENGTH_POTION2_117,1,1,1.0), + WeightedItem(Items.DEFENCE_POTION2_135,1,1,1.0), + ) + + fun initMaze(player: Player) { + setAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 300) + setVarp(player, MAZE_TIMER_VARP, (getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3),false) + openOverlay(player, MAZE_TIMER_INTERFACE) + sendMessage(player, "You need to reach the maze center, then you'll be returned to where you were.") + sendNPCDialogue(player, NPCs.MYSTERIOUS_OLD_MAN_410, "You need to reach the maze center, then you'll be returned to where you were.") + } + + fun calculateLoot(player: Player) { + val randomNumber = (0..8).random() + val totalLevel = player.getSkills().totalLevel.toDouble() + val rewardPotential = getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0).toDouble() / 300.0 + val itemDivisor = ITEM_DIVISOR[randomNumber] + val itemQuantity = (totalLevel * rewardPotential * 3.33) / itemDivisor + // sendMessage(player, "Maze reward calculation: $totalLevel * $rewardPotential * 3.33 / $itemDivisor = $itemQuantity") + if (itemQuantity.toInt() > 0) { + addItemOrDrop(player, REWARD_ITEM[randomNumber], itemQuantity.toInt()) + } + } + + /** + * Chest Location to rotation mapping. + * This is needed as it is impossible to obtain the underlying chest scenery for the rotation. + * 0: Facing North, 1: Facing East, 2: Facing South, 3: Facing West + */ + val chestLocationRotationMap = mapOf( + Location(2930, 4595, 0).toString() to 2, + Location(2924, 4572, 0).toString() to 2, + Location(2925, 4573, 0).toString() to 0, + Location(2900, 4578, 0).toString() to 2, + Location(2901, 4560, 0).toString() to 1, + Location(2890, 4599, 0).toString() to 2, + Location(2896, 4591, 0).toString() to 2, + Location(2895, 4592, 0).toString() to 1, + Location(2901, 4560, 0).toString() to 3, + Location(2918, 4590, 0).toString() to 1, + Location(2917, 4590, 0).toString() to 3, + ) + + /** + * Chest Interaction workaround + * + * The issue here is that the walls(3626) of the Maze are overlapping some(not all) chest sceneries. + * + * The types for the wallScenery: + * Type 0 - flat panel | + * Type 2 - right angle panel with rotation 0:r 1:7 2:> 3:L + * Type 3 - corner post . for angle edges of walls + */ + fun overrideScenery(wallScenery: core.game.node.scenery.Scenery, chestSceneryId: Int): core.game.node.scenery.Scenery { + if (wallScenery.id == chestSceneryId) { + replaceScenery(wallScenery, Scenery.CHEST_3636, 30) + wallScenery.isActive = true + return wallScenery // Return the chest scenery as the wallScenery isn't there. + } + + addScenery(Scenery.CHEST_3636, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10) + addScenery(wallScenery) + // replaceScenery(newChestScenery, Scenery.CHEST_3636, 3) // didn't work for an underlying scenery + // I did a world pulse since everyone will get to see the chest open. + Pulser.submit(object : Pulse(30) { + override fun pulse(): Boolean { + addScenery(Scenery.CHEST_3635, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10) + addScenery(wallScenery) + return true + } + }) + // Return the chest scenery to replace PacketProcessor so that MISMATCH will not happen. + return core.game.node.scenery.Scenery( + chestSceneryId, + wallScenery.location, + chestLocationRotationMap[wallScenery.location.toString()] ?: 0 + ) + } + } + + override fun defineListeners() { + + // This somehow doesn't trigger as the scenery.id != objId (3626 != 3635) + on(Scenery.CHEST_3635, IntType.SCENERY, "open") { player, node -> + if (getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0 && getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0) < 10) { + animate(player, 536) + // val actualScenery = RegionManager.getObject(node.location.z, node.location.x, node.location.y, 3626) + val tableRoll = CHEST_REWARDS.roll() + addItemOrBank(player, tableRoll[0].id) + when (tableRoll[0].id){ + Items.AIR_RUNE_556 -> sendItemDialogue(player, Items.AIR_RUNE_556, "You've found some air runes!") + Items.WATER_RUNE_555 -> sendItemDialogue(player, Items.WATER_RUNE_555, "You've found some water runes!") + Items.EARTH_RUNE_557 -> sendItemDialogue(player, Items.EARTH_RUNE_557, "You've found some earth runes!") + Items.FIRE_RUNE_554 -> sendItemDialogue(player, Items.FIRE_RUNE_554, "You've found some fire runes!") + Items.BRONZE_ARROW_882 -> sendItemDialogue(player, Items.BRONZE_ARROW_882, "You've found some bronze arrows!") + Items.BRONZE_BOLTS_877 -> sendItemDialogue(player, Items.BRONZE_BOLTS_877, "You've found some bronze bolts!") + Items.IRON_ARROW_884 -> sendItemDialogue(player, Items.IRON_ARROW_884, "You've found some iron arrows!") + Items.ATTACK_POTION2_123 -> sendItemDialogue(player, Items.ATTACK_POTION2_123, "You've found an attack potion!") + Items.STRENGTH_POTION2_117 -> sendItemDialogue(player, Items.STRENGTH_POTION2_117, "You've found a strength potion!") + Items.DEFENCE_POTION2_135 -> sendItemDialogue(player, Items.DEFENCE_POTION2_135, "You've found a defence potion!") + } + setAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0)) + } else { + sendMessage(player,"You find nothing of interest.") + } + return@on true + } + + on(Scenery.CHEST_3636, SCENERY, "search") { player, node -> + sendMessage(player,"You find nothing of interest.") + return@on true + } + + on(Scenery.WALL_3626, IntType.SCENERY, "open") { player, node -> + sendMessage(player, "That bit doesn't open.") // 0xBrLo9woIY + return@on true + } + + on(Scenery.WALL_3628, IntType.SCENERY, "open") { player, node -> + // Door opening workaround + // Ignore 3629(WALL_3629) and 3630(WALL_3630) in handleAutowalkDoor ignoreSecondDoor + DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery) + return@on true + } + + on(Scenery.STRANGE_SHRINE_3634, IntType.SCENERY, "touch") { player, node -> + player.unhook(this) + closeOverlay(player) + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + lock(player, 6) + sendGraphics(Graphics(86, 0, 3), player.location) + animate(player,862) + return@queueScript delayScript(player, 6) + } + 1 -> { + lock(player, 6) + sendGraphics(Graphics(1576, 0, 0), player.location) + animate(player,8939) + playAudio(player, Sounds.TELEPORT_ALL_200) + return@queueScript delayScript(player, 3) + } + 2 -> { + teleport(player, getAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + sendGraphics(Graphics(1577, 0, 0), player.location) + removeAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC) + animate(player,8941) + closeOverlay(player) + return@queueScript delayScript(player, 1) + } + 3 -> { + calculateLoot(player) + removeAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT) + removeAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + + return@on true + } + } + + override fun process(entity: Entity, event: TickEvent) { + if (entity is Player) { + if (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0) { + setAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) - 1) + } + setVarp(entity, MAZE_TIMER_VARP, (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3), false) + } + } + + override fun defineAreaBorders(): Array { + return arrayOf(getRegionBorders(11591)) + } + + override fun getRestrictions(): Array { + return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + sendMessage(entity, "Head for the center of the maze.") + entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12) + openOverlay(entity, MAZE_TIMER_INTERFACE) + } + } + + override fun areaLeave(entity: Entity, logout: Boolean) { + if (entity is Player) { + entity.interfaceManager.restoreTabs() + closeOverlay(entity) + entity.unhook(this) + } + } + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + entity.hook(Event.Tick, this) + } + } + +} \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/maze/MazeNPC.kt b/Server/src/main/content/global/ame/events/maze/MazeNPC.kt new file mode 100644 index 000000000..973f8423d --- /dev/null +++ b/Server/src/main/content/global/ame/events/maze/MazeNPC.kt @@ -0,0 +1,58 @@ +package content.global.ame.events.maze + +import content.global.ame.RandomEventNPC +import core.api.* +import core.api.utils.WeightBasedTable +import core.game.interaction.QueueStrength +import core.game.node.entity.npc.NPC +import core.game.system.timer.impl.AntiMacro +import core.game.world.map.Location +import core.game.world.map.build.DynamicRegion +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.NPCs +import org.rs09.consts.Sounds + +class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.MYSTERIOUS_OLD_MAN_410) { + + override fun init() { + super.init() + sendChat("Aha, you'll do ${player.username}!") + face(player) + queueScript(player, 4, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + lock(player, 6) + sendGraphics(Graphics(1576, 0, 0), player.location) + animate(player,8939) + playAudio(player, Sounds.TELEPORT_ALL_200) + return@queueScript delayScript(player, 3) + } + 1 -> { + if (getAttribute(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, null) == null) { + setAttribute(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, player.location) + } + MazeInterface.initMaze(player) + // Note: This event is NOT instanced: + // Sources: + // https://youtu.be/2gpzn9oNdy0 (2007) + // https://youtu.be/Tni1HURgnxg (2008) + // https://youtu.be/igdwDZOv9LU (2008) + // https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for." + // https://youtu.be/FMuKZm-Ikgs (2011) + // val region = DynamicRegion.create(11591) + teleport(player, MazeInterface.STARTING_POINTS.random()) // 10 random spots + AntiMacro.terminateEventNpc(player) + sendGraphics(Graphics(1577, 0, 0), player.location) + animate(player,8941) + removeAttribute(player, MazeInterface.MAZE_ATTRIBUTE_CHESTS_OPEN) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + override fun talkTo(npc: NPC) { + // Do nothing. + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/global/action/DoorActionHandler.java b/Server/src/main/core/game/global/action/DoorActionHandler.java index 028030824..02234e136 100644 --- a/Server/src/main/core/game/global/action/DoorActionHandler.java +++ b/Server/src/main/core/game/global/action/DoorActionHandler.java @@ -115,7 +115,9 @@ public final class DoorActionHandler { if (object.getCharge() == IN_USE_CHARGE) { return false; } - final Scenery second = (object.getId() == 3) ? null : getSecondDoor(object, entity); + // TODO: Maybe have this passed in as an optional parameter or overload handleAutowalkDoor? + boolean ignoreSecondDoor = (object.getId() == 3628 || object.getId() == 3629 || object.getId() == 3630 || object.getId() == 3631|| object.getId() == 3632); // Ignore second door for Maze Random + final Scenery second = (object.getId() == 3 || ignoreSecondDoor) ? null : getSecondDoor(object, entity); entity.lock(4); final Location loc = entity.getLocation(); if (entity instanceof Player) { diff --git a/Server/src/main/core/net/packet/PacketProcessor.kt b/Server/src/main/core/net/packet/PacketProcessor.kt index a171b9c63..d6028d648 100644 --- a/Server/src/main/core/net/packet/PacketProcessor.kt +++ b/Server/src/main/core/net/packet/PacketProcessor.kt @@ -15,6 +15,7 @@ import core.game.node.entity.player.info.Rights import core.game.node.entity.player.info.login.LoginConfiguration import core.game.node.entity.player.link.SpellBookManager import core.game.node.entity.combat.spell.MagicSpell +import content.global.ame.events.maze.MazeInterface import content.global.skill.summoning.familiar.FamiliarSpecial import core.game.node.item.GroundItemManager import core.game.node.item.Item @@ -670,6 +671,11 @@ object PacketProcessor { if (pkt.id == 6899) scenery = Scenery(6899, Location(3221, 9618)) + // Random Event Maze chests are overridden by the walls, which needs to be hacked in. + if ((scenery?.id == 3626 || scenery?.id == 3635) && (objId in 3635..3636)) { + scenery = MazeInterface.overrideScenery(scenery, objId) + } + // Family crest levers don't have varps associated with them, so their state is validated with attributes // instead, and they always appear as their down/odd variant in the server's map if (objId in 2421..2426 && objId % 2 == 0) { From e63c6f523adb817baeb5c3628523fa604e83ac36 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 11 Feb 2025 13:06:49 +0000 Subject: [PATCH 206/306] Fixed bug where ::forcegravedeath could make admins lose admin status Added ::makeadmin command to promote accounts to admin Added ::dropadmin command to demote accounts from admin Added ::setpestpoints to set Pest Control points Testing commands now take optional player name argument ::max, ::noobme, ::setlevel and ::addxp --- .../entity/combat/graves/GraveController.kt | 17 ++-- .../command/sets/DevelopmentCommandSet.kt | 89 ++++++++++++++++++- .../system/command/sets/MiscCommandSet.kt | 72 --------------- 3 files changed, 94 insertions(+), 84 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt b/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt index cfead670c..00e0e0b1b 100644 --- a/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt +++ b/Server/src/main/core/game/node/entity/combat/graves/GraveController.kt @@ -17,6 +17,7 @@ import org.rs09.consts.Items import core.ServerStore import core.game.interaction.InteractionListener import core.game.interaction.IntType +import core.game.interaction.QueueStrength import core.game.system.command.Privilege import core.game.world.GameWorld import core.game.world.map.zone.impl.WildernessZone @@ -36,18 +37,16 @@ class GraveController : PersistWorld, TickListener, InteractionListener, Command } override fun defineCommands() { - define("forcegravedeath", Privilege.ADMIN, "", "Forces a death that should produce a grave.") {player, _ -> + define("forcegravedeath", Privilege.ADMIN, "", "Forces a death that should produce a grave.") { player, _ -> player.details.rights = Rights.REGULAR_PLAYER setAttribute(player, "tutorial:complete", true) player.impactHandler.manualHit(player, player.skills.lifepoints, ImpactHandler.HitsplatType.NORMAL) - notify(player, "Grave created at ${player.getAttribute("/save:original-loc",player.location)}") - GameWorld.Pulser.submit(object : Pulse(15) { - override fun pulse(): Boolean { - player.details.rights = Rights.ADMINISTRATOR - sendMessage(player, "Rights restored") - return true - } - }) + notify(player, "Grave created at ${player.getAttribute("/save:original-loc", player.location)}") + queueScript(player, 15, QueueStrength.SOFT) { stage: Int -> + player.details.rights = Rights.ADMINISTRATOR + sendMessage(player, "Rights restored") + return@queueScript stopExecuting(player) + } } } diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index 538bbb43c..253011da6 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -34,10 +34,20 @@ import core.game.world.repository.Repository class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { val farmKitItems = arrayListOf(Items.RAKE_5341, Items.SPADE_952, Items.SEED_DIBBER_5343, Items.WATERING_CAN8_5340, Items.SECATEURS_5329, Items.GARDENING_TROWEL_5325,Items.COMPOST_6032, Items.SUPERCOMPOST_6034, Items.PLANT_CURE_6036) val runeKitItems = arrayListOf(Items.AIR_RUNE_556, Items.EARTH_RUNE_557, Items.FIRE_RUNE_554, Items.WATER_RUNE_555, Items.MIND_RUNE_558, Items.BODY_RUNE_559, Items.DEATH_RUNE_560, Items.NATURE_RUNE_561, Items.CHAOS_RUNE_562, Items.LAW_RUNE_563, Items.COSMIC_RUNE_564, Items.BLOOD_RUNE_565, Items.SOUL_RUNE_566, Items.ASTRAL_RUNE_9075) + + fun getPlayerFromArgs(player: Player, args: Array, startindex: Int = 1): Player? { + val n = args.slice(startindex until args.size).joinToString("_") + if (n == "") { //no argument given -> return self player + return player + } + val target = Repository.getPlayerByName(n) + if (target == null) { + reject(player, "Could not find a player named '$n'") + } + return target + } + override fun defineCommands() { - /** - * Gives the player a set of tools used to test farming stuff. - */ define("farmkit", Privilege.ADMIN, "", "Provides a kit of various farming equipment."){player,_ -> for(item in farmKitItems){ player.inventory.add(Item(item)) @@ -291,5 +301,78 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { player.sendMessage(" ${timer.identifier}") } } + + define("setpestpoints", Privilege.ADMIN, "::setpestpoints points player_name", "Sets your (or player_name's) Pest Control points to 'points'") { player, args -> + val target = getPlayerFromArgs(player, args, 2) ?: return@define + val points = args[1].toIntOrNull() + if (points == null) { + reject(player, "No valid 'points' argument given") + } + target.savedData.activityData.pestPoints = points!! + } + + define("makeadmin", Privilege.ADMIN, "::makeadmin player_name", "Permanently gives admin rights to player_name (or self if empty)") { player, args -> + val target = getPlayerFromArgs(player, args, 1) ?: return@define + target.details.rights = Rights.ADMINISTRATOR + sendMessage(player, "Gave admin rights to ${target.username}.") + sendMessage(target, "You've been given admin rights by ${player.username}!") + } + + define("dropadmin", Privilege.ADMIN, "::dropadmin", "Permanently drops admin rights from self") { player, _ -> + player.details.rights = Rights.REGULAR_PLAYER + sendMessage(player, "Dropped admin rights.") + } + + define("max", Privilege.ADMIN, "::max player_name", "Gives all 99s to player_name (or self if empty)") { player, args -> + val target = getPlayerFromArgs(player, args, 1) ?: return@define + var index = 0 + Skills.SKILL_NAME.forEach { + target.skills.setStaticLevel(index,99) + target.skills.setLevel(index,99) + index++ + } + target.skills.updateCombatLevel() + } + + define("noobme", Privilege.ADMIN, "::noobme player_name", "Sets player_name (or self if empty) back to default stats") { player, args -> + val target = getPlayerFromArgs(player, args, 1) ?: return@define + var index = 0 + Skills.SKILL_NAME.forEach { + val level = if (index == Skills.HITPOINTS) 10 else 1 + target.skills.setStaticLevel(index, level) + target.skills.setLevel(index, level) + index++ + } + target.skills.updateCombatLevel() + } + + define("setlevel", Privilege.ADMIN, "::setlevel SKILL NAME LEVEL PLAYER", "Sets SKILL NAME to LEVEL for PLAYER (self if omitted)."){player,args -> + if (args.size < 3) reject(player,"Usage: ::setlevel skillname level") + val skillname = args[1] + val desiredLevel: Int? = args[2].toIntOrNull() + if (desiredLevel == null) { + reject(player, "Level must be an integer.") + } + if (desiredLevel!! > 99) reject(player,"Level must be 99 or lower.") + val skill = Skills.getSkillByName(skillname) + if (skill < 0) reject(player, "Must use a valid skill name!") + val target = getPlayerFromArgs(player, args, 3) ?: return@define + target.skills.setStaticLevel(skill,desiredLevel) + target.skills.setLevel(skill,desiredLevel) + target.skills.updateCombatLevel() + } + + define("addxp", Privilege.ADMIN, "::addxp skill name | id xp", "Add xp to skill") { player, args -> + if (args.size < 3) reject(player, "Usage: ::addxp skill name | id xp player(optional)") + val target = getPlayerFromArgs(player, args, 3) ?: return@define + + val skill = args[1].toIntOrNull() ?: Skills.getSkillByName(args[1]) + if (skill < 0 || skill >= Skills.NUM_SKILLS) reject(player, "Must use valid skill name or id.") + + val xp = args[2].toDoubleOrNull() + if (xp == null || xp <= 0) reject(player, "Xp must be a positive number.") + + target.skills.addExperience(skill, xp!!) + } } } diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 0fec9ec16..473998a67 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -296,78 +296,6 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ player.dialogueInterpreter.close() } - - /** - * Max account stats - */ - define("max", Privilege.ADMIN, "", "Gives you all 99s."){player,_ -> - var index = 0 - Skills.SKILL_NAME.forEach { - player.skills.setStaticLevel(index,99) - player.skills.setLevel(index,99) - index++ - } - player.skills.updateCombatLevel() - } - - define("noobme", Privilege.ADMIN, "", "Sets you back to default stats."){ player,_ -> - var index = 0 - Skills.SKILL_NAME.forEach { - if (index == Skills.HITPOINTS) { - player.skills.setStaticLevel(index,10) - player.skills.setLevel(index,10) - index++ - } else { - player.skills.setStaticLevel(index,1) - player.skills.setLevel(index,1) - index++ - } - } - player.skills.updateCombatLevel() - } - - /** - * Set a specific skill to a specific level - */ - define("setlevel", Privilege.ADMIN, "::setlevel SKILL NAME LEVEL PLAYER", "Sets SKILL NAME to LEVEL for PLAYER (self if omitted)."){player,args -> - if(args.size < 3) reject(player,"Usage: ::setlevel skillname level") - val skillname = args[1] - val desiredLevel: Int? = args[2].toIntOrNull() - if(desiredLevel == null){ - reject(player, "Level must be an integer.") - } - if(desiredLevel!! > 99) reject(player,"Level must be 99 or lower.") - val skill = Skills.getSkillByName(skillname) - if(skill < 0) reject(player, "Must use a valid skill name!") - var target = player - if (args.size > 3) { - val n = args.slice(3 until args.size).joinToString("_") - val foundtarget = Repository.getPlayerByName(n) - if (foundtarget == null) { - reject(player,"Invalid player \"${n}\" or player not online") - } - target = foundtarget!! - } - target.skills.setStaticLevel(skill,desiredLevel) - target.skills.setLevel(skill,desiredLevel) - target.skills.updateCombatLevel() - } - - /** - * Add xp to skill - */ - define("addxp", Privilege.ADMIN, "::addxp skill name | id xp", "Add xp to skill") { player, args -> - if (args.size != 3) reject(player, "Usage: ::addxp skill name | id xp") - - val skill = args[1].toIntOrNull() ?: Skills.getSkillByName(args[1]) - if (skill < 0 || skill >= Skills.NUM_SKILLS) reject(player, "Must use valid skill name or id.") - - val xp = args[2].toDoubleOrNull() - if (xp == null || xp <= 0) reject(player, "Xp must be a positive number.") - - player.skills.addExperience(skill, xp!!) - } - define("completediaries", Privilege.ADMIN, "", "Completes all diaries."){player,_ -> player.achievementDiaryManager.diarys.forEach { for(level in it.taskCompleted.indices){ From 0f14639e9b39d4cfc30c928011421572c04a5936 Mon Sep 17 00:00:00 2001 From: MrKingFish Date: Tue, 11 Feb 2025 13:13:31 +0000 Subject: [PATCH 207/306] Added examine text for Ahad, Phingspet and Grimesquit --- Server/data/configs/npc_configs.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index d462378c8..6ca752c8c 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -76021,6 +76021,7 @@ "name": "Make-over Mage" }, { + "examine": "So what can one do with a drunken sailor?", "id": "2692", "name": "Ahab" }, @@ -76377,10 +76378,12 @@ "name": "Pox" }, { + "examine": "Cracking personality.", "id": "2946", "name": "Grimesquit" }, { + "examine": "Lovely girl, shame about the smell.", "id": "2947", "name": "Phingspet" }, From 8a4ea5d1f3d3a851e1909dde040759a45723eec3 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 11 Feb 2025 13:17:20 +0000 Subject: [PATCH 208/306] Runecrafting skillcape now only consume a charge if the teleport took place Improved navigation of the runecrafting skillcape teleport menu Runecrafting skillcape message improvement --- .../skill/skillcapeperks/SkillcapePerks.kt | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt index 5c5cb0bf3..7dbc1992b 100644 --- a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt @@ -15,6 +15,7 @@ import core.ServerStore.Companion.getBoolean import core.ServerStore.Companion.getInt import core.api.* import core.cache.def.impl.ItemDefinition +import core.tools.END_DIALOGUE import org.rs09.consts.Items import content.data.Quests @@ -48,7 +49,6 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? player.dialogueInterpreter.sendDialogue("Your cape is still on cooldown.") } else { player.dialogueInterpreter.open(509871233) - store[player.name] = used + 1 } }), SEED_ATTRACTION("cape_perks:seed_attract",{player -> @@ -223,54 +223,69 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? } override fun open(vararg args: Any?): Boolean { - options("Air","Mind","Water","Earth","More...") + altarList(0) stage = 0 return true } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - 0 -> when(buttonId){ + when(stage) { + 0 -> when(buttonId) { 1 -> sendAltar(player, Altar.AIR) 2 -> sendAltar(player, Altar.MIND) 3 -> sendAltar(player, Altar.WATER) 4 -> sendAltar(player, Altar.EARTH) - 5 -> options("Fire","Body","Cosmic","Chaos","More...").also { stage++ } + 5 -> altarList(++stage) } - 1 -> when(buttonId){ - 1 -> sendAltar(player, Altar.FIRE) - 2 -> sendAltar(player, Altar.BODY) - 3 -> sendAltar(player, Altar.COSMIC) - 4 -> sendAltar(player, Altar.CHAOS) - 5 -> options("Astral","Nature","Law","Death","More...").also { stage++ } + 1 -> when(buttonId) { + 1 -> altarList(--stage) + 2 -> sendAltar(player, Altar.FIRE) + 3 -> sendAltar(player, Altar.BODY) + 4 -> sendAltar(player, Altar.COSMIC) + 5 -> altarList(++stage) } - 2 -> when(buttonId){ - 1 -> sendAltar(player, Altar.ASTRAL) - 2 -> sendAltar(player, Altar.NATURE) - 3 -> sendAltar(player, Altar.LAW) - 4 -> sendAltar(player, Altar.DEATH) - 5 -> options("Blood","Nevermind").also { stage++ } + 2 -> when(buttonId) { + 1 -> altarList(--stage) + 2 -> sendAltar(player, Altar.CHAOS) + 3 -> sendAltar(player, Altar.ASTRAL) + 4 -> sendAltar(player, Altar.NATURE) + 5 -> altarList(++stage) } - 3 -> when(buttonId){ - 1 -> sendAltar(player, Altar.BLOOD) - 2 -> end() + 3 -> when(buttonId) { + 1 -> altarList(--stage) + 2 -> sendAltar(player, Altar.LAW) + 3 -> sendAltar(player, Altar.DEATH) + 4 -> sendAltar(player, Altar.BLOOD) + 5 -> altarList(0).also { stage = 0 } } } return true } - fun sendAltar(player: Player,altar: Altar){ + fun altarList(stage: Int) { + when (stage) { + 0 -> options("Air", "Mind", "Water", "Earth", "More...") + 1 -> options("Back...", "Fire", "Body", "Cosmic", "More...") + 2 -> options("Back...", "Chaos", "Astral", "Nature", "More...") + 3 -> options("Back...", "Law", "Death", "Blood", "More...") + } + } + + fun sendAltar(player: Player,altar: Altar) { end() if (altar == Altar.DEATH && !hasRequirement(player, Quests.MOURNINGS_END_PART_II)) return if (altar == Altar.ASTRAL && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) return if (altar == Altar.BLOOD && !hasRequirement(player, Quests.LEGACY_OF_SEERGAZE)) return if (altar == Altar.LAW && !ItemDefinition.canEnterEntrana(player)) { - sendItemDialogue(player, Items.SARADOMIN_SYMBOL_8055, "No weapons or armour are permitted on holy Entrana.") + sendMessage(player, "The power of Saradomin prevents you from taking armour or weaponry to Entrana."); return } var endLoc = if (altar == Altar.ASTRAL) Location.create(2151, 3864, 0) else altar.ruin.end + val store = ServerStore.getArchive("daily-abyss-warp") + val used = store.getInt(player.name,0) + store[player.name] = used + 1 player.teleporter.send(endLoc, TeleportManager.TeleportType.TELE_OTHER) player.incrementAttribute("/save:cape_perks:abyssal_warp",-1) } From 5540febf6e4d8dfe92a39dcf89d3b9a61c2d573d Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 11 Feb 2025 10:23:06 -0700 Subject: [PATCH 209/306] Reverting sliding scale exp multiplier Reverting manually instead of doing a git revert because this version of gitea has an error when attempting reverts. I still like how it reduced the early game boost, however it has some disadvantages. It's impossible to calculate the needed number of actions for a certain level, quest and minigame rewards get more valuable the longer you put them off, and some skills have no early game content and are a bit of a slog. Setting it back to a static multiplier. --- Server/src/main/core/game/node/entity/skill/Skills.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index fc3ed9191..482d2e12f 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -290,12 +290,7 @@ public final class Skills { private double getExperienceMod(int slot, double experience, boolean playerMod, boolean multiplyer) { //Keywords for people ctrl + Fing the project //xprate xp rate xp multiplier skilling rate - - //Snowscape Custom: experience multiplier starts at 1x and scales to the selected multiplier as level incrceases - double perLevel = (experienceMultiplier-1)/100; - double finalMult = staticLevels[slot]*perLevel+1; - return finalMult; - //return experienceMultiplier; + return experienceMultiplier; /*if (!(entity instanceof Player)) { return 1.0; From 389c5858d04a57cc2cc2147d4c0c7543b03d9645 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 11 Feb 2025 10:23:06 -0700 Subject: [PATCH 210/306] Reverting sliding scale exp multiplier Reverting manually instead of doing a git revert because this version of gitea has an error when attempting reverts. I still like how it reduced the early game boost, however it has some disadvantages. It's impossible to calculate the needed number of actions for a certain level, quest and minigame rewards get more valuable the longer you put them off, and some skills have no early game content and are a bit of a slog. Setting it back to a static multiplier. --- Server/src/main/core/game/node/entity/skill/Skills.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index fc3ed9191..482d2e12f 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -290,12 +290,7 @@ public final class Skills { private double getExperienceMod(int slot, double experience, boolean playerMod, boolean multiplyer) { //Keywords for people ctrl + Fing the project //xprate xp rate xp multiplier skilling rate - - //Snowscape Custom: experience multiplier starts at 1x and scales to the selected multiplier as level incrceases - double perLevel = (experienceMultiplier-1)/100; - double finalMult = staticLevels[slot]*perLevel+1; - return finalMult; - //return experienceMultiplier; + return experienceMultiplier; /*if (!(entity instanceof Player)) { return 1.0; From 84951244f9b9ed20f4fb31f98c4a119cb59756cc Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 11 Feb 2025 11:12:39 -0700 Subject: [PATCH 211/306] Farming leprechauns now give free buckets There is no way to increase the limit past 31, but buckets are so cheap they are just an inconvenience. So now you can deposit and withraw any number of buckets, regardless of what is stored. --- .../content/global/skill/farming/ToolLeprechaunInterface.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt b/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt index 29e0d719d..75fbe8f07 100644 --- a/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt +++ b/Server/src/main/content/global/skill/farming/ToolLeprechaunInterface.kt @@ -135,7 +135,7 @@ class ToolLeprechaunInterface : InterfaceListener { player ?: return val hasAmount = amountInInventory(player, item) var finalAmount = amount - val spaceLeft = (if (item == Items.BUCKET_1925) 31 else 255) - quantityCheckMethod.invoke(player) + val spaceLeft = (if (item == Items.BUCKET_1925) 255 else 255) - quantityCheckMethod.invoke(player) if (hasAmount == 0) { val itemName = if (item == Items.BUCKET_1925) "buckets" else getItemName(item).lowercase() @@ -183,7 +183,7 @@ class ToolLeprechaunInterface : InterfaceListener { private fun doStackedWithdrawal(player: Player?, item: Int, amount: Int, updateQuantityMethod: (Player?, Int) -> Unit, quantityCheckMethod: (Player?) -> Int) { player ?: return - val hasAmount = quantityCheckMethod.invoke(player) + val hasAmount = if (item == Items.BUCKET_1925) 31 else quantityCheckMethod.invoke(player) var finalAmount = amount if (hasAmount == 0) { From 212ce5758013d587c2fe397c3f6f35b5cd9fed72 Mon Sep 17 00:00:00 2001 From: GregF Date: Wed, 12 Feb 2025 11:35:17 +0000 Subject: [PATCH 212/306] Fixed barbarian fishing xp rate manipulation --- .../skill/gather/fishing/barbfishing/BarbFishingPulse.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/content/global/skill/gather/fishing/barbfishing/BarbFishingPulse.kt b/Server/src/main/content/global/skill/gather/fishing/barbfishing/BarbFishingPulse.kt index 2a66a2f1f..a44387209 100644 --- a/Server/src/main/content/global/skill/gather/fishing/barbfishing/BarbFishingPulse.kt +++ b/Server/src/main/content/global/skill/gather/fishing/barbfishing/BarbFishingPulse.kt @@ -48,6 +48,10 @@ class BarbFishingPulse(player: Player) : SkillPulse(player,NPC(1176)) { } override fun reward(): Boolean { + if (delay == 1){ + super.setDelay(5) + return false + } val stragiXP = arrayOf(5,6,7) val fishXP = arrayOf(50,70,80) val reward = getRandomFish() From 62a7dd432495a1b49a28ecc4938276c9a310533e Mon Sep 17 00:00:00 2001 From: sirdabalot Date: Wed, 12 Feb 2025 12:17:02 +0000 Subject: [PATCH 213/306] Ported kill stats and rare item drop storage to sqlite from json This fixes lengthy and memory intensive server shutdowns Existing global_kill_stats.json will be imported on first run --- Server/.gitignore | 1 + Server/src/main/core/ServerConstants.backup | 217 --------------- Server/src/main/core/api/ContentAPI.kt | 4 +- .../main/core/api/utils/GlobalKillCounter.kt | 120 --------- .../main/core/api/utils/PlayerStatsCounter.kt | 253 ++++++++++++++++++ .../main/core/game/node/entity/npc/NPC.java | 5 +- .../system/command/sets/StatsCommandSet.kt | 92 +++---- .../test/kotlin/PlayerStatsCounterTests.kt | 111 ++++++++ 8 files changed, 415 insertions(+), 388 deletions(-) delete mode 100644 Server/src/main/core/ServerConstants.backup delete mode 100644 Server/src/main/core/api/utils/GlobalKillCounter.kt create mode 100644 Server/src/main/core/api/utils/PlayerStatsCounter.kt create mode 100644 Server/src/test/kotlin/PlayerStatsCounterTests.kt diff --git a/Server/.gitignore b/Server/.gitignore index f22e9f978..a9a29cad7 100644 --- a/Server/.gitignore +++ b/Server/.gitignore @@ -2,6 +2,7 @@ bin/** out/** data/logs/** data/profile/** +data/playerstats/** .idea/** /bin .DS_Store** diff --git a/Server/src/main/core/ServerConstants.backup b/Server/src/main/core/ServerConstants.backup deleted file mode 100644 index 3c4d50610..000000000 --- a/Server/src/main/core/ServerConstants.backup +++ /dev/null @@ -1,217 +0,0 @@ -package core - -import core.game.system.SystemShutdownHook -import core.game.system.mysql.SQLManager -import core.game.world.map.Location -import core.tools.mysql.Database -import core.tools.secondsToTicks -import org.json.simple.JSONObject -import java.io.File -import java.math.BigInteger - -/** - * A class holding various variables for the server. - * @author Ceikry - */ -class ServerConstants { - companion object { - @JvmField - var SHUTDOWN_HOOK: Thread = Thread(SystemShutdownHook()) - - @JvmField - var DATA_PATH: String? = null - - //path to the cache - @JvmField - var CACHE_PATH: String? = null - - //path for the server store (obsolete, but kept for the sake of system sanity.) - @JvmField - var STORE_PATH: String? = null - - //path for player saves - @JvmField - var PLAYER_SAVE_PATH: String? = null - - @JvmField - var PLAYER_ATTRIBUTE_PATH = "ish"; - - //path to the various config files, such as npc_spawns.json - var CONFIG_PATH: String? = null - - @JvmField - var GRAND_EXCHANGE_DATA_PATH: String? = null - - @JvmField - var RDT_DATA_PATH: String? = null - - @JvmField - var OBJECT_PARSER_PATH: String? = null - - @JvmField - var SCRIPTS_PATH: String? = null - - @JvmField - var DIALOGUE_SCRIPTS_PATH: String? = null - - @JvmField - var LOGS_PATH: String? = null - - @JvmField - var BOT_DATA_PATH: String? = null - - //the max number of players. - @JvmField - var MAX_PLAYERS = 0 - - //the max number of NPCs - @JvmField - var MAX_NPCS = 0 - - //the location where new players are placed on login. - @JvmField - var START_LOCATION: Location? = null - - //Location for all home teleports/respawn location - @JvmField - var HOME_LOCATION: Location? = null - - //the name for the database - @JvmField - var DATABASE_NAME: String? = null - - //username for the database - @JvmField - var DATABASE_USER: String? = null - - //password for the database - @JvmField - var DATABASE_PASS: String? = null - - //address for the database - @JvmField - var DATABASE_ADDRESS: String? = null - - @JvmField - var DATABASE_PORT: String? = null - - @JvmField - var WRITE_LOGS: Boolean = false - - @JvmField - var BANK_SIZE: Int = 496 - - @JvmField - var GE_AUTOSAVE_FREQUENCY = secondsToTicks(3600) //1 hour - - @JvmField - var GE_AUTOSTOCK_ENABLED = false - - //location names for the ::to command. - val TELEPORT_DESTINATIONS = arrayOf( - arrayOf(Location.create(2974, 4383, 2), "corp", "corporal", "corporeal"), - arrayOf(Location.create(2659, 2649, 0), "pc", "pest control", "pest"), - arrayOf(Location.create(3293, 3184, 0), "al kharid", "alkharid", "kharid"), - arrayOf(Location.create(3222, 3217, 0), "lumbridge", "lumby"), - arrayOf(Location.create(3110, 3168, 0), "wizard tower", "wizards tower", "tower", "wizards"), - arrayOf(Location.create(3083, 3249, 0), "draynor", "draynor village"), - arrayOf(Location.create(3019, 3244, 0), "port sarim", "sarim"), - arrayOf(Location.create(2956, 3209, 0), "rimmington"), - arrayOf(Location.create(2965, 3380, 0), "fally", "falador"), - arrayOf(Location.create(2895, 3436, 0), "taverley"), - arrayOf(Location.create(3080, 3423, 0), "barbarian village", "barb"), - arrayOf(Location.create(3213, 3428, 0), "varrock"), - arrayOf(Location.create(3164, 3485, 0), "grand exchange", "ge"), - arrayOf(Location.create(2917, 3175, 0), "karamja"), - arrayOf(Location.create(2450, 5165, 0), "tzhaar"), - arrayOf(Location.create(2795, 3177, 0), "brimhaven"), - arrayOf(Location.create(2849, 2961, 0), "shilo village", "shilo"), - arrayOf(Location.create(2605, 3093, 0), "yanille"), - arrayOf(Location.create(2663, 3305, 0), "ardougne", "ardy"), - arrayOf(Location.create(2450, 3422, 0), "gnome stronghold", "gnome"), - arrayOf(Location.create(2730, 3485, 0), "camelot", "cammy", "seers"), - arrayOf(Location.create(2805, 3435, 0), "catherby"), - arrayOf(Location.create(2659, 3657, 0), "rellekka"), - arrayOf(Location.create(2890, 3676, 0), "trollheim"), - arrayOf(Location.create(2914, 3746, 0), "godwars", "gwd", "god wars"), - arrayOf(Location.create(3180, 3684, 0), "bounty hunter", "bh"), - arrayOf(Location.create(3272, 3687, 0), "clan wars", "clw"), - arrayOf(Location.create(3090, 3957, 0), "mage arena", "mage", "magearena", "arena"), - arrayOf(Location.create(3069, 10257, 0), "king black dragon", "kbd"), - arrayOf(Location.create(3359, 3416, 0), "digsite"), - arrayOf(Location.create(3488, 3489, 0), "canifis"), - arrayOf(Location.create(3428, 3526, 0), "slayer tower", "slayer"), - arrayOf(Location.create(3502, 9483, 2), "kalphite queen", "kq", "kalphite hive", "kalphite"), - arrayOf(Location.create(3233, 2913, 0), "pyramid"), - arrayOf(Location.create(3419, 2917, 0), "nardah"), - arrayOf(Location.create(3482, 3090, 0), "uzer"), - arrayOf(Location.create(3358, 2970, 0), "pollnivneach", "poln"), - arrayOf(Location.create(3305, 2788, 0), "sophanem"), - arrayOf(Location.create(2898, 3544, 0), "burthorpe", "burthorp"), - arrayOf(Location.create(3088, 3491, 0), "edge", "edgeville"), - arrayOf(Location.create(3169, 3034, 0), "bedabin"), - arrayOf(Location.create(3565, 3289, 0), "barrows"), - arrayOf(Location.create(3016, 3513, 0), "bkf", "black knights fortress"), - arrayOf(Location.create(3052, 3481, 0), "monastery") - ) - - @JvmField - var DATABASE: Database? = null - - //if SQL is enabled - @JvmField - var MYSQL = true - - //the server name - @JvmField - var SERVER_NAME: String = "" - - //The RSA_KEY for the server. - @JvmField - var EXPONENT = BigInteger("52317200263721308660411803146360972546561037484450290559823448967617618536819222494429186211525706853703641369936136465589036631055945454547936148730495933263344792588795811788941129493188907621550836988152620502378278134421731002382361670176785306598134280732756356458964850508114958769985438054979422820241") - - //The MODULUS for the server. - @JvmField - var MODULUS = BigInteger("96982303379631821170939875058071478695026608406924780574168393250855797534862289546229721580153879336741968220328805101128831071152160922518190059946555203865621183480223212969502122536662721687753974815205744569357388338433981424032996046420057284324856368815997832596174397728134370577184183004453899764051") - - /** - * Parses a JSONObject and retrieves the values for all settings in this file. - * @author Ceikry - * @param data : The JSONObject to parse. - */ - fun parse(data: JSONObject) { - MAX_PLAYERS = data["max_players"].toString().toInt() - MAX_NPCS = data["max_npcs"].toString().toInt() - - START_LOCATION = JSONUtils.parseLocation(data["new_player_location"].toString()) - HOME_LOCATION = JSONUtils.parseLocation(data["home_location"].toString()) - - DATA_PATH = JSONUtils.parsePath(data["data_path"].toString()) - CACHE_PATH = JSONUtils.parsePath(data["cache_path"].toString()) - STORE_PATH = JSONUtils.parsePath(data["store_path"].toString()) - PLAYER_SAVE_PATH = JSONUtils.parsePath(data["save_path"].toString()) - CONFIG_PATH = JSONUtils.parsePath(data["configs_path"].toString()) - PLAYER_ATTRIBUTE_PATH = PLAYER_SAVE_PATH + "attributes" + File.separator - GRAND_EXCHANGE_DATA_PATH = JSONUtils.parsePath(data["grand_exchange_data_path"].toString()) - BOT_DATA_PATH = JSONUtils.parsePath(data["bot_data_path"].toString()) - RDT_DATA_PATH = JSONUtils.parsePath(data["rare_drop_table_path"].toString()) - OBJECT_PARSER_PATH = JSONUtils.parsePath(data["object_parser_path"].toString()) - SCRIPTS_PATH = JSONUtils.parsePath(data["scripts_path"].toString()) - DIALOGUE_SCRIPTS_PATH = JSONUtils.parsePath(data["dialogue_scripts_path"].toString()) - if(data.containsKey("logs_path")){ - LOGS_PATH = data["logs_path"].toString() - } - if(data.containsKey("writeLogs")){ - WRITE_LOGS = data["writeLogs"] as Boolean - } - - DATABASE_NAME = data["database_name"].toString() - DATABASE_USER = data["database_username"].toString() - DATABASE_PASS = data["database_password"].toString() - DATABASE_ADDRESS = data["database_address"].toString() - DATABASE_PORT = data["database_port"].toString() - - DATABASE = Database(DATABASE_ADDRESS, DATABASE_NAME, DATABASE_USER, DATABASE_PASS) - } - } -} \ No newline at end of file diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index f10fff1c3..091a196df 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -10,7 +10,7 @@ import content.global.skill.slayer.SlayerManager import content.global.skill.slayer.Tasks import content.global.skill.summoning.familiar.BurdenBeast import core.ServerConstants -import core.api.utils.GlobalKillCounter +import core.api.utils.PlayerStatsCounter import core.api.utils.Vector import core.cache.def.impl.AnimationDefinition import core.cache.def.impl.ItemDefinition @@ -2075,7 +2075,7 @@ fun sendItemSelect (player: Player, vararg options: String, keepAlive: Boolean = fun announceIfRare(player: Player, item: Item) { if (item.definition.getConfiguration(ItemConfigParser.RARE_ITEM, false)) { sendNews("${player.username} has just received: ${item.amount} x ${item.name}.") - GlobalKillCounter.incrementRareDrop(player, item) + PlayerStatsCounter.incrementRareDrop(player, item) } } diff --git a/Server/src/main/core/api/utils/GlobalKillCounter.kt b/Server/src/main/core/api/utils/GlobalKillCounter.kt deleted file mode 100644 index eaecfe982..000000000 --- a/Server/src/main/core/api/utils/GlobalKillCounter.kt +++ /dev/null @@ -1,120 +0,0 @@ -package core.api.utils - -import core.api.ShutdownListener -import core.api.StartupListener -import core.game.node.entity.player.Player -import core.tools.SystemLogger -import java.io.File -import java.io.FileReader -import java.io.FileWriter -import org.json.simple.JSONObject -import org.json.simple.parser.JSONParser -import core.ServerConstants -import core.api.log -import core.game.node.item.Item -import core.tools.Log -import core.tools.SystemLogger.logShutdown -import core.tools.SystemLogger.logStartup - -class GlobalKillCounter : StartupListener, ShutdownListener { - override fun startup() { - logStartup("Parsing Global Kill Counts") - val file = File(ServerConstants.DATA_PATH + File.separator + "global_kill_stats.json") - if(!file.exists()) { - return - } - - val reader = FileReader(file) - val parser = JSONParser() - try { - val data = parser.parse(reader) as JSONObject - val tmp_kills = data.get("kills") - populate(kills, tmp_kills) - val tmp_rare_drops = data.get("rare_drops") - populate(rare_drops, tmp_rare_drops) - } catch (e: Exception){ - log(this::class.java, Log.ERR, "Failed parsing ${file.name} - stack trace below.") - e.printStackTrace() - } - } - - override fun shutdown() { - logShutdown("Saving Global Kill Counts") - val data = JSONObject() - data.put("kills", saveField(kills)) - data.put("rare_drops", saveField(rare_drops)) - val file = File(ServerConstants.DATA_PATH + File.separator + "global_kill_stats.json") - FileWriter(file).use { it.write(data.toJSONString()); it.flush(); it.close() } - } - - companion object { - val kills: HashMap> = HashMap() - val rare_drops: HashMap> = HashMap() - - @JvmStatic - fun populate(field: HashMap>, obj: Any?) { - if(obj != null && obj is JSONObject) { - for((player, tmp_kc) in obj.asIterable()) { - if(player is String) { - val kc: HashMap = HashMap() - for((npc_id, count) in (tmp_kc as JSONObject).asIterable()) { - kc.put(java.lang.Long.parseLong(npc_id as String), count as Long) - } - field.put(player, kc) - } - } - } - } - - @JvmStatic - fun saveField(field: HashMap>): JSONObject { - val tmp_kills = JSONObject() - for((player, kc) in field.asIterable()) { - val tmp_kc = JSONObject() - for((id, count) in kc.asIterable()) { - tmp_kc.put(id, count) - } - tmp_kills.put(player, tmp_kc) - } - return tmp_kills - } - - @JvmStatic - fun save() { - - } - - @JvmStatic - fun incrementKills(player: Player, npc_id: Int) { - val player_kills = kills.getOrPut(player.username, { HashMap() }) - val old_amount = player_kills.getOrElse(npc_id.toLong(), { 0 }) - player_kills.put(npc_id.toLong(), 1 + old_amount) - } - - @JvmStatic - fun incrementRareDrop(player: Player, item: Item) { - val player_drops = rare_drops.getOrPut(player.username, { HashMap() }) - val old_amount = player_drops.getOrElse(item.id.toLong(), { 0 }) - player_drops.put(item.id.toLong(), item.amount + old_amount) - } - - @JvmStatic - fun getKills(player: Player, npc_id: Int): Long { - return kills.getOrElse(player.username, { HashMap() }).getOrElse(npc_id.toLong(), { 0 }) - } - - @JvmStatic - fun getKills(player: Player, npc_ids: IntArray): Long { - var sum: Long = 0 - for(npc_id in npc_ids) { - sum += getKills(player, npc_id) - } - return sum - } - - @JvmStatic - fun getRareDrops(player: Player, item_id: Int): Long { - return rare_drops.getOrElse(player.username, { HashMap() }).getOrElse(item_id.toLong(), { 0 }) - } - } -} diff --git a/Server/src/main/core/api/utils/PlayerStatsCounter.kt b/Server/src/main/core/api/utils/PlayerStatsCounter.kt new file mode 100644 index 000000000..15808360b --- /dev/null +++ b/Server/src/main/core/api/utils/PlayerStatsCounter.kt @@ -0,0 +1,253 @@ +package core.api.utils + +import core.api.StartupListener +import core.game.node.entity.player.Player +import java.io.File +import java.io.FileReader +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import core.ServerConstants +import core.api.log +import core.game.node.item.Item +import core.game.world.GameWorld +import core.integrations.sqlite.SQLiteProvider +import core.tools.Log +import core.tools.SystemLogger.logStartup +import kotlin.io.path.Path + +class PlayerStatsCounter( + private val dbPath: String = Path(ServerConstants.DATA_PATH ?: "", "playerstats", "player_stats.db").toString() +) : StartupListener { + + override fun startup() { + logStartup("Loading Player Stats") + + db = SQLiteProvider(dbPath, expectedTables) + db.initTables() + + if (!tableHasData()) { // TODO: Remove check, porter and raw inserts once SQLite tracking is proven and the live server has been updated + portLegacyKillCounterJsonToSQLite() + } + } + + companion object { + lateinit var db: SQLiteProvider + + private fun resolveUIDFromPlayerUsername(playerUsername: String): Int { + return GameWorld.accountStorage.getAccountInfo(playerUsername).uid + } + + private fun portLegacyKillCounterJsonToSQLite() { + val file = File(Path(ServerConstants.DATA_PATH ?: "", "global_kill_stats.json").toString()) + if (!file.exists()) { + return + } + + val reader = FileReader(file) + val parser = JSONParser() + try { + val data = parser.parse(reader) as JSONObject + val json_kills = data.get("kills") + if (json_kills != null && json_kills is JSONObject) { + var progress = 1 + val totalPlayers = json_kills.size + for ((player, killStats) in json_kills.asIterable()) { + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Porting kill counters for player $progress/$totalPlayers" + ) + if (player is String) { + val playerUid = resolveUIDFromPlayerUsername(player) + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Player $player ($playerUid)" + ) + for ((npc_id, count) in (killStats as JSONObject).asIterable()) { + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Inserting kill for $player ($playerUid, $npc_id, $count)" + ) + incrementKills( + playerUid, + (npc_id as String).toInt(), + count as Long + ) + } + } + progress++ + } + } + val json_rare_drops = data.get("rare_drops") + if (json_rare_drops != null && json_rare_drops is JSONObject) { + var progress = 1 + val totalPlayers = json_rare_drops.size + for ((player, rareDrops) in json_rare_drops.asIterable()) { + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Porting rare drops for player $progress/$totalPlayers" + ) + if (player is String) { + val playerUid = resolveUIDFromPlayerUsername(player) + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Player $player ($playerUid)" + ) + for ((item_id, count) in (rareDrops as JSONObject).asIterable()) { + log( + PlayerStatsCounter::class.java, + Log.INFO, + "Inserting rare drop for $player ($playerUid, $item_id, $count)" + ) + incrementRareDrop( + playerUid, + (item_id as String).toInt(), + count as Long + ) + } + } + progress++ + } + } + } catch (e: Exception) { + log(this::class.java, Log.ERR, "Failed parsing ${file.name} - stack trace below.") + e.printStackTrace() + } + } + + private val killsTableDefinition = """ + CREATE TABLE kills( + player_uid INTEGER, + entity_id INTEGER, + kills INTEGER, + PRIMARY KEY(player_uid, entity_id)) + """.trimIndent() + + private val rareDropsTableDefinition = """ + CREATE TABLE rare_drops( + player_uid INTEGER, + item_id INTEGER, + amount INTEGER, + PRIMARY KEY (player_uid, item_id)) + """.trimIndent() + + private val getKillsRowCountSql = """ + SELECT COUNT(1) FROM kills; + """.trimIndent() + + private val insertOrIncrementKillSql = """ + INSERT INTO kills (player_uid, entity_id, kills) + VALUES (?, ?, ?) + ON CONFLICT(player_uid, entity_id) DO UPDATE SET kills = kills + ?; + """.trimIndent() + + private val insertOrIncrementRareDropSql = """ + INSERT INTO rare_drops (player_uid, item_id, amount) + VALUES (?, ?, ?) + ON CONFLICT(player_uid, item_id) DO UPDATE SET amount = amount + ?; + """.trimIndent() + + private val getRareDropsSql = """ + SELECT amount FROM rare_drops WHERE player_uid=? AND item_id=? + """.trimIndent() + + private fun createGetKillsSql(countOfEntitiesToSearchFor: Int): String { + if (countOfEntitiesToSearchFor < 1) { + throw Exception("Should be at least 1") + } + val entitySearchParameterMarkers = "?" + ",?".repeat(countOfEntitiesToSearchFor - 1) + return """ + SELECT SUM(kills) FROM kills WHERE player_uid=? AND entity_id IN ($entitySearchParameterMarkers) + """.trimIndent() + } + + private val expectedTables = hashMapOf( + "kills" to killsTableDefinition, + "rare_drops" to rareDropsTableDefinition, + ) + + private fun tableHasData(): Boolean { + var hasData = false + db.run { conn -> + val statement = conn.prepareStatement(getKillsRowCountSql) + val result = statement.executeQuery() + if (result.next()) { + val rowCount = result.getInt(1) + hasData = rowCount > 0 + } + } + return hasData + } + + @JvmStatic + private fun incrementKills(playerUid: Int, npcId: Int, kills: Long) { + db.run { conn -> + val statement = conn.prepareStatement(insertOrIncrementKillSql) + statement.setInt(1, playerUid) + statement.setInt(2, npcId) + statement.setLong(3, kills) + statement.setLong(4, kills) + statement.execute() + } + } + + @JvmStatic + fun incrementKills(player: Player, npcId: Int) { + incrementKills(player.details.uid, npcId, 1) + } + + @JvmStatic + private fun incrementRareDrop(playerUid: Int, itemId: Int, amount: Long) { + db.run { conn -> + val statement = conn.prepareStatement(insertOrIncrementRareDropSql) + statement.setInt(1, playerUid) + statement.setInt(2, itemId) + statement.setLong(3, amount) + statement.setLong(4, amount) + statement.execute() + } + } + + @JvmStatic + fun incrementRareDrop(player: Player, item: Item) { + incrementRareDrop(player.details.uid, item.id, item.amount.toLong()) + } + + @JvmStatic + fun getKills(player: Player, npcIds: IntArray): Long { + var kills: Long = 0 + db.run { conn -> + val statement = conn.prepareStatement(createGetKillsSql(npcIds.size)) + statement.setInt(1, player.details.uid) + for (npcIdParamIndex in npcIds.indices) { + // +2 because the statement parameterIndexes start at 1 and the first param is the player uid + statement.setInt(npcIdParamIndex + 2, npcIds[npcIdParamIndex]) + } + val result = statement.executeQuery() + if (result.next()) { + kills = result.getLong(1) + } + } + return kills + } + + @JvmStatic + fun getRareDrops(player: Player, itemId: Int): Long { + var rareDropsForItem: Long = 0 + db.run { conn -> + val statement = conn.prepareStatement(getRareDropsSql) + statement.setInt(1, player.details.uid) + statement.setInt(2, itemId) + val result = statement.executeQuery() + if (result.next()) { + rareDropsForItem = result.getLong(1) + } + } + return rareDropsForItem + } + } +} diff --git a/Server/src/main/core/game/node/entity/npc/NPC.java b/Server/src/main/core/game/node/entity/npc/NPC.java index 38691b7c9..b1d4aba99 100644 --- a/Server/src/main/core/game/node/entity/npc/NPC.java +++ b/Server/src/main/core/game/node/entity/npc/NPC.java @@ -8,7 +8,6 @@ import core.game.interaction.MovementPulse; import core.game.node.entity.Entity; import core.game.node.entity.combat.BattleState; import core.game.node.entity.combat.spell.CombatSpell; -import core.game.node.entity.combat.CombatPulse; import core.game.node.entity.combat.CombatStyle; import core.game.node.entity.combat.spell.DefaultCombatSpell; import core.game.node.entity.combat.equipment.WeaponInterface; @@ -29,7 +28,7 @@ import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.game.world.update.flag.*; import core.tools.RandomFunction; -import core.api.utils.GlobalKillCounter; +import core.api.utils.PlayerStatsCounter; import core.api.utils.Vector; import core.game.shops.Shops; import core.game.node.entity.combat.CombatSwingHandler; @@ -573,7 +572,7 @@ public class NPC extends Entity { Player p = !(killer instanceof Player) ? null : (Player) killer; if (p != null) { p.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_ENEMIES_KILLED); - GlobalKillCounter.incrementKills(p, originalId); + PlayerStatsCounter.incrementKills(p, originalId); } handleDrops(p, killer); if (!isRespawn()) diff --git a/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt b/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt index 33ff9a4bc..f3899a7a1 100644 --- a/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt @@ -11,7 +11,7 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items import org.rs09.consts.NPCs -import core.api.utils.GlobalKillCounter +import core.api.utils.PlayerStatsCounter import core.game.system.command.Privilege import core.game.world.repository.Repository import java.util.* @@ -89,69 +89,69 @@ class StatsCommandSet : CommandSet(Privilege.STANDARD) { } 1 -> { when(i) { - 97 -> sendLine(player, "Turoths: ${GlobalKillCounter.getKills(queryPlayer, TUROTH_IDS)}", i) - 68 -> sendLine(player, "Kurasks: ${GlobalKillCounter.getKills(queryPlayer, KURASK_IDS)}", i) - 69 -> sendLine(player, "Leaf-bladed swords: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.LEAF_BLADED_SWORD_13290)}", i) + 97 -> sendLine(player, "Turoths: ${PlayerStatsCounter.getKills(queryPlayer, TUROTH_IDS)}", i) + 68 -> sendLine(player, "Kurasks: ${PlayerStatsCounter.getKills(queryPlayer, KURASK_IDS)}", i) + 69 -> sendLine(player, "Leaf-bladed swords: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.LEAF_BLADED_SWORD_13290)}", i) 70 -> sendLine(player, SPACER,i) - 71 -> sendLine(player, "Gargoyles: ${GlobalKillCounter.getKills(queryPlayer, GARGOYLE_IDS)}", i) - 72 -> sendLine(player, "Granite mauls: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.GRANITE_MAUL_4153)}", i) + 71 -> sendLine(player, "Gargoyles: ${PlayerStatsCounter.getKills(queryPlayer, GARGOYLE_IDS)}", i) + 72 -> sendLine(player, "Granite mauls: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.GRANITE_MAUL_4153)}", i) 73 -> sendLine(player, SPACER,i) - 74 -> sendLine(player, "Spiritual mages: ${GlobalKillCounter.getKills(queryPlayer, SPIRITUAL_MAGE_IDS)}", i) - 75 -> sendLine(player, "Dragon boots: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DRAGON_BOOTS_11732)}", i) + 74 -> sendLine(player, "Spiritual mages: ${PlayerStatsCounter.getKills(queryPlayer, SPIRITUAL_MAGE_IDS)}", i) + 75 -> sendLine(player, "Dragon boots: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DRAGON_BOOTS_11732)}", i) 76 -> sendLine(player, SPACER,i) - 77 -> sendLine(player, "Abyssal demons: ${GlobalKillCounter.getKills(queryPlayer, NPCs.ABYSSAL_DEMON_1615)}", i) - 78 -> sendLine(player, "Abyssal whips: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.ABYSSAL_WHIP_4151)}", i) + 77 -> sendLine(player, "Abyssal demons: ${PlayerStatsCounter.getKills(queryPlayer, intArrayOf(NPCs.ABYSSAL_DEMON_1615))}", i) + 78 -> sendLine(player, "Abyssal whips: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.ABYSSAL_WHIP_4151)}", i) 79 -> sendLine(player, SPACER,i) - 80 -> sendLine(player, "Dark beasts: ${GlobalKillCounter.getKills(queryPlayer, NPCs.DARK_BEAST_2783)}", i) - 81 -> sendLine(player, "Dark bows: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DARK_BOW_11235)}", i) + 80 -> sendLine(player, "Dark beasts: ${PlayerStatsCounter.getKills(queryPlayer, intArrayOf(NPCs.DARK_BEAST_2783))}", i) + 81 -> sendLine(player, "Dark bows: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DARK_BOW_11235)}", i) - 82 -> sendLine(player, "Green Dragons: ${GlobalKillCounter.getKills(queryPlayer, GREEN_DRAGON_IDS)}", i) - 83 -> sendLine(player, "Blue Dragons: ${GlobalKillCounter.getKills(queryPlayer, BLUE_DRAGON_IDS)}", i) - 84 -> sendLine(player, "Red Dragons: ${GlobalKillCounter.getKills(queryPlayer, RED_DRAGON_IDS)}", i) - 85 -> sendLine(player, "Black Dragons: ${GlobalKillCounter.getKills(queryPlayer, BLACK_DRAGON_IDS)}", i) + 82 -> sendLine(player, "Green Dragons: ${PlayerStatsCounter.getKills(queryPlayer, GREEN_DRAGON_IDS)}", i) + 83 -> sendLine(player, "Blue Dragons: ${PlayerStatsCounter.getKills(queryPlayer, BLUE_DRAGON_IDS)}", i) + 84 -> sendLine(player, "Red Dragons: ${PlayerStatsCounter.getKills(queryPlayer, RED_DRAGON_IDS)}", i) + 85 -> sendLine(player, "Black Dragons: ${PlayerStatsCounter.getKills(queryPlayer, BLACK_DRAGON_IDS)}", i) 86 -> sendLine(player, SPACER,i) - 87 -> sendLine(player, "Bronze Dragons: ${GlobalKillCounter.getKills(queryPlayer, BRONZE_DRAGON_IDS)}", i) - 88 -> sendLine(player, "Iron Dragons: ${GlobalKillCounter.getKills(queryPlayer, IRON_DRAGON_IDS)}", i) - 89 -> sendLine(player, "Steel Dragons: ${GlobalKillCounter.getKills(queryPlayer, STEEL_DRAGON_IDS)}", i) - 90 -> sendLine(player, "Mithril Dragons: ${GlobalKillCounter.getKills(queryPlayer, MITHRIL_DRAGON_IDS)}", i) - 91 -> sendLine(player, "Skeletal Wyverns: ${GlobalKillCounter.getKills(queryPlayer, SKELETAL_WYVERN_IDS)}", i) + 87 -> sendLine(player, "Bronze Dragons: ${PlayerStatsCounter.getKills(queryPlayer, BRONZE_DRAGON_IDS)}", i) + 88 -> sendLine(player, "Iron Dragons: ${PlayerStatsCounter.getKills(queryPlayer, IRON_DRAGON_IDS)}", i) + 89 -> sendLine(player, "Steel Dragons: ${PlayerStatsCounter.getKills(queryPlayer, STEEL_DRAGON_IDS)}", i) + 90 -> sendLine(player, "Mithril Dragons: ${PlayerStatsCounter.getKills(queryPlayer, MITHRIL_DRAGON_IDS)}", i) + 91 -> sendLine(player, "Skeletal Wyverns: ${PlayerStatsCounter.getKills(queryPlayer, SKELETAL_WYVERN_IDS)}", i) 92 -> sendLine(player, SPACER,i) - 93 -> sendLine(player, "Draconic visages: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DRACONIC_VISAGE_11286)}", i) + 93 -> sendLine(player, "Draconic visages: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DRACONIC_VISAGE_11286)}", i) else -> sendLine(player,"",i) } } 2 -> { when(i) { - 97 -> sendLine(player, "Ahrim's hood: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.AHRIMS_HOOD_4708)}", i) - 68 -> sendLine(player, "Ahrim's staff: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.AHRIMS_STAFF_4710)}", i) - 69 -> sendLine(player, "Ahrim's robetop: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.AHRIMS_ROBETOP_4712)}", i) - 70 -> sendLine(player, "Ahrim's robeskirt: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.AHRIMS_ROBESKIRT_4714)}", i) + 97 -> sendLine(player, "Ahrim's hood: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.AHRIMS_HOOD_4708)}", i) + 68 -> sendLine(player, "Ahrim's staff: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.AHRIMS_STAFF_4710)}", i) + 69 -> sendLine(player, "Ahrim's robetop: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.AHRIMS_ROBETOP_4712)}", i) + 70 -> sendLine(player, "Ahrim's robeskirt: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.AHRIMS_ROBESKIRT_4714)}", i) 71 -> sendLine(player, SPACER,i) - 72 -> sendLine(player, "Dharok's helm: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DHAROKS_HELM_4716)}", i) - 73 -> sendLine(player, "Dharok's greataxe: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DHAROKS_GREATAXE_4718)}", i) - 74 -> sendLine(player, "Dharok's platebody: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DHAROKS_PLATEBODY_4720)}", i) - 75 -> sendLine(player, "Dharok's platelegs: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.DHAROKS_PLATELEGS_4722)}", i) + 72 -> sendLine(player, "Dharok's helm: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DHAROKS_HELM_4716)}", i) + 73 -> sendLine(player, "Dharok's greataxe: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DHAROKS_GREATAXE_4718)}", i) + 74 -> sendLine(player, "Dharok's platebody: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DHAROKS_PLATEBODY_4720)}", i) + 75 -> sendLine(player, "Dharok's platelegs: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.DHAROKS_PLATELEGS_4722)}", i) 76 -> sendLine(player, SPACER,i) - 77 -> sendLine(player, "Guthan's helm: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.GUTHANS_HELM_4724)}", i) - 78 -> sendLine(player, "Guthan's warspear: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.GUTHANS_WARSPEAR_4726)}", i) - 79 -> sendLine(player, "Guthan's platebody: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.GUTHANS_PLATEBODY_4728)}", i) - 80 -> sendLine(player, "Guthan's chainskirt: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.GUTHANS_CHAINSKIRT_4730)}", i) + 77 -> sendLine(player, "Guthan's helm: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.GUTHANS_HELM_4724)}", i) + 78 -> sendLine(player, "Guthan's warspear: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.GUTHANS_WARSPEAR_4726)}", i) + 79 -> sendLine(player, "Guthan's platebody: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.GUTHANS_PLATEBODY_4728)}", i) + 80 -> sendLine(player, "Guthan's chainskirt: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.GUTHANS_CHAINSKIRT_4730)}", i) - 82 -> sendLine(player, "Karil's coif: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.KARILS_COIF_4732)}", i) - 83 -> sendLine(player, "Karil's crossbow: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.KARILS_CROSSBOW_4734)}", i) - 84 -> sendLine(player, "Karil's leathertop: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.KARILS_LEATHERTOP_4736)}", i) - 85 -> sendLine(player, "Karil's leatherskirt: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.KARILS_LEATHERSKIRT_4738)}", i) + 82 -> sendLine(player, "Karil's coif: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.KARILS_COIF_4732)}", i) + 83 -> sendLine(player, "Karil's crossbow: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.KARILS_CROSSBOW_4734)}", i) + 84 -> sendLine(player, "Karil's leathertop: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.KARILS_LEATHERTOP_4736)}", i) + 85 -> sendLine(player, "Karil's leatherskirt: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.KARILS_LEATHERSKIRT_4738)}", i) 86 -> sendLine(player, SPACER,i) - 87 -> sendLine(player, "Torag's helm: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.TORAGS_HELM_4745)}", i) - 88 -> sendLine(player, "Torag's hammers: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.TORAGS_HAMMERS_4747)}", i) - 89 -> sendLine(player, "Torag's platebody: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.TORAGS_PLATEBODY_4749)}", i) - 90 -> sendLine(player, "Torag's platelegs: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.TORAGS_PLATELEGS_4751)}", i) + 87 -> sendLine(player, "Torag's helm: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.TORAGS_HELM_4745)}", i) + 88 -> sendLine(player, "Torag's hammers: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.TORAGS_HAMMERS_4747)}", i) + 89 -> sendLine(player, "Torag's platebody: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.TORAGS_PLATEBODY_4749)}", i) + 90 -> sendLine(player, "Torag's platelegs: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.TORAGS_PLATELEGS_4751)}", i) 91 -> sendLine(player, SPACER,i) - 92 -> sendLine(player, "Verac's helm: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.VERACS_HELM_4753)}", i) - 93 -> sendLine(player, "Verac's flail: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.VERACS_FLAIL_4755)}", i) - 94 -> sendLine(player, "Verac's brassard: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.VERACS_BRASSARD_4757)}", i) - 95 -> sendLine(player, "Verac's plateskirt: ${GlobalKillCounter.getRareDrops(queryPlayer, Items.VERACS_PLATESKIRT_4759)}", i) + 92 -> sendLine(player, "Verac's helm: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.VERACS_HELM_4753)}", i) + 93 -> sendLine(player, "Verac's flail: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.VERACS_FLAIL_4755)}", i) + 94 -> sendLine(player, "Verac's brassard: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.VERACS_BRASSARD_4757)}", i) + 95 -> sendLine(player, "Verac's plateskirt: ${PlayerStatsCounter.getRareDrops(queryPlayer, Items.VERACS_PLATESKIRT_4759)}", i) else -> sendLine(player,"",i) } } diff --git a/Server/src/test/kotlin/PlayerStatsCounterTests.kt b/Server/src/test/kotlin/PlayerStatsCounterTests.kt new file mode 100644 index 000000000..1b2ce9bc7 --- /dev/null +++ b/Server/src/test/kotlin/PlayerStatsCounterTests.kt @@ -0,0 +1,111 @@ +import core.api.utils.PlayerStatsCounter +import core.game.node.item.Item +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import java.io.File + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class PlayerStatsCounterTests { + companion object { + private const val TEST_DB_PATH = "player_stats_test.db" + private val counter = PlayerStatsCounter(TEST_DB_PATH) + init { + TestUtils.preTestSetup() + counter.startup() + } + @AfterAll @JvmStatic fun cleanup() { + File(TEST_DB_PATH).delete() + } + } + + @Test fun testKillIncrementShouldAddOneKillForNewPlayer() { + val testPlayer = TestUtils.getMockPlayer("test_kill_inc") + val testNPCId = 10 + + val oldKills = PlayerStatsCounter.getKills(testPlayer, IntArray(testNPCId)) + Assertions.assertEquals(0, oldKills) + + PlayerStatsCounter.incrementKills(testPlayer,testNPCId) + + val newKills = PlayerStatsCounter.getKills(testPlayer, intArrayOf(testNPCId)) + Assertions.assertEquals(1, newKills) + } + + @Test fun testGetKillShouldReturnKillsForSinglePlayer() { + val testPlayer = TestUtils.getMockPlayer("kill_single_player_1") + val testPlayer2 = TestUtils.getMockPlayer("kill_single_player_2") + val testNPCId = 10 + + PlayerStatsCounter.incrementKills(testPlayer,testNPCId) + + PlayerStatsCounter.incrementKills(testPlayer2,testNPCId) + PlayerStatsCounter.incrementKills(testPlayer2,testNPCId) + + val kills = PlayerStatsCounter.getKills(testPlayer2, intArrayOf(testNPCId)) + Assertions.assertEquals(2, kills) + } + + @Test fun testGetKillShouldReturnSumForAllNPCsForAGivenPlayer() { + val testPlayer = TestUtils.getMockPlayer("test_sum_npcs") + val testNPCId1 = 10 + val testNPCId2 = 11 + val testNPCId3 = 12 + + PlayerStatsCounter.incrementKills(testPlayer,testNPCId1) + + PlayerStatsCounter.incrementKills(testPlayer,testNPCId2) + PlayerStatsCounter.incrementKills(testPlayer,testNPCId2) + PlayerStatsCounter.incrementKills(testPlayer,testNPCId2) + + PlayerStatsCounter.incrementKills(testPlayer,testNPCId3) + PlayerStatsCounter.incrementKills(testPlayer,testNPCId3) + + val killsForNPCs1And2 = PlayerStatsCounter.getKills(testPlayer, intArrayOf(testNPCId1, testNPCId2)) + Assertions.assertEquals(4, killsForNPCs1And2) + val killsForAllNPCs = PlayerStatsCounter.getKills(testPlayer, intArrayOf(testNPCId1, testNPCId2, testNPCId3)) + Assertions.assertEquals(6, killsForAllNPCs) + } + + @Test fun testRewardIncrementShouldAddOneRewardForNewPlayer() { + val testPlayer = TestUtils.getMockPlayer("test_reward_inc") + val itemId = 10 + + val oldRareDrops = PlayerStatsCounter.getRareDrops(testPlayer, itemId) + Assertions.assertEquals(0, oldRareDrops) + + PlayerStatsCounter.incrementRareDrop(testPlayer, Item(itemId)) + + val newRareDrops = PlayerStatsCounter.getRareDrops(testPlayer, itemId) + Assertions.assertEquals(1, newRareDrops) + } + + @Test fun testGetRewardsShouldReturnRewardsForSinglePlayer() { + val testPlayer = TestUtils.getMockPlayer("reward_single_player_1") + val testPlayer2 = TestUtils.getMockPlayer("reward_single_player_2") + val testItemId = 10 + + PlayerStatsCounter.incrementRareDrop(testPlayer,Item(testItemId)) + + PlayerStatsCounter.incrementRareDrop(testPlayer2,Item(testItemId)) + PlayerStatsCounter.incrementRareDrop(testPlayer2,Item(testItemId)) + + val rareDrops = PlayerStatsCounter.getRareDrops(testPlayer2, testItemId) + Assertions.assertEquals(2, rareDrops) + } + + @Test fun testGetRewardsShouldHonourItemAmountWhenIncrementing() { + val testPlayer = TestUtils.getMockPlayer("test_reward_inc_itemamount") + val itemId = 10 + + val itemAmount: Long = 5 + + val oldRareDrops = PlayerStatsCounter.getRareDrops(testPlayer, itemId) + Assertions.assertEquals(0, oldRareDrops) + + PlayerStatsCounter.incrementRareDrop(testPlayer, Item(itemId, itemAmount.toInt())) + + val newRareDrops = PlayerStatsCounter.getRareDrops(testPlayer, itemId) + Assertions.assertEquals(itemAmount, newRareDrops) + } +} From 618d39d73c5ab7442c7bca8cb7508e5c550aeb7e Mon Sep 17 00:00:00 2001 From: Player Name Date: Thu, 13 Feb 2025 11:30:02 +0000 Subject: [PATCH 214/306] Fixed shooting star resetting on server shutdown --- .../activity/shootingstar/ShootingStar.kt | 65 +++++++++++-------- .../shootingstar/ShootingStarMiningPulse.kt | 1 + .../shootingstar/ShootingStarPlugin.kt | 19 +++++- .../wilderness/handlers/ChaosTunnelZone.java | 2 +- Server/src/main/core/ServerStore.kt | 12 ++-- 5 files changed, 64 insertions(+), 35 deletions(-) diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt index 0dd2e005a..9432ea009 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt @@ -11,12 +11,13 @@ import core.ServerStore.Companion.getString import content.global.bots.ShootingStarBot import core.game.world.repository.Repository +import core.tools.RandomFunction /** * Represents a shooting star object (Only ever initialized once) (ideally) * @author Ceikry */ -class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()){ +class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()) { val crash_locations = mapOf( "East of Dark Wizards' Tower" to Location.create(2925, 3339, 0), // East of Dark Wizards' Tower "Crafting Guild" to Location.create(2940, 3280, 0), // Crafting Guild Mine @@ -79,22 +80,15 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando * Degrades a ShootingStar (or removes the starObject and spawns a Star Sprite if it's the last star) */ fun degrade() { - if(level.ordinal == 0){ - selfBots.filter { it.isMining() }.forEach { it.sleep() } - SceneryBuilder.remove(starObject) - isSpawned = false - starSprite.location = starObject.location - starSprite.init() - spriteSpawned = true - ShootingStarPlugin.getStoreFile().clear() + if(level.ordinal == 0) { + spawnSprite() return } level = getNextType() maxDust = level.totalStardust dustLeft = level.totalStardust - ShootingStarPlugin.getStoreFile()["level"] = level.ordinal - ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered + ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft val newStar = Scenery(level.objectId, starObject.location) SceneryBuilder.replace(starObject, newStar) @@ -110,7 +104,6 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando */ fun fire() { SceneryBuilder.remove(starObject) - rebuildVars() clearSprite() SceneryBuilder.add(starObject) if(!isSpawned) { @@ -123,37 +116,54 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando } isSpawned = true Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location}!") + ShootingStarPlugin.getStoreFile()["level"] = level.ordinal + ShootingStarPlugin.getStoreFile()["location"] = location + ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered + ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft } /** * Rebuilds some of the variables with new information. */ fun rebuildVars(){ - if(firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()){ - level = ShootingStarType.values()[ShootingStarPlugin.getStoreFile().getInt("level")] - location = ShootingStarPlugin.getStoreFile().getString("location") - isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered") - } else { - level = ShootingStarType.values().random() - location = crash_locations.entries.random().key - isDiscovered = false + // Defaults + var levelOrd = RandomFunction.random(9) + level = ShootingStarType.values()[levelOrd] + location = crash_locations.entries.random().key + isDiscovered = false + dustLeft = level.totalStardust + ticks = 0 + spriteSpawned = false + + if (firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()) { + // Replace default with stored values, if any + levelOrd = ShootingStarPlugin.getStoreFile().getInt("level", levelOrd) + level = ShootingStarType.values()[levelOrd] + location = ShootingStarPlugin.getStoreFile().getString("location", location) + isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered", false) + dustLeft = ShootingStarPlugin.getStoreFile().getInt("dustLeft", dustLeft) + ticks = ShootingStarPlugin.getStoreFile().getInt("ticks", ticks) + spriteSpawned = ShootingStarPlugin.getStoreFile().getBoolean("spriteSpawned", false) } maxDust = level.totalStardust - dustLeft = level.totalStardust starObject = Scenery(level.objectId, crash_locations.get(location)) + } - ShootingStarPlugin.getStoreFile()["level"] = level.ordinal - ShootingStarPlugin.getStoreFile()["location"] = location - ShootingStarPlugin.getStoreFile()["isDiscovered"] = false - - ticks = 0 - firstStar = false + fun spawnSprite() { + selfBots.filter { it.isMining() }.forEach { it.sleep() } + SceneryBuilder.remove(starObject) + isSpawned = false + starSprite.location = starObject.location + starSprite.init() + spriteSpawned = true + ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned } fun clearSprite() { starSprite.clear() spriteSpawned = false + ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned } /** @@ -161,6 +171,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando */ fun decDust() { if(--dustLeft <= 0) degrade() + ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft } /** diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStarMiningPulse.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStarMiningPulse.kt index 456efb4f2..5f5ee3649 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStarMiningPulse.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStarMiningPulse.kt @@ -51,6 +51,7 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin player.sendMessage("You have ${player.skills.experienceMultiplier * player.getAttribute("shooting-star:bonus-xp", 0).toDouble()} bonus xp towards mining stardust.") ShootingStarPlugin.submitScoreBoard(player) star.isDiscovered = true + ShootingStarPlugin.getStoreFile()["isDiscovered"] = star.isDiscovered return player.skills.getLevel(Skills.MINING) >= star.miningLevel } diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt index 680d2d6da..1e993e1bb 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt @@ -27,14 +27,30 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com override fun tick() { ++star.ticks + // Check if the current star sprite should expire val maxDelay = tickDelay + (tickDelay / 3) if(star.ticks > maxDelay && star.spriteSpawned){ star.clearSprite() } - if ((star.ticks >= tickDelay && !star.spriteSpawned) || (!star.isSpawned && !star.spriteSpawned)) { + if (star.firstStar && !star.isSpawned && !star.spriteSpawned) { + // Apparently, the server has only just booted + star.rebuildVars() + if (star.spriteSpawned) { + star.spawnSprite() + } else { + star.fire() + } + star.firstStar = false + } + + // Check if it's time to fire a new one + if (star.ticks >= tickDelay && !star.spriteSpawned) { + star.rebuildVars() star.fire() } + + getStoreFile()["ticks"] = star.ticks } override fun defineListeners() { @@ -122,6 +138,7 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com } define("submit", Privilege.ADMIN) { _, _ -> + star.rebuildVars() star.fire() } diff --git a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java index c240e190b..6d1f06cfc 100644 --- a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java +++ b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java @@ -267,7 +267,7 @@ public final class ChaosTunnelZone extends MapZone implements Plugin { * @param player The player. */ private void commenceBorkBattle(Player player) { - if (ServerStore.getBoolean(getStoreFile(), player.getUsername().toLowerCase()) && GameWorld.getSettings().isHosted()) { + if (ServerStore.getBoolean(getStoreFile(), player.getUsername().toLowerCase(), false) && GameWorld.getSettings().isHosted()) { player.getPacketDispatch().sendMessage("The portal's magic is too weak to teleport you right now."); return; } diff --git a/Server/src/main/core/ServerStore.kt b/Server/src/main/core/ServerStore.kt index ad2678584..52df7fb52 100644 --- a/Server/src/main/core/ServerStore.kt +++ b/Server/src/main/core/ServerStore.kt @@ -113,18 +113,18 @@ class ServerStore : PersistWorld { } @JvmStatic - fun JSONObject.getString(key: String): String { - return this[key] as? String ?: "nothing" + fun JSONObject.getString(key: String, default: String = "nothing"): String { + return this[key] as? String ?: default } @JvmStatic - fun JSONObject.getLong(key: String): Long { - return this[key] as? Long ?: 0L + fun JSONObject.getLong(key: String, default: Long = 0L): Long { + return this[key] as? Long ?: default } @JvmStatic - fun JSONObject.getBoolean(key: String): Boolean { - return this[key] as? Boolean ?: false + fun JSONObject.getBoolean(key: String, default: Boolean = false): Boolean { + return this[key] as? Boolean ?: default } fun List.toJSONArray(): JSONArray{ From 4387b346dc60dc74bcf310959b8967821170cba5 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Thu, 13 Feb 2025 12:34:23 +0000 Subject: [PATCH 215/306] Implemented The Curse of Zaros Miniquest --- Server/data/configs/npc_configs.json | 198 ++++++++++++++++++ Server/data/configs/npc_spawns.json | 56 ++++- .../desert/quest/curseofzaros/CurseOfZaros.kt | 189 +++++++++++++++++ .../MysteriousGhostDhalakDialogue.kt | 149 +++++++++++++ .../MysteriousGhostKharrimDialogue.kt | 143 +++++++++++++ .../MysteriousGhostLennissaDialogue.kt | 155 ++++++++++++++ .../MysteriousGhostRennardDialogue.kt | 151 +++++++++++++ .../MysteriousGhostValdezDialogue.kt | 136 ++++++++++++ .../MysteriousGhostViggoraDialogue.kt | 188 +++++++++++++++++ 9 files changed, 1361 insertions(+), 4 deletions(-) create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/CurseOfZaros.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostDhalakDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostKharrimDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostLennissaDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostRennardDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostValdezDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostViggoraDialogue.kt diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 6ca752c8c..2967df677 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -24103,6 +24103,199 @@ "attack_level": "61" }, { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2381", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2382", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2383", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2384", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2385", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2386", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2387", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2388", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2389", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2390", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2391", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2392", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2393", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2394", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2395", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", + "name": "Mysterious ghost", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "combat_audio": "436,439,438", + "strength_level": "1", + "id": "2396", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, @@ -24114,6 +24307,7 @@ "attack_level": "1" }, { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, @@ -24125,6 +24319,7 @@ "attack_level": "1" }, { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, @@ -24136,6 +24331,7 @@ "attack_level": "1" }, { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, @@ -24147,6 +24343,7 @@ "attack_level": "1" }, { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, @@ -24158,6 +24355,7 @@ "attack_level": "1" }, { + "examine": "Seems to flitter in and out of existence...", "name": "Mysterious ghost", "defence_level": "1", "safespot": null, diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 98df5d25d..3684e902a 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -5511,21 +5511,69 @@ "npc_id": "2374", "loc_data": "{2041,4632,0,1,3}-{2037,4630,0,1,3}-{2041,4644,0,1,4}-" }, + { + "npc_id": "2381", + "loc_data": "{2555,3444,0,1,0}-" + }, + { + "npc_id": "2382", + "loc_data": "{3022,3946,0,1,0}-" + }, + { + "npc_id": "2383", + "loc_data": "{3034,3701,0,1,0}-" + }, + { + "npc_id": "2384", + "loc_data": "{3162,2982,0,1,0}-" + }, { "npc_id": "2385", - "loc_data": "{3112,3159,0,0,0}-" + "loc_data": "{3112,3158,0,1,0}-" }, { "npc_id": "2386", - "loc_data": "{3051,3496,1,0,0}-" + "loc_data": "{3052,3496,1,1,0}-" + }, + { + "npc_id": "2387", + "loc_data": "{3053,3378,1,1,0}-" + }, + { + "npc_id": "2388", + "loc_data": "{2950,3820,0,1,0}-" }, { "npc_id": "2389", - "loc_data": "{3219,3677,0,0,0}-" + "loc_data": "{3218,3677,0,1,0}-" + }, + { + "npc_id": "2390", + "loc_data": "{3068,3858,0,1,0}-" + }, + { + "npc_id": "2391", + "loc_data": "{2850,3348,0,1,0}-" }, { "npc_id": "2392", - "loc_data": "{3043,3204,0,0,0}-" + "loc_data": "{3044,3204,0,1,0}-" + }, + { + "npc_id": "2393", + "loc_data": "{2396,3481,0,1,0}-" + }, + { + "npc_id": "2394", + "loc_data": "{3294,3934,1,1,0}-" + }, + { + "npc_id": "2395", + "loc_data": "{3448,3550,1,1,0}-" + }, + { + "npc_id": "2396", + "loc_data": "{3119,9996,0,1,0}-" }, { "npc_id": "2414", diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/CurseOfZaros.kt b/Server/src/main/content/region/desert/quest/curseofzaros/CurseOfZaros.kt new file mode 100644 index 000000000..a57abef78 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/CurseOfZaros.kt @@ -0,0 +1,189 @@ +package content.region.desert.quest.curseofzaros + +import core.game.dialogue.* +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player + +/** + * Curse of Zaros is a miniquest with no quest points or final dialogue + * + * Players get the ghostly set for fashionscape. + */ +class CurseOfZaros { + companion object { + const val attributePathNumber = "/save:miniquest:curseofzaros-pathnumber" // 1 of 3. + const val attributeValdezSpoke = "/save:miniquest:curseofzaros-valdezspoke" + const val attributeRennardSpoke = "/save:miniquest:curseofzaros-rennardspoke" + const val attributeKharrimSpoke = "/save:miniquest:curseofzaros-kharrimspoke" + const val attributeLennissaSpoke = "/save:miniquest:curseofzaros-lennissaspoke" + const val attributeDhalakSpoke = "/save:miniquest:curseofzaros-dhalakspoke" + const val attributeViggoraSpoke = "/save:miniquest:curseofzaros-viggoraspoke" + + // Ghostly Robes lost: http://youtu.be/YcwYOqfG1Ys + + fun withoutGhostspeak(d: DialogueLabeller) { + fun label(label: String) { d.label(label) } + fun loadLabel(player: Player, label: String) { d.loadLabel(player, label) } + fun player(vararg messages: String) { d.player(ChatAnim.NEUTRAL, *messages) } + fun npc(vararg messages: String) { d.npc(ChatAnim.NEUTRAL, *messages) } + fun exec(callback: (player: Player, npc: NPC) -> Unit) { d.exec(callback) } + + label("noghostspeak") + exec { player, npc -> + loadLabel(player, "noghostspeak" + (1..8).random()) + } + + label("noghostspeak1") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("You don't say?") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("You don't say!") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Well, I guess you didn't say.") + + label("noghostspeak2") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("Yeah, I don't want to brag, but seriously: I am SOOOO rich....") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("Yeah, I know they say money doesn't bring you happiness, but sometimes I just like to open my bank account and look at all of the stuff I own and just think to myself:") + player("Wow. I am soooooo rich.") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Well, us rich alive people don't want to waste all day spending time with you poor dead people, because I'm just sooooo rich I have to go now, and very possibly make myself even richer.") + player("See ya around ghosty!") + + label("noghostspeak3") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("Yeah, I heard about that, ha-ha-ha!") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("With a MACKEREL? Ouch!") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Well, it was fun. Let's do it again sometime.") + + label("noghostspeak4") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("Why, thank you very much!") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("I know, but what are you going to do?") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Well, I guess that's always true in the long run. See you around, weird invisible dead person!") + + label("noghostspeak5") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("Yeah it's not bad, but I prefer cooked chicken.") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("Maybe, but nothing beats a home cooked pie!") + player("Man, I love pie!") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("You don't say? I never knew that. Well, I must be going, see you around.") + + // This is peak 2009 memez + label("noghostspeak6") + player("Hello there.") + npc("Wooo? Woooo woo woooooo wooooo woooowooo wooo woooooo woo!") + player("We get signal!") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("Somebody set up us the bomb!") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("You have no chance to survive make your time.") + npc("Woo?") + player("All your base are belong to us.") + + label("noghostspeak7") + player("Hey, don't think you can talk to me like that!") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("Are you threatening me?") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Just because you're already dead, doesn't mean I can't find a way to hurt you ghosty!") + + label("noghostspeak8") + player("No, I've never been there in my life and CERTAINLY didn't steal anything when I was!") + npc("Woo! WOO WOOOOO WOOWOOWOO WOO WOOOOO!") + player("Are you calling me a liar?!?! I have never stolen a thing in my life, and I resent the implication that I am the kind of morally depraved individual that would steal someone else's hard earned") + player("money from their very pockets!") + player("Or cakes. Or fur. Repeatedly. For long periods at a time.") + npc("Wooowoowoooooo.... Woowoowoo? Woooo, wooowoo wooowooowooo!") + player("Well if you are going to take that attitude, then I have nothing further to say on the matter, and bid you good day!") + } + + + fun wrongPath(d: DialogueLabeller) { + fun label(label: String) { d.label(label) } + fun loadLabel(player: Player, label: String) { d.loadLabel(player, label) } + fun player(vararg messages: String) { d.player(ChatAnim.NEUTRAL, *messages) } + fun npc(vararg messages: String) { d.npc(ChatAnim.NEUTRAL, *messages) } + fun exec(callback: (player: Player, npc: NPC) -> Unit) { d.exec(callback) } + + label("wrongpath") + exec { player, npc -> + loadLabel(player, "wrongpath" + (1..7).random()) + } + + label("wrongpath1") + player("Hello there.") + npc("The endless tragedy of fate...", "Why must you torment me so?") + player("Alright, alright, calm down, calm down. All I said was 'hello'!") + + label("wrongpath2") + player("Hello there.") + npc("You can see me?") + player("Uh... yes?") + npc("And you understand my words?") + player("Well, most of them...") + npc("This is incredible! How can such a thing have come to pass?") + player("What can I say? I'm a professional.") + + label("wrongpath3") + player("Hello there.") + npc("Hello back at you.") + player("So what's a nice ghost like you doing in a place like this?") + npc("I suppose you think that's funny?") + player("Well... Mildly amusing I guess.") + npc("I don't think I want to talk to you anymore.") + + label("wrongpath4") + player("Hello there.") + npc("Hello stranger. It is rare indeed that I meet one who can see my presence, let alone one who can understand my words.") + player("Soooo.... Is it fun being a ghost?") + npc("Does it look like fun to you?") + player("Erm... Well, yes actually.") + npc("Then you are a fool, and I will waste no more words upon you.") + player("What, not even 'goodbye'?") + npc(" ") + player("Sheesh, what a grouch. You'd think you'd have more of a sense of humour being dead and all.") + + label("wrongpath5") + player("Hello there.") + npc("Mortal... Take heed of my example, and waste not your life, lest you may suffer the same fate as myself...") + player("Huh? You mean someone did this to you?") + npc("You have ascertained the truth in my words...") + player("So who did it to you? And why?") + npc("Events of moons past, I remember not clearly...") + player("Fine help you are then.") + + label("wrongpath6") + player("Hello there.") + npc("Hello stranger.") + player("So.... Invisible ghost haunting the same place for thousands of years, huh?") + npc("You have no idea...") + player("Well, bad luck and all that. See ya around!") + + label("wrongpath7") + player("Hello there.") + npc("Hello.") + player("So you're a ghost, huh?") + npc("Apparently.") + player("In which case I only have one thing to say to you:") + npc("...what?") + player("Guess you don't have the amulet of humanspeak, huh?") + npc("...huh?") + player("Yeah, that's right. WOO! WOOOWOOO WOO WOOOOWOO! Got no comeback for that, have you?") + npc("You are very strange...") + + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostDhalakDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostDhalakDialogue.kt new file mode 100644 index 000000000..d8c89c1d0 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostDhalakDialogue.kt @@ -0,0 +1,149 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostDhalakDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostDhalakDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostDhalakDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2385, 2386, 2387) + } +} + +class MysteriousGhostDhalakDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (2384 + getAttribute(player, CurseOfZaros.attributePathNumber, 0) == npc.id) { + if (getAttribute(player, CurseOfZaros.attributeDhalakSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_HOOD_6109) || inEquipment(player, Items.GHOSTLY_HOOD_6109)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "wrongpath") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + CurseOfZaros.wrongPath(this) + + label("firsttime") + player("Hello Dhalak.") + npc("You see my form, hear my words, and know my name, yet your face I recognise not...") + npc("Be you some mighty sorcerer to bind me so?") + player("Um... Well, not really...") // player("Well, I don't mean to brag, but I guess I am with my level 99 magic...") if you are 99 lvl magic but calm the fuck down showoff + player("But that is besides the point. It is not I who has trapped you here as a ghost.") + npc("Then how comes it to be that you know my name stranger?") + player("Lennissa told me about you, and where to find you?") + npc("Lennissa? Oh that poor sweet girl... Has my foolishness cursed her as well as myself???") + player("Your foolishness?") + npc("The story shames me stranger, I wouldst rather keep it unto myself.") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Look, I don't want to force you into telling me, but perhaps sharing it with someone might relieve your guilt?") + npc("Aye... Perhaps it might at that.") + npc("So what has Lennissa told you of the events of the day this curse befell me?") + player("Well, she told me that she was working as an undercover agent of Saradomin amongst the followers of some 'Empty Lord', and when news of the theft of a god-weapon reached her, she passed the message on to") + player("you instead of taking it to Saradomin because she was scared her cover might be blown.") + npc("Aye, that is a fair account of events...") + player("But I don't understand why you didn't take her message to Saradomin?") + npc("Stranger, my foolishness was a result of my respect for Saradomin, not as a result of any attempted treachery!") + player("So why didn't you pass on Lennissa's message? As I understand it something happened with that staff that could have been avoided if you had passed her message on!") + npc("(sigh) I know not what occurred with that god-weapon, but I have my suspicions...") + npc("Let me explain myself. I was Lennissa's immediate superior, and I was often her contact for missions.") + npc("Because of this role, I had access to a larger picture of what was happening than she herself did, and I was not only well aware that her presence amongst the enemy camp had been detected, but I was also well aware that") + npc("there was a growing faction amongst them who were plotting to overthrow their master.") + player("Their master being...?") + npc("That I will not tell you. I will tempt the fates no more than I already have done.") + npc("But anyway, it had come to my attention that the Mahjarrat who had been liberated from the control of Icthlarin did not much appreciate one form of slavery to another, and under the leadership of the mighty") + npc("Zamorak were making plans to overthrow their master and take his power for themselves.") + npc("Now, as powerful, long-lived and evil as they were, they were still just mortal, and I made the decision that it would be of benefit to my Lord Saradomin for his mightiest rival to be distracted by such internal conflicts.") + player("So that is why you decided not to pass the report from Lennissa on?") + npc("Yes, but my guilt is more than simply inaction...") + npc("I knew that with such a weapon, Zamorak would be capable of launching an attack that could actually stand a chance of success, but I also knew that he would never be able to get a chance to use it in a battle for") + npc("being a god-weapon its very presence would have sung out to their leader.") + player("I'm guessing you did something about that, then?") + npc("Indeed I did. To my eternal shame, I decided that I would assist Zamorak and his henchmen in their battle, by secretly casting a spell of concealment upon the staff so that") + npc("they might use it secretly against their master.") + player("So Zamorak knew about this?") + npc("No, nobody except myself, and now you, knew that I cast such a spell....") + npc("Had I known what a threat to my Lord Saradomin Zamorak would later become, I wouldst have taken the message to Saradomin immediately! Alas, it is all too easy to see your mistakes after you") + npc("have made them...") + player("I'm confused. What exactly happened with this staff anyway? And why have all these various random people been cursed because of it?") + npc("I cannot answer your question with anything other than my own suppositions, but I do know of one who might be able to, and if any man deserved to be cursed for their actions that day, it was he!") + player("Who are you speaking of?") + npc("His name was Viggora. He was an evil man, brutal and vicious, and deadly with a blade.") + npc("He was one of the few humans Zamorak allowed to rise to a position of power amongst his rebels, possibly because he imitated those same qualities of Zamorak.") + npc("If anyone knows what Zamorak did with that god- weapon to have caused this curse to have befallen us, it would have been he, for he would have been fighting on Zamorak's very right hand side in their rebellion.") + npc("Please, if this curse can be lifted, find Viggora and find out what he has wrought upon us! I have no wealth nor magic to aid you, but take my hood as reward;") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeDhalakSpoke, true) + addItemOrDrop(player, Items.GHOSTLY_HOOD_6109) + } + npc("it has served me well these centuries past, and may bring you luck.") + player("Where would you suggest I look for Viggora?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("subsequenttime") + player("Dhalak, where can I find the swordsman Viggora?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("curseofzaros1") + npc("Ah, the evil swordsman Viggora... A rogue like him would probably flock to his own kind.") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros2") + npc("Ah, the evil swordsman Viggora... Perhaps he has returned to his castle in the dark lands?") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros3") + npc("Ah, the evil swordsman Viggora... Paddewwa was where he fought many battles, perhaps he has returned to one of his old haunts?") + player("Okay, well I'll try and find him for you then.") + + + label("lostghostlything") + + player(ChatAnim.SAD, "Could I have that hat again? I seem to have misplaced it", "somewhere...") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_HOOD_6109) + } + npc("Certainly, I am not sure how, but it returned to me by", "some magic or other.") + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostKharrimDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostKharrimDialogue.kt new file mode 100644 index 000000000..4d825f193 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostKharrimDialogue.kt @@ -0,0 +1,143 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostKharrimDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostKharrimDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostKharrimDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2388, 2389, 2390) + } +} + +class MysteriousGhostKharrimDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (2387 + getAttribute(player, CurseOfZaros.attributePathNumber, 0) == npc.id) { + if (getAttribute(player, CurseOfZaros.attributeKharrimSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_BOOTS_6106) || inEquipment(player, Items.GHOSTLY_BOOTS_6106)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "wrongpath") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + CurseOfZaros.wrongPath(this) + + label("firsttime") + player("Hello. So you must be Kharrim the messenger.") + npc("How do you know my name, stranger?") + player("Well now... I had a very interesting chat with Rennard the thief.") + player("It seems you redirected his message regarding a certain god-weapon for your own ends.") + npc("So THAT is what this is about... I should have known the deal was too good to have no repercussions...") + player("It seems as though you might be responsible for this curse that has befallen you by not delivering Rennard's message to the correct person.") + npc("Ha! That is not a truthful assessment of the story... You might think differently if you had heard my side of events.") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Please let me hear your side of the story then...") + npc("Well, if you have spoken to Rennard, then you will know that he had somehow managed to obtain a very valuable weapon, and was looking for buyers.") + npc("What he probably didn't tell you, was that he met me in a drunken stupor in some smoke filled tavern, and I offered to arrange a purchaser for his item, in exchange for a small finders fee.") + player("So you knew what the staff was?") + npc("The god-staff of Armadyl? Well, of course I did.") + npc("Honestly, you would have to be pretty slow-witted to not recognise a legendary artefact such as that.") + player("Wait, I don't understand, Rennard said that he had a buyer already in mind, and that you diverted his message to a General Zamorak instead?") + npc("Ha! Here is a word of advice for you adventurer; Never trust the words of a drunk.") + npc("Whatever he might have thought he was doing with it, in the end all that happened was he left me to arrange a purchaser for the item.") + player("So you thought you would offer it to General Zamorak?") + npc("Ah yes, Lord Zamorak. He was merely a mortal back then, you know?") + npc("Yet I could see great things in store for him even then. He had a kind of brilliant ruthlessness... And that special kind of vicious streak you see so rarely...") + npc("Well anyway, when given the task of selling a weapon forged by the very gods themselves, I naturally thought of Zamorak as a potential buyer.") + npc("I was a messenger in his employ anyway, so it was a mere trifle to find him and deliver the news, and I knew of his particular interest in armour and weaponry of all kinds.") + npc("Yes, he was always quite the connoisseur when it came to weaponry...") + npc("But I digress. I let Lord Zamorak know that there was some drunken fool with an artefact of incredible power that could probably be bought off with a few jewels and trinkets,") + npc("and he escorted me to the tavern and made the purchase there and then.") + npc("It was a satisfactory deal all around, I got a share of the sale price from Rennard, and I greatly increased my prestige amongst Zamorak and his followers.") + npc("But maybe... Perhaps the events that followed were responsible for my cursed state...") + player("Events that followed?") + npc("I can not tell you of them precisely, for I myself was not there to witness them.") + npc("I am after all, simply a messenger. When... 'it' happened, I was busy elsewhere delivering a message from Zamorak to the rest of his Mahjarrat ilk.") + player("When 'it' happened? What was 'it'?") + npc("As I have explained, I was not there, and I do not know what Zamorak did with the staff, but whatever it was resulted in his banishment by the other gods for many years.") + npc("The very strange thing was that Saradomin must have known about it, whatever it was, before it even happened...") + player("Really? Why do you say that?") + npc("Well, it was the contents of the message I was returning to Zamorak;") + npc("Lucien seemed quite certain that there was a spy for Saradomin somewhere amongst his followers named Lennissa.") + npc("If whatever happened to the staff caused this curse to befall me, then it is certain that she too would have been afflicted, because she would have been in the very heart of the action.") + npc("Hmmm....") + npc("You have given me much to think on adventurer. I would like to reward you with my sturdy messenger boots, may they aid you in your travels.") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeKharrimSpoke, true) + addItemOrDrop(player, Items.GHOSTLY_BOOTS_6106) + } + player("But where can I find this Lennissa?") + npc("Ah yes, the whereabouts of the treacherous Lennissa...") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("subsequenttime") + player("Hello again Kharrim.") + player("Can you remind me where to find Lennissa?") + npc("Ah yes, the whereabouts of the treacherous Lennissa...") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("curseofzaros1") + npc("Well, she was always sickeningly obedient to Saradomin, so I would expect her to have run to some great place of worship of him if she was affected by the curse to try and gain his blessing.") + player("Okay, well I'll try and find her for you then.") + + label("curseofzaros2") + npc("According to Lucien's intelligence report, she had been uncovered as a spy by her constant use of ships to ferry information...") + npc("It is entirely possible she would be located somewhere coastal to this day!") + player("Okay, well I'll try and find her for you then.") + + label("curseofzaros3") + npc("Well, we knew little about her or she would have been caught and exposed as a traitor and a spy, but Lucien did mention that he had evidence that she was a great fan of ball games...") + player("Okay, well I'll try and find her for you then.") + + + label("lostghostlything") + player(ChatAnim.SAD, "I lost those boots you gave me...", "Can I have some more please?") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_BOOTS_6106) + } + npc(ChatAnim.SAD, "How strange...", "They seemed to return to me when you lost them...") + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostLennissaDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostLennissaDialogue.kt new file mode 100644 index 000000000..74c3657d7 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostLennissaDialogue.kt @@ -0,0 +1,155 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostLennissaDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostLennissaDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostLennissaDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2391, 2392, 2393) + } +} + +class MysteriousGhostLennissaDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (2390 + getAttribute(player, CurseOfZaros.attributePathNumber, 0) == npc.id) { + if (getAttribute(player, CurseOfZaros.attributeLennissaSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_ROBE_6108) || inEquipment(player, Items.GHOSTLY_ROBE_6108)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "wrongpath") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + CurseOfZaros.wrongPath(this) + + label("firsttime") + player("Hello. You would be Lennissa, I take it?") + npc("Who are you? Where did you hear that name? How comes it that you can see and speak to me?") + player("Well, a ghost called Kharrim directed me towards you.") + npc("So that weasel Kharrim has been blighted by this curse too?") + npc("Ha, a good thing too. If anybody deserved such a fate it would be one such as him.") + player("I guess you didn't get along then?") + npc("No, evil scum such as he should never have been allowed to walk this world.") + npc("What lies has he told you to come here? Have you come to try and kill me?") + player("Well, I'm not sure I could if I tried, but that is not why I have come to you.") + npc("Then speak, and speak well, for I may yet be dead, but am still a danger to those who cross me.") + player("Actually, I'm trying to work out why all of you invisible ghosts seem to have been cursed.") + player("I'm not sure how exactly, but the trail seems to have led me to you...") + npc("That makes no sense... I served Saradomin faithfully my entire life, then all of a sudden I find myself reduced to this state!") + player("Well, it seems as though that may have been the cause...") + npc("What? Explain yourself.") + player("As I understand it, it was something to do with the Staff of Armadyl, and your refusal to tell Saradomin that it had been stolen...") + npc("What? But... But that is not how it happened at all!") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Then please, go ahead and tell me the events of that day in your own words...") + npc("Let me see... I had been working as a spy for my Lord Saradomin, amongst the forces of... the Empty Lord.") + player("'The Empty Lord'? Who is that?") + npc("I will not give you his name, for to do so would give him power here.") + npc("Let us just say that he was a fearsome deity, whose strength was greater than all the gods we knew of on this realm at the time.") + npc("It is probably worth mentioning that at this time we had no knowledge of the mysterious nature god Guthix.") + player("So he was stronger than Saradomin?") + npc("As Saradomin was, yes. As Saradomin is now? Who can say?") + player("I see... Please, continue.") + npc("As I say, I was working as a spy within the very camp of my Lord's enemies.") + npc("I knew that should I have been caught, I risked being killed upon the spot, but my combat skills were always formidable, and if truth be told, there was a fair amount of dissent amongst... 'his' followers anyway.") + player("How do you mean 'dissent'?") + npc("Ah, to not understand this, you must have led a sheltered life...") + npc("Let me tell you this: Evil will always breed more evil, and will never be satisfied with what it has.") + npc("The Empty Lord chose to ally himself with the dark creatures of this world, fully aware that their own natures would cause them to rally against his rule, and take every opportunity they could to betray him.") + npc("This has always been the nature of evil. Perhaps he thought his power could prevent such treachery?") + npc("This allowed me freedom amongst their camp, for it was always easy to point the finger of suspicion at some unsuspecting necromancer or foolish Mahjarrat if it seemed as though my activities had been discovered.") + npc("Similarly, should I ever be caught in the act of my sabotage, it was all too easy to bribe whoever found me or persuade them into believing it was just some minor treachery of my own, rather than my work for my") + npc("Lord Saradomin.") + player("Okay... Well, that makes sense, but I don't understand what the Staff of Armadyl had to do with this...?") + npc("As I have told you, the Empty Lord was extremely powerful, but not so powerful that he could rule over the other deities of this world without opposition.") + npc("Should he have made a move against any other god, then he could still have been easily brought down by the combined efforts of the others.") + npc("The theft of Armadyl's staff changed this however.") + npc("If he had taken possession of this god-weapon, then his power would have been so great that he could have overthrown all on this world, and made it into his own image!") + npc("I could not allow such a thing to happen!") + npc("I went immediately to my comrade Dhalak, the mage, and told him that a message had come to the lair offering this weapon for sale!") + npc("I knew that as soon as my Lord Saradomin heard this, he would contact Armadyl to inform them of the theft, and the matter would have been resolved quickly and discreetly.") + player("So you passed this information to Dhalak instead of taking it to Saradomin yourself?") + npc("To my eternal shame, I indeed failed my Lord Saradomin...") + npc("I could not risk taking the message directly, for I feared my disguise had been uncovered.") + npc("Lucien particularly had been taking an unhealthy interest in my activities, and I had a gut feeling that to make any obvious moves against the Empty Lord would have been my undoing.") + npc("But Dhalak was a noble man! I cannot believe that he would not have taken my message immediately to Lord Saradomin!") + player("Well, it seems like he didn't, but I don't know why not...") + npc("Please adventurer, discover what foul fate must have befallen him for him to have neglected his duty!") + npc("I have not much to offer as reward, but for these spare robes I wore while on assignment...") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeLennissaSpoke, true) + addItemOrDrop(player, Items.GHOSTLY_ROBE_6108) + } + npc("Please find him and discover why I am cursed like this!") + player("Where would I be able to find this Dhalak then?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("subsequenttime") + player("Hello Lennissa. Can you remind me where to find Dhalak?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("curseofzaros1") + npc("Dhalak? Well, he was always a knowlegeable mage, so if this curse has befallen him as well, I would suspect he would be researching how to free himself of it.") + npc("I would look for a library to find him if I were you.") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros2") + npc("Dhalak? He was always a loyal follower of Saradomin... I think he would have found an altar to Saradomin so that he may pray for this curse to be lifted.") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros3") + npc("Dhalak? I know not where, but he would try and make the most of his situation if he has been cursed, and find a place to lift his spirits!") + player("Okay, well I'll try and find him for you then.") + + + label("lostghostlything") + player(ChatAnim.SAD, "Could I have that rob bottom again? I seem to have", "misplaced it somewhere...") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_ROBE_6108) + } + npc(ChatAnim.SAD, "Certainly, I am not sure how, but it returned to me by", "some magic or other.") + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostRennardDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostRennardDialogue.kt new file mode 100644 index 000000000..83f8383ef --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostRennardDialogue.kt @@ -0,0 +1,151 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostRennardDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostRennardDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostRennardDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2382, 2383, 2384) + } +} + +class MysteriousGhostRennardDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (2381 + getAttribute(player, CurseOfZaros.attributePathNumber, 0) == npc.id) { + if (getAttribute(player, CurseOfZaros.attributeRennardSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_GLOVES_6110) || inEquipment(player, Items.GHOSTLY_GLOVES_6110)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "wrongpath") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + CurseOfZaros.wrongPath(this) + + label("firsttime") + player("Hello. You must be Rennard.") + npc("What be this? You both see me and hear me, and also know my name?") + npc("Tell me what devilry brings you here, and be quick about it afore I gut you like a fish!") + player("Well, apart from the fact I ain't scared of no ghost, I am here because I have spoken to Valdez.") + npc("Valdez? Who be that? Some foul necromancer?") + player("No, he was a ghost I met near Glarial's tomb.") + player("He seems convinced that the artefact you stole from him is responsible for him becoming cursed to be an invisible ghost.") + player("Seems like he might be onto something too, given the state of you.") + npc("A curse ye say... Aye, that makes sense...") + npc("And there was I thinking my fate be the fault of the thieving and murdering I spent me life a-doing...") + npc("So it all began the day I stole that staff, ye say? Aye, that be a story I have never told another soul...") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Why don't you tell me what happened? I might be able to help...") + npc("Well, I was making me merry way along, having just pulled off a glorious jewellery heist from a bunch of stinking dwarves...") + player("Hey, that's no way to talk about dwarves! Some of my best friends are short!") + npc("Ah, yer misunderstand me [lad/lass], I wasn't generalising about the whole dwarf species, I had just stolen a bundle of jewels from a very specific group of dwarves who happened to have an odious stench about them!") + player("Oh. Well I guess that's okay then. Please continue.") + npc("Well, as I headed on me merry way, hoping the foul odours that lingered in me nostrils would soon pass, I see in front of me this explorer fella, all decked out in in his fine clothing, and carrying some long package") + npc("bundled in rags.") + npc("So I says to meself, 'Rennard', I says, 'Rennard, why would some fella all dressed in his finery be carrying something wrapped in dirty rags?'.") + npc("So I thinks to meself a little more, 'Rennard', I thinks, 'Rennard, maybe that fella has something valuable in there, and he covered it in dirty rags so it don't look so valuable'.") + npc("So I coshed this fella round the back of his head with me bag of jewels, picked up his package and was on me merry way afore he comes to.") + player("So what happened then?") + npc("Well, I makes me way to the closest tavern I knew of that catered to my sort of people...") + player("You mean thieves?") + npc("Right ye are, so I makes me way to the nearest friendly tavern, and unwraps the bundle to see what it had inside.") + player("The Staff of Armadyl?") + npc("Was it? Ah, I never knew that...") + npc("Anysways, I unwraps this staff, and sees it be a god- weapon; I may be just a common thief, but I recognises a weapon not made by mortal hands when I sees one.") + player("So what did you do then?") + npc("Well, I knew such a weapon would be of great value to...") + npc("Now that's funny. Can't remember his name, now. The powerful god, lived in the North-east. Took the Mahjarrat away from under Icthlarin's") + npc("control.") + npc("Anyway, I hired me a messenger to go off and let him know I had something I was prepared to sell that I thought he'd be interested in...") + npc("Now WHY can't I remember his name? Very odd that...") + player("So you sold the staff to this god you can't remember?") + npc("Well, that's the other funny thing... He never showed up, he sent some General or other instead.") + npc("Hmmm... You know... Thinking back on that, I'm getting the feeling that messenger did a little doublecross of his own, and took") + npc("me message to the wrong fella.") + player("So what was this General's name?") + npc("His name was Zamorak. I remember thinking at the time it was odd, because the fella was a mighty powerful warrior, but was never fully trusted by...") + npc("WHY can't I remember his name???") + player("So you suspect the messenger might have taken the message to the wrong person? So you think it was an accident or deliberate?") + npc("Well that I can't tell ya, but if something happened to get me cursed, it's likely the messenger would know what more than me.") + npc("His name was Kharrim, and if he caused me to be stuck like this, I'm gonna fillet him like a dog, ghost or no!") + npc("I tell ye what, you've given me much to think about so I'd like to offer yer a gift; Here, take these, they were the gloves I stole me first cake with, they might bring yer some luck.") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeRennardSpoke, true) + addItemOrDrop(player, Items.GHOSTLY_GLOVES_6110) + } + player("Where can I find this Kharrim then?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("subsequenttime") + player("Hello again Rennard.") + npc("Ah, it be you again! What can I do fer ya?") + player("Can you tell me where I can find Kharrim again?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("curseofzaros1") + npc("Kharrim the messenger... Well, he was always a devoted follower of old General Zamorak, and if I remember rightly Zamorak set up a small base in an old temple near Dareeyak...") + npc("You might want to check around there.") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros2") + npc("Kharrim the messenger... Last I'd heard of him, he'd headed off to Carrallagar to seek his fortune. Ya might want to check around there somewhere.") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros3") + npc("Kharrim the messenger... The last I'd heard of that weasel he was claiming he'd found some underground deposit of runite ore guarded by demons and dragons.") + npc("I suspect he was pulling some scam or other, but if you know of such a place, that might be a good place to start checking.") + player("Okay, well I'll try and find him for you then.") + + + label("lostghostlything") + player(ChatAnim.SAD, "I lost those gloves you gave me...", "Can I have some more please?") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_GLOVES_6110) + } + npc(ChatAnim.SAD, "It seems as though the curse that keeps me here", "extends to my very clothing...") + npc("Here, take them, some evil power returned them to", "me...") + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostValdezDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostValdezDialogue.kt new file mode 100644 index 000000000..0383402f7 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostValdezDialogue.kt @@ -0,0 +1,136 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostValdezDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostValdezDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostValdezDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2381) // wrong const SICK_LOOKING_SHEEP_4_2381 -> should be correct MYSTERIOUS_GHOST_2381 + } +} + +class MysteriousGhostValdezDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (getAttribute(player, CurseOfZaros.attributeValdezSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_ROBE_6107) || inEquipment(player, Items.GHOSTLY_ROBE_6107)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + label("firsttime") + player("Hello.") + npc(ChatAnim.EXTREMELY_SHOCKED, "H-hello!") + player(ChatAnim.THINKING, "So what's up?") + npc(ChatAnim.EXTREMELY_SHOCKED, "I cannot believe it!", "You can see me?", "You understand my words?") + player("Sure can.", "So why are you hanging around here?") + npc(ChatAnim.SAD, "My tale is one of woe...", "No doubt you will have little interest in hearing it...") + npc(ChatAnim.SAD, "Though it has been so many moons since last I had", "company in this endless non-life...") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Well, actually I would like to know what happened to you to turn you into an invisible ghost.") + player(ChatAnim.SUSPICIOUS, "If only so I can make sure it doesn't happen to me...") + npc("My name is Valdez. I served my Lord Saradomin faithfully for many years, as an explorer of this strange land we had been brought to.") + npc("I remember the day this curse fell upon me clearly... I had just discovered a huge temple, hidden below the ground, of one of Saradomin's compatriots.") + npc("I am unsure who had built it, or why they had left it seemingly abandoned, but inside I located a great treasure...") + npc("It was the godstaff of Armadyl.", "Oh, how I rue my choice that day!") + player("Choice?") + npc("Aye, stranger.", "I chose that day to take it so that my Lord Saradomin's", "power and prestige could be increased by its possession.") + npc("A god-weapon!", "Do you have any comprehension of the difficulty and", "rarity in obtaining such a thing?") + npc("To find such an artefact of power just lying around, it is almost incomprehensible...") + npc("So it was there in that deserted temple that I made my", "choice.", "I took the staff, and left that temple for Entrana", "immediately.") + npc("This was the cause of my cursed state.") + player("What, you mean you gave it to Saradomin and in return he cursed you???") + player("Seems kind of ungrateful if you ask me...") + npc("No stranger, you misunderstand completely...", "Firstly my gracious Lord would never treat anyone in", "such a manner;", "If he felt it was beyond my bounds as a mere mortal") + npc("to hold such an artefact, he would simply have commanded me to return it to whence I had claimed it, and I being eternally loyal would have obeyed without question...") + player("And secondly?") + npc("And secondly, I never managed to pass the artefact on to my Lord...") + npc("The vile thief Rennard accosted me as I made my way to Entrana, and after defeating me with a sneak attack, plundered the staff from my person, and left me for dead...") + npc("I do not know what became of the staff, but I can feel in my very bones that whatever its final fate was, it is somehow related to this curse upon me...") + player("Wow", "Tough break.") + npc("I am sorry to bore you with my tale stranger, please allow me to compound my rudeness by asking you for one favour, small to perform?") + player("Eh, I won't make any promises, but if it's nothing too annoying I guess I can help you out.") + npc("Many thanks stranger, this existence tortures me...") + npc("I need you to find Rennard and if he has the staff yet reclaim it, or find out what hideous deed he performed to curse me so!") + npc("I have nothing I may offer you save this piece of clothing, please take it as payment...") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeValdezSpoke, true) + // Set the path to follow. + setAttribute(player, CurseOfZaros.attributePathNumber, (1..3).random()) + addItemOrDrop(player, Items.GHOSTLY_ROBE_6107) + } + player("Where can I find this Rennard then?") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("subsequenttime") + npc("Thank you for hearing my tale...", "It has been so lonely here...") + player("Can you remind me where to find the thief Rennard who caused this curse to befall you again?") + npc("Of course...") + exec { player, npc -> + // 1 of 3 paths. + loadLabel(player, "curseofzaros" + getAttribute(player, CurseOfZaros.attributePathNumber, 0)) + } + + label("curseofzaros1") + npc("Ah, the infamous Rennard...", "The last I had heard of him, he had sought passage on", "a ship crewed by none but the most dastardly lowly", "pirates...") + npc("I also heard that this ship had been caught in a violent", "storm, and stranded upon rocks, where the pirates then", "made their home...") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros2") + npc("Ah, the infamous Rennard...", "The last I had heard of that vile thief, he had joined a", "group of bandits in an evil land to the North-east of", "here, where they had made their home living outside of") + npc("the reach of the authorities that pursued them...") + player("Okay, well I'll try and find him for you then.") + + label("curseofzaros3") + npc("Ah, the infamous Rennard...", "The last I had heard of that vile thief, he had joined a", "group of bandits in a barren land to the South-east of", "here, where they prey upon the unsuspecting visitors to") + npc("the desert awaiting the return of their dark master...") + player("Okay, well I'll try and find him for you then.") + + + label("lostghostlything") + player(ChatAnim.SAD, "I lost that Robe top you gave me...", "Can I have another please?") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_ROBE_6107) + } + npc(ChatAnim.SAD, "It seems as though the curse that keeps me here", "extends to my very clothing...") + npc("Here, take it, the moment you lost it, it returned to", "me...") + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostViggoraDialogue.kt b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostViggoraDialogue.kt new file mode 100644 index 000000000..d5464ee19 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/curseofzaros/MysteriousGhostViggoraDialogue.kt @@ -0,0 +1,188 @@ +package content.region.desert.quest.curseofzaros + +import core.api.* +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialogueOption +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MysteriousGhostViggoraDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return MysteriousGhostViggoraDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MysteriousGhostViggoraDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(2394, 2395, 2396) + } +} + +class MysteriousGhostViggoraDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + if (inEquipment(player, Items.GHOSTSPEAK_AMULET_552) || inEquipment(player, Items.GHOSTSPEAK_AMULET_4250)){ + if (2393 + getAttribute(player, CurseOfZaros.attributePathNumber, 0) == npc.id) { + if (getAttribute(player, CurseOfZaros.attributeViggoraSpoke, false)) { + if (inInventory(player, Items.GHOSTLY_CLOAK_6111) || inEquipment(player, Items.GHOSTLY_CLOAK_6111)) { + loadLabel(player, "subsequenttime") + } else { + loadLabel(player, "lostghostlything") + } + } else { + loadLabel(player, "firsttime") + } + } else { + loadLabel(player, "wrongpath") + } + } else { + loadLabel(player, "noghostspeak") + } + } + + CurseOfZaros.withoutGhostspeak(this) + + CurseOfZaros.wrongPath(this) + + label("firsttime") + player("So... You must be the infamous Viggora.") + npc("Hold thy tongue varlet! Speak fast, how come you to find me here, and how doth you understand mine speech?") + player("You want me to hold my tongue and tell you how I found you?") + npc("Cease thy chatter and respond to my demand!") + player("Cease my chatter AND respond to your demand?") + npc("I warn thee knave, this curse upon me hath not improved my temper, these centuries past...") + player("Well, it's actually about that curse that I have come to speak to you.") + npc("Oh, be that so? Then forgive my swift anger, and speak to me of how you plan to break this curse.") + player("Erm... I didn't actually mention anything about breaking the curse...") + npc("Then what lets you dare speak to me?") + player("Well, I heard of your name from a mage called Dhalak, and I'm trying to find out what exactly caused the curse to befall him, and you as well apparently.") + npc("Ha! So the weak-willed mage was cursed along with me?") + npc("Well now, that is an interesting turn of events... Then am I to assume that Valdez, Rennard, Kharrim and Lennissa were also cursed along with me?") + player("...How did you know that?") + npc("Ha ha ha! Oh, the curse cut deeper than I had previously thought!") + npc("Stranger, this news has brought me a ray of sunshine in an otherwise dreary millennium! Please, ask any question you wish!") + options( + DialogueOption("tellmeyourstory", "Tell me your story", skipPlayer = true), + DialogueOption("goodbye", "Goodbye then", skipPlayer = true), + ) + + label("goodbye") + player("Well, that's all fascinating, but I just don't particularly care. Bye-bye.") + + label("tellmeyourstory") + player("Erm... Thanks, I think. So what exactly happened on that day you were all cursed?") + player("I know that Valdez discovered the Staff of Armadyl, was robbed by Rennard, who then sent Kharrim to tell Zamorak of it.") + player("Meanwhile Lennissa heard of the sale, and informed Dhalak who placed an enchantment upon it so that its power would be hidden.") + player("I still don't know what happened with the staff to cause this curse, or what you had to do with it though...") + npc("Well stranger, rest yourself awhile, and I will recount a tale of the events of that day, for I was one of the few actually there when it happened...") + player("When what happened?") + npc("When my Lord Zamorak first got his taste of godhood!") + player("Wow. Sounds like quite the dinner party anecdote.") + npc("You can take the snide venom out of your voice whelp, you came to me; 'twas not the other way round.") + player("Okay, okay. Please continue.") + npc("Well now, let us see... As you may have heard tell, my affiliation lay with General Zamorak, a mighty warrior of the Mahjarrat tribe, and my skill on the battlefield had quickly brought") + npc("me to his attention.") + npc("So pleased was he with my bloodlust that he promoted me on the battlefield once to serve in his honour guard, and let me tell you, this was a rare honour indeed, for I was the only human chosen to take such a position.") + player("Really?") + npc("Oh yes, the dragon riders, Mahjarrat, demons and vampyre warriors made up the bulk of the force, but I wager I was their equal in all ways of combat.") + npc("Ha, when I think of someone like Lucien struggling to lift a blade, in some ways I was even their better!") + player("Please continue.") + npc("Well anyway... Myself and the rest of Zamoraks honour guard were formulating stratagems in our battle-tent, when that sneaky messenger Kharrim came in offering to sell us") + npc("the god-staff of Armadyl!") + npc("Naturally, we suspected that this was some trick by our Lord to test our loyalty...") + player("Yes, who was your lord? Everyone has been very evasive about that...") + npc("Quiet fool, all things in their course; You are disrupting my train of thought!") + player("Sorry...") + npc("Well anyway, we thought it was too good to be true, yet when we visited this scummy tavern we were amazed to discover there was no trick, no test of loyalty, no hidden trap:") + npc("Somehow this fool had actually managed to obtain the god-staff of Armadyl!") + npc("Its power was incredible, you could almost feel the energies crackling around it in the air!") + player("So what happened then?") + npc("Well, with such a weapon, the plans we had been developing for a rebellion against our lord could finally be put into action, but we knew that we would have to act swiftly, before he heard that we had a weapon") + npc("capable of defeating him, and we would have to act decisively, for even amongst our group there were still those loyal to the lord - such as that pathetic fool Azzanadra.") + player("So JUST WHO WAS this lord you speak of?") + npc("And I tell thee again, I will say when it is appropriate, now do not disrupt my tale!") + player("Okay, carry on then...") + npc("So anyway, Lord Zamorak and his most trusted compatriots, namely myself, Hazeel, Drakan, Thammaron and Zemouregal made plans to overthrow our lord using the god-weapon, and by pledging") + npc("allegiance to Zamorak as our master, were each to be given a large piece of land as our own in return.") + npc("We decided to move immediately, before anyone got cold feet, or any other parties could interfere in our work, and made haste towards the castle where our Lord lived.") + npc("If Lucien had not been otherwise occupied, he would have probably accompanied us with his magicks, but it turned out the foolish Dhalak had made his involvement unnecessary with some spells of his own allowing us to") + npc("get close enough to the castle with the staff without the Empty Lord being able to sense its presence.") + player("So your lord was the one that cursed you?") + npc("I am coming to that... So anyway, we made our way to the castle, under the pretense that we had war plans against Saradomin and the other deities to discuss.") + npc("As usual, our lord was guarded well, but this was why Zamorak had brought his most trusted fighters with him.") + npc("While we distracted the Empty Lord with our feints and attacks, and kept his bodyguards busy, Lord Zamorak outflanked him, unsheathed the staff and plunged it into his back!") + npc("Ah, it was a glorious sight... At that moment I was reminded for whom I fought, and why General Zamorak had earned his nickname 'the scourge' upon the battlefield...") + player("And the next thing you know you were cursed?") + npc("No, it was not quite that simple... The Empty Lord turned away from our battle, eyes burning with hatred, and towards Zamorak instead. Seeing this, we all fought with extra vigour, so that") + npc("General Zamorak would not face our lord alone, but we were outnumbered by many hundreds of warriors and demons, and could not reach him to assist him!") + player("So what then?") + npc("Why, it was the Empty Lord versus Zamorak, in single combat! And the sight of the battle will be with me forever more...") + npc("The Empty Lord was a powerful god, stronger than any of the others awake at that time, possibly even as strong as Guthix is, and Zamorak was but a mortal: A Mahjarrat warrior all the same, with all of the") + npc("strength and power that that entails, but mortal nonetheless, but to see him fight, you would not think of him as a 'mere' anything...") + npc("He was war itself! Flurry after flurry of blows he rained upon the Empty Lord, and the very castle walls shook and quivered with their power, but the Empty Lord would not fall!") + npc("Even with the weapon of a god embedded in his back, he fought on, and with each blow our victory seemed less and less certain...") + player("So what then?") + npc("Well, then a miracle happened. Or luck. Or natural justice.") + npc("You can call it what you want, but as the Empty Lords hands wrapped tightly around Zamorak's throat, Lord Zamorak, kicking and screaming defiantly and radiant in his anger until the very last, plunged towards the") + npc("Empty Lord, who seemed to lose his footing slightly, and fell in such a way so that the staff plunged deeper into his body, but also impaled Lord Zamorak with it at the same time...") + npc("And then...") + player("And then what?") + npc("And then nothing. There was a sudden flash of bright light, and then a sudden blink of cold darkness, and it was over.") + npc("Zamorak stood over the Empty Lord who was slowly... fading from existence... And as he faded, it seemed as though... It almost seemed as though Zamorak became more real,") + npc("more solid than he had been before...") + npc("And as the Empty Lord faded from this world completely, I heard his voice, almost a whisper upon the wind, cursing all who had helped Zamorak in his victory, which as you now tell me seems to have been all who") + npc("were responsible for the staff ending up in Zamorak's hands at the castle.") + npc("As I heard it, I saw that I too was fading, just as the Empty Lord had, and I called to my brethren for their assistance, but they could no longer hear my words, nor see my form.") + npc("It was then that the other gods appeared and banished Zamorak from the world completely for daring to kill one of their kind, although as it turned out it didn't quite work out that way for them, when he returned") + npc("stronger than ever, a god himself.") + npc("But the god wars were another story entirely...") + player("But... I don't understand... If it was Zamorak who used the weapon, then why was it only you who were cursed?") + player("And the other people who were cursed, why them? Why not the other Mahjarrat for example?") + player("And just who was this 'Empty Lord' you keep speaking of?") + npc("Well, in my life I was nothing but a warrior. I had no hidden knowledge, I didn't especially care about the gods or their magics, and I certainly didn't respect them.") + npc("Now in my... I suppose this is my death. I am but a shade on the wind, unnoticed by all who pass me, until today anyway, and the only answer I can give you is that the others who were with me, the") + npc("Mahjarrats and the Vampyre, they were beings of magic.") + npc("It runs through their very veins, and ebbs through their bones.") + npc("Who knows why the curse fell as it did? Perhaps as a mere human I was more susceptible to it, when they were not. Perhaps they too are cursed, but their life spans are so") + npc("long that it will be millennia before they feel it upon them. Perhaps because it did not affect them, it extended backwards through time, to the moment the staff was") + npc("taken from its rightful place, and all who had known of its theft were cursed too. Perhaps there are others also cursed, who played no part in this tale, and were merely unlucky enough to be") + npc("in the wrong place at the wrong time...") + npc("I don't know. Things do not always happen for a reason, just as tales do not always end with all of the loose ends neatly tied up and all answers supplied.") + npc("I have simply told you the events I was witness to, for I can do no more.") + npc("You have cheered me no end to let me know that this curse that has afflicted me has not left me alone here, in this void between worlds.") + exec { player, npc -> + setAttribute(player, CurseOfZaros.attributeViggoraSpoke, true) + addItemOrDrop(player, Items.GHOSTLY_CLOAK_6111) + } + npc("Perhaps I will hunt down these others who have also been cursed as I was, but I feel I must reward you for your efforts; Here, take my cloak, it is drenched in the blood of a") + npc("thousand foes, and may bring you luck in battle.") + player("So how can I break this curse?") + npc("Who knows? If it was the death curse of the Empty Lord, there may be no way to break it.") + npc("If it was not his death curse, and he is still alive but not on this world, then the only way to break it may be to bring him back here;") + npc("But I would rather stay cursed than suffer under his rule again...") + player("But WHO was this 'Empty Lord'? WHAT was his NAME?") + npc("You do not know? You have not guessed yet?") + npc("He was Zaros.") + + label("subsequenttime") + player("Hello.") + npc("Hello yourself.") + player("I really liked your little story. Can you tell me another one?") + player("Preferably something with a big fight and lots of explosions!") + npc("...You are a very strange young @g[man/woman].") + + label("lostghostlything") + player(ChatAnim.SAD, "Can I have that cloak back?") + exec { player, npc -> + addItemOrDrop(player, Items.GHOSTLY_CLOAK_6111) + } + npc("Hmph.", "I suppose.") + + } +} \ No newline at end of file From 957477b9b0249a41e01de07b0f0a300653693e66 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 16 Feb 2025 05:17:13 +0000 Subject: [PATCH 216/306] Fixed Death Plateau softlock in Dunstan dialogue Fixed Harold not accepting blurberry special Spiked boots now accessible --- .../burthorpe/dialogue/DunstanDialogue.kt | 66 +++++++++++++++++++ .../quest/deathplateau/DenulthDialogueFile.kt | 2 +- .../quest/deathplateau/DunstanDialogueFile.kt | 6 +- .../quest/deathplateau/HaroldDialogueFile.kt | 3 + .../trollstronghold/DunstanDialogueFile.kt | 40 ++++++++++- 5 files changed, 111 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt index 92a7b22c2..73759083a 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/dialogue/DunstanDialogue.kt @@ -6,9 +6,11 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.dialogue.Topic import core.game.node.entity.player.Player +import core.game.node.item.Item import core.plugin.Initializable import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import org.rs09.consts.Items import org.rs09.consts.NPCs /** @@ -28,6 +30,7 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage++ } 1 -> npcl(FacialExpression.FRIENDLY, "Hi! What can I do for you?").also { stage++ } 2 -> showTopics( + Topic(FacialExpression.THINKING, "Can you put some spikes on my Climbing boots?", 30), Topic(FacialExpression.THINKING, "Is it OK if I use your anvil?", 10), Topic(FacialExpression.FRIENDLY, "Nothing, thanks.", END_DIALOGUE), Topic(FacialExpression.FRIENDLY, "How is your son getting on?", 15), @@ -41,6 +44,37 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { 15 -> npcl(FacialExpression.FRIENDLY, "He is getting on fine! He has just been promoted to Sergeant! I'm really proud of him!").also { stage++ } 16 -> playerl(FacialExpression.FRIENDLY, "I'm happy for you!").also { stage++ } 17 -> npcl(FacialExpression.FRIENDLY, "Anything else before I get on with my work?").also { stage = 2 } + 30 -> playerl(FacialExpression.FRIENDLY, "Can you put some spikes on my Climbing boots?").also { stage++ } + 31 -> npcl(FacialExpression.NEUTRAL,"For you, no problem.").also { stage++ } + 32 -> npc(FacialExpression.THINKING, "Do you realise that you can only use the Climbing", "boots right now? The Spiked boots can only be used in", "the Icelands but no ones been able to get there for", "years!").also { stage++ } + 33 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Yes, but I still want them.", 40, true), + Topic(FacialExpression.NEUTRAL, "Oh OK, I'll leave them thanks.", 43), + ) + 40 -> { + if (inInventory(player!!, Items.CLIMBING_BOOTS_3105) && inInventory(player!!, Items.IRON_BAR_2351)) { + sendDoubleItemDialogue(player!!, Items.IRON_BAR_2351, Items.CLIMBING_BOOTS_3105, "You give Dunstan an Iron bar and the climbing boots.") + sendMessage(player!!, "You give Dunstan an Iron bar and the climbing boots.") + if (removeItem(player!!, Item(Items.CLIMBING_BOOTS_3105)) && removeItem(player!!, Item(Items.IRON_BAR_2351))) { + addItemOrDrop(player!!, Items.SPIKED_BOOTS_3107) + stage++ + } else { + stage = END_DIALOGUE + } + } else if (inInventory(player!!, Items.CLIMBING_BOOTS_3105)){ + npcl(FacialExpression.NEUTRAL,"Sorry, I'll need an iron bar to make the spikes.") + stage = 2 + } else { + playerl(FacialExpression.NEUTRAL,"I don't have them on me.") + stage = 2 + } + } + 41 -> sendItemDialogue(player!!, Items.SPIKED_BOOTS_3107, "Dunstan has given you the spiked boots.").also { stage++ + sendMessage(player!!, "Dunstan has given you the spiked boots.") + } + 43 -> npcl(FacialExpression.FRIENDLY, "Anything else before I get on with my work?").also { + stage = 2 + } } return true } @@ -57,6 +91,7 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Hi!").also { stage++ } 1 -> npcl(FacialExpression.FRIENDLY, "Hi! What can I do for you?").also { stage++ } 2 -> showTopics( + Topic(FacialExpression.THINKING, "Can you put some spikes on my Climbing boots?", 30), Topic(FacialExpression.THINKING, "Is it OK if I use your anvil?", 10), Topic(FacialExpression.FRIENDLY, "Nothing, thanks.", END_DIALOGUE), Topic(FacialExpression.FRIENDLY, "How is your son getting on?", 15), @@ -69,6 +104,37 @@ class DunstanDialogue(player: Player? = null) : DialoguePlugin(player) { 15 -> npcl(FacialExpression.SAD, "He was captured by those cursed trolls! I don't know what to do. Even the imperial guard are too afraid to go rescue him.").also { stage++ } 16 -> playerl(FacialExpression.ASKING, "What happened?").also { stage++ } 17 -> npcl(FacialExpression.SAD, "Talk to Denulth, he can tell you all about it. Anything else before I get on with my work?").also { stage = 2 } + 30 -> npcl(FacialExpression.NEUTRAL,"For you, no problem.").also { stage++ } + 31 -> npc(FacialExpression.THINKING, "Do you realise that you can only use the Climbing", "boots right now? The Spiked boots can only be used in", "the Icelands but no ones been able to get there for", "years!").also { stage++ } + 32 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Yes, but I still want them.", 40, true), + Topic(FacialExpression.NEUTRAL, "Oh OK, I'll leave them thanks.", 43), + ) + 40 -> { + if (inInventory(player!!, Items.CLIMBING_BOOTS_3105) && inInventory(player!!, Items.IRON_BAR_2351)) { + sendDoubleItemDialogue(player!!, Items.IRON_BAR_2351, Items.CLIMBING_BOOTS_3105, "You give Dunstan an Iron bar and the climbing boots.") + sendMessage(player!!, "You give Dunstan an Iron bar and the climbing boots.") + if (removeItem(player!!, Item(Items.CLIMBING_BOOTS_3105)) && removeItem(player!!, Item(Items.IRON_BAR_2351))) { + addItemOrDrop(player!!, Items.SPIKED_BOOTS_3107) + stage++ + } else { + stage = END_DIALOGUE + } + } else if (inInventory(player!!, Items.CLIMBING_BOOTS_3105)){ + npcl(FacialExpression.NEUTRAL,"Sorry, I'll need an iron bar to make the spikes.") + stage = 2 + } else { + playerl(FacialExpression.NEUTRAL,"I don't have them on me.") + stage = 2 + } + } + 41 -> sendItemDialogue(player!!, Items.SPIKED_BOOTS_3107, "Dunstan has given you the spiked boots.").also { + stage = 43 + sendMessage(player!!, "Dunstan has given you the spiked boots.") + } + 43 -> npcl(FacialExpression.FRIENDLY, "Anything else before I get on with my work?").also { + stage = 2 + } } return true } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt index 415a29109..2046cf51a 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DenulthDialogueFile.kt @@ -154,7 +154,7 @@ class DenulthDialogueFile : DialogueFile() { stage = 8 } } - 7 -> playerl(FacialExpression.FRIENDLY, "I have opened the door but I don't have the combination on me.").also { stage++ } + 7 -> playerl(FacialExpression.FRIENDLY, "I have opened the door but I don't have the combination on me.").also { stage = END_DIALOGUE } 8 -> playerl(FacialExpression.FRIENDLY, "Yes! The door is open and here is the combination.").also { stage++ } 9 -> sendItemDialogue(player!!, Items.COMBINATION_3102, "You give Denulth the combination to the equipment room.").also { if (removeItem(player!!, Item(Items.COMBINATION_3102))) { diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt index 616635575..6cf2eabf4 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/DunstanDialogueFile.kt @@ -83,15 +83,17 @@ class DunstanDialogueFile : DialogueFile() { 4 -> playerl(FacialExpression.FRIENDLY, "I don't have the climbing boots.").also { stage = END_DIALOGUE } 5 -> playerl(FacialExpression.FRIENDLY, "I don't have the iron bar or the climbing boots.").also { stage = END_DIALOGUE } - 7 -> sendDoubleItemDialogue(player!!, Items.IRON_BAR_2351, Items.CLIMBING_BOOTS_3105, "You give Dunstan an iron bar and the climbing boots.").also { + 7 -> sendDoubleItemDialogue(player!!, Items.IRON_BAR_2351, Items.CLIMBING_BOOTS_3105, "You give Dunstan an Iron bar and the climbing boots.").also { + sendMessage(player!!, "You give Dunstan an Iron bar and the climbing boots.") if (removeItem(player!!, Item(Items.CLIMBING_BOOTS_3105)) && removeItem(player!!, Item(Items.IRON_BAR_2351))) { + addItemOrDrop(player!!, Items.SPIKED_BOOTS_3107) stage++ } else { stage = END_DIALOGUE } } 8 -> sendItemDialogue(player!!, Items.SPIKED_BOOTS_3107, "Dunstan has given you the spiked boots.").also { stage++ - addItemOrDrop(player!!, Items.SPIKED_BOOTS_3107) + sendMessage(player!!, "Dunstan has given you the spiked boots.") } 9 -> playerl(FacialExpression.FRIENDLY, "Thank you!").also { stage++ } 10 -> npcl(FacialExpression.FRIENDLY, "No problem.").also { diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt index 50739d72a..005206e10 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt @@ -112,6 +112,9 @@ class HaroldDialogueFile : DialogueFile() { if (removeItem(player!!, Items.BLURBERRY_SPECIAL_2064)) { sendMessage(player!!, "You give Harold a Blurberry Special.") sendItemDialogue(player!!, Items.BLURBERRY_SPECIAL_2064, "You give Harold a Blurberry Special.").also { stage++ } + } else if (removeItem(player!!, Items.BLURBERRY_SPECIAL_9520)) { // This should not be here since 9520 is used by the gnome restaurant minigame. + sendMessage(player!!, "You give Harold a Blurberry Special.") + sendItemDialogue(player!!, Items.BLURBERRY_SPECIAL_2064, "You give Harold a Blurberry Special.").also { stage++ } } else if (removeItem(player!!, Items.PREMADE_BLURB_SP_2028)) { sendMessage(player!!, "You give Harold a Blurberry Special.") sendItemDialogue(player!!, Items.PREMADE_BLURB_SP_2028, "You give Harold a Blurberry Special.").also { stage++ } diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt index 0719be236..4cd3a3f1a 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/trollstronghold/DunstanDialogueFile.kt @@ -1,13 +1,14 @@ package content.region.asgarnia.burthorpe.quest.trollstronghold import content.data.Quests -import core.api.finishQuest -import core.api.getQuestStage +import core.api.* import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.dialogue.Topic +import core.game.node.item.Item import core.tools.END_DIALOGUE import core.tools.START_DIALOGUE +import org.rs09.consts.Items class DunstanDialogueFile : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { @@ -18,14 +19,47 @@ class DunstanDialogueFile : DialogueFile() { 1 -> playerl(FacialExpression.FRIENDLY, "Not yet.").also { stage++ } 2 -> npcl(FacialExpression.FRIENDLY, "Please hurry! Who knows what they will do to him? Is there anything I can do in the meantime?").also { stage++ } 3 -> showTopics( + Topic(FacialExpression.THINKING, "Can you put some spikes on my Climbing boots?", 30), Topic(FacialExpression.THINKING, "Is it OK if I use your anvil?", 10), - Topic(FacialExpression.FRIENDLY, "Nothing, thanks.", END_DIALOGUE), + Topic(FacialExpression.NEUTRAL, "Nothing, thanks.", 20), ) 10 -> npcl(FacialExpression.FRIENDLY, "So you're a smithy are you?").also { stage++ } 11 -> playerl(FacialExpression.FRIENDLY, "I dabble.").also { stage++ } 12 -> npcl(FacialExpression.FRIENDLY, "A fellow smith is welcome to use my anvil!").also { stage++ } 13 -> playerl(FacialExpression.FRIENDLY, "Thanks!").also { stage++ } 14 -> npcl(FacialExpression.FRIENDLY, "Anything else before I get on with my work?").also { stage = 3 } + 20 -> npcl(FacialExpression.NEUTRAL, "All right. Speak to you later then.").also { stage = END_DIALOGUE } + 30 -> playerl("Can you put some spikes on my Climbing boots?").also { stage++ } + 31 -> npcl("For you, no problem.").also { stage++ } + 32 -> npc("Do you realise that you can only use the Climbing", "boots right now? The Spiked boots can only be used in", "the Icelands but no ones been able to get there for", "years!").also { stage++ } + 33 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Yes, but I still want them.", 40, true), + Topic(FacialExpression.NEUTRAL, "Oh OK, I'll leave them thanks.", 43), + ) + 40 -> { + if (inInventory(player!!, Items.CLIMBING_BOOTS_3105) && inInventory(player!!, Items.IRON_BAR_2351)) { + sendDoubleItemDialogue(player!!, Items.IRON_BAR_2351, Items.CLIMBING_BOOTS_3105, "You give Dunstan an Iron bar and the climbing boots.") + sendMessage(player!!, "You give Dunstan an Iron bar and the climbing boots.") + if (removeItem(player!!, Item(Items.CLIMBING_BOOTS_3105)) && removeItem(player!!, Item(Items.IRON_BAR_2351))) { + addItemOrDrop(player!!, Items.SPIKED_BOOTS_3107) + stage++ + } else { + stage = END_DIALOGUE + } + } else if (inInventory(player!!, Items.CLIMBING_BOOTS_3105)){ + npcl("Sorry, I'll need an iron bar to make the spikes.") + stage = 3 + } else { + playerl("I don't have them on me.") + stage = 3 + } + } + 41 -> sendItemDialogue(player!!, Items.SPIKED_BOOTS_3107, "Dunstan has given you the spiked boots.").also { stage++ + sendMessage(player!!, "Dunstan has given you the spiked boots.") + } + 43 -> npcl(FacialExpression.FRIENDLY, "Anything else before I get on with my work?").also { + stage = 3 + } } } 11 -> { From a6eb706358ec3dba123236f21e162a0bb2943cb7 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 05:20:14 +0000 Subject: [PATCH 217/306] Corrected many examine texts --- Server/data/configs/item_configs.json | 78 +++++++++++++-------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index d43d541e9..7dbd04fbf 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -5719,7 +5719,7 @@ }, { "shop_price": "35", - "examine": "Allows you to rest in the luxurious Paramayer[sic] Inn.", + "examine": "Allows you to rest in the luxurious Paramayer Inn.", "durability": null, "name": "Paramaya ticket", "archery_ticket_price": "0", @@ -5727,7 +5727,7 @@ }, { "shop_price": "35", - "examine": "Allows you to rest in the luxurious Paramayer[sic] Inn.", + "examine": "Allows you to rest in the luxurious Paramayer Inn.", "durability": null, "name": "Paramaya ticket", "archery_ticket_price": "0", @@ -33982,7 +33982,7 @@ { "requirements": "{1,40}", "ge_buy_limit": "2", - "examine": "Rune platebody with complete gold trim & plating.", + "examine": "Rune platebody with complete gold trim & plating.", "durability": null, "weight": "10", "absorb": "3,0,6", @@ -48987,7 +48987,7 @@ "id": "5419" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There is one potato in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(1)", @@ -49004,7 +49004,7 @@ "id": "5421" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are two potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(2)", @@ -49021,7 +49021,7 @@ "id": "5423" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are three potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(3)", @@ -49038,7 +49038,7 @@ "id": "5425" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are four potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(4)", @@ -49055,7 +49055,7 @@ "id": "5427" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are five potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(5)", @@ -49072,7 +49072,7 @@ "id": "5429" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are six potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(6)", @@ -49089,7 +49089,7 @@ "id": "5431" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are seven potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(7)", @@ -49106,7 +49106,7 @@ "id": "5433" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are eight potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(8)", @@ -49123,7 +49123,7 @@ "id": "5435" }, { - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are nine potatoes in this sack.", "grand_exchange_price": "1276", "durability": null, "name": "Potatoes(9)", @@ -49141,7 +49141,7 @@ }, { "ge_buy_limit": "1000", - "examine": "There are <number of potatoes> in this sack.", + "examine": "There are ten potatoes in this sack.", "grand_exchange_price": "1052", "durability": null, "name": "Potatoes(10)", @@ -49333,7 +49333,7 @@ "id": "5459" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There is one cabbage in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(1)", @@ -49349,7 +49349,7 @@ "id": "5461" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are two cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(2)", @@ -49365,7 +49365,7 @@ "id": "5463" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are three cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(3)", @@ -49381,7 +49381,7 @@ "id": "5465" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are four cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(4)", @@ -49397,7 +49397,7 @@ "id": "5467" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are five cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(5)", @@ -49413,7 +49413,7 @@ "id": "5469" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are six cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(6)", @@ -49429,7 +49429,7 @@ "id": "5471" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are seven cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(7)", @@ -49445,7 +49445,7 @@ "id": "5473" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are eight cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(8)", @@ -49461,7 +49461,7 @@ "id": "5475" }, { - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are nine cabbages in this sack.", "grand_exchange_price": "1304", "durability": null, "name": "Cabbages(9)", @@ -49478,7 +49478,7 @@ }, { "ge_buy_limit": "1000", - "examine": "There are <number of cabbages> in this sack.", + "examine": "There are ten cabbages in this sack.", "grand_exchange_price": "917", "durability": null, "name": "Cabbages(10)", @@ -58309,7 +58309,7 @@ { "shop_price": "150", "ge_buy_limit": "100", - "examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.", + "examine": "A brown armband, as worn by the Tai Bwo Wannai locals.", "grand_exchange_price": "734", "durability": null, "name": "Villager armband", @@ -58442,7 +58442,7 @@ { "shop_price": "150", "ge_buy_limit": "100", - "examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.", + "examine": "A blue armband, as worn by the Tai Bwo Wannai locals.", "grand_exchange_price": "672", "durability": null, "name": "Villager armband", @@ -58553,7 +58553,7 @@ { "shop_price": "150", "ge_buy_limit": "100", - "examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.", + "examine": "A yellow armband, as worn by the Tai Bwo Wannai locals.", "grand_exchange_price": "823", "durability": null, "name": "Villager armband", @@ -58664,7 +58664,7 @@ { "shop_price": "150", "ge_buy_limit": "100", - "examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.", + "examine": "A pink armband, as worn by the Tai Bwo Wannai locals.", "grand_exchange_price": "1697", "durability": null, "name": "Villager armband", @@ -59764,7 +59764,7 @@ }, { "destroy_message": "You will not get a replacement for the present. Open it for your reward.", - "examine": "Thanks for all your help! Love, Bob & Neite.", + "examine": "Thanks for all your help! Love, Bob & Neite.", "durability": null, "name": "Present", "tradeable": "false", @@ -93158,7 +93158,7 @@ }, { "requirements": "{1,40}", - "examine": "Rune platebody with complete gold trim & plating.", + "examine": "Rune platebody with complete gold trim & plating.", "durability": null, "weight": "10", "absorb": "3,0,6", @@ -105245,28 +105245,28 @@ "id": "12196" }, { - "examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.", + "examine": "A hatchling green dragon.", "durability": null, "name": "Dragon hatchling", "archery_ticket_price": "0", "id": "12197" }, { - "examine": "Baby: Little NipperAdult: Bigger Nipper.", + "examine": "Little Nipper.", "durability": null, "name": "Baby giant crab", "archery_ticket_price": "0", "id": "12198" }, { - "examine": "(Baby) A stripy little baby raccoon.(Adult) He can run with us.", + "examine": "A stripy little baby raccoon.", "durability": null, "name": "Baby raccoon", "archery_ticket_price": "0", "id": "12199" }, { - "examine": "Adult: An experienced nut-thief.Baby: A tiny nut-thief.", + "examine": "An experienced nut-thief.", "durability": null, "name": "Squirrel", "archery_ticket_price": "0", @@ -106499,28 +106499,28 @@ "id": "12468" }, { - "examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.", + "examine": "A hatchling red dragon.", "durability": null, - "name": "Hatchling dragon", + "name": "Dragon hatchling", "archery_ticket_price": "0", "id": "12469" }, { - "examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.", + "examine": "A hatchling blue dragon.", "durability": null, "name": "Hatchling dragon", "archery_ticket_price": "0", "id": "12471" }, { - "examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.", + "examine": "A hatchling green dragon.", "durability": null, "name": "Hatchling dragon", "archery_ticket_price": "0", "id": "12473" }, { - "examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.", + "examine": "A hatchling black dragon.", "durability": null, "name": "Hatchling dragon", "archery_ticket_price": "0", @@ -122125,7 +122125,7 @@ { "lendable": "true", "destroy_message": "Drop", - "examine": "Rune platebody with complete gold trim & plating.", + "examine": "Rune platebody with complete gold trim & plating.", "grand_exchange_price": "2034838", "durability": null, "name": "Gilded platebody", From 1afd4d532819667b5de37999991726b244e5dcca Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 05:22:36 +0000 Subject: [PATCH 218/306] Fixed bug preventing The Fremennik Trials lyre concert being marked as completed --- .../TFTInteractionListeners.kt | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt index d65bbe126..7bd87557a 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt @@ -22,6 +22,7 @@ import core.game.interaction.IntType import core.game.system.config.ItemConfigParser import core.game.world.GameWorld.Pulser import content.data.Quests +import core.game.interaction.QueueStrength class TFTInteractionListeners : InteractionListener { @@ -155,7 +156,7 @@ class TFTInteractionListeners : InteractionListener { sendNPCDialogue(player,1278,"Yeah you're good to go through. Olaf tells me you're some kind of outerlander bard here on tour. I doubt you're worse than Olaf is.") core.game.global.action.DoorActionHandler.handleAutowalkDoor(player,door.asScenery()) } - getAttribute(player,"lyreConcertPlayed",false) -> { + getAttribute(player,"lyreConcertPlayed",false) || isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS) -> { core.game.global.action.DoorActionHandler.handleAutowalkDoor(player,door.asScenery()) } else -> { @@ -167,7 +168,7 @@ class TFTInteractionListeners : InteractionListener { on(LYRE_IDs, IntType.ITEM, "play"){ player, lyre -> if(getAttribute(player,"onStage",false) && !getAttribute(player,"lyreConcertPlayed",false)){ - Pulser.submit(LyreConcertPulse(player,lyre.id)) + playLyreConcert(player, lyre.id) } else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) < 20 || !isQuestComplete(player, Quests.THE_FREMENNIK_TRIALS)){ sendMessage(player,"You lack the knowledge to play this.") } else if(LYRE_IDs.isLast(lyre.id)){ @@ -353,7 +354,7 @@ class TFTInteractionListeners : InteractionListener { } } - class LyreConcertPulse(val player: Player, val Lyre: Int) : Pulse(){ + fun playLyreConcert(player: Player, lyre: Int) { val GENERIC_LYRICS = arrayOf( "${player.username?.capitalize()} is my name,", "I haven't much to say", @@ -378,7 +379,6 @@ class TFTInteractionListeners : InteractionListener { "I will simply tell you this:", "I've joined the Legends' Guild!" ) - var counter = 0 val questPoints = getQuestPoints(player) val champGuild = player.achievementDiaryManager?.hasCompletedTask(DiaryType.VARROCK, 1, 1)?: false val legGuild = questPoints >= 111 @@ -401,15 +401,17 @@ class TFTInteractionListeners : InteractionListener { else -> GENERIC_LYRICS } - override fun pulse(): Boolean { - when(counter++){ + queueScript(player, 0, QueueStrength.SOFT) { stage -> + when (stage) { 0 -> { player.lock() animate(player,1318,true) + return@queueScript delayScript(player, 1) } 2 -> { animate(player,1320,true) player.musicPlayer.play(MusicEntry.forId(165)) + return@queueScript delayScript(player, 1) } 4 -> { animate(player,1320,true) @@ -433,13 +435,15 @@ class TFTInteractionListeners : InteractionListener { } 14 ->{ setAttribute(player,"/save:lyreConcertPlayed",true) - player.removeAttribute("LyreEnchanted") - if(removeItem(player,Lyre)) - addItem(player,Items.ENCHANTED_LYRE_3690) + removeAttribute(player, "/save:LyreEnchanted") + if (removeItem(player,lyre)) { + addItem(player, Items.ENCHANTED_LYRE_3690) + } player.unlock() + return@queueScript stopExecuting(player) } } - return false + return@queueScript delayScript(player, 1) } } From fed309a70b3feded529bd9c8b901f50956173491 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 16 Feb 2025 05:28:53 +0000 Subject: [PATCH 219/306] Fixed map areas that caused client crashes in HD --- Server/data/cache/main_file_cache.dat2 | 4 ++-- Server/data/cache/main_file_cache.idx255 | 2 +- Server/data/cache/main_file_cache.idx5 | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/data/cache/main_file_cache.dat2 b/Server/data/cache/main_file_cache.dat2 index 376fd9153..245fa6081 100644 --- a/Server/data/cache/main_file_cache.dat2 +++ b/Server/data/cache/main_file_cache.dat2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6b92de1ed8601bc3961de4466e961cffe5777887cb87c7ffed1d466a3d08491 -size 91621090 +oid sha256:b5431211b019b9403b4cfca933f4c9635c1d5278d3730995dced0d8672b1cc91 +size 91702293 diff --git a/Server/data/cache/main_file_cache.idx255 b/Server/data/cache/main_file_cache.idx255 index a437d6da5..6e504259a 100644 --- a/Server/data/cache/main_file_cache.idx255 +++ b/Server/data/cache/main_file_cache.idx255 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86269328a9c606c683569c2d9ea200a391e08c04c1591071aaed9a36978b744b +oid sha256:83a2292c515596af0423764c48e41dfe1aac482920dca0b89ecb343db6dd4c30 size 174 diff --git a/Server/data/cache/main_file_cache.idx5 b/Server/data/cache/main_file_cache.idx5 index dad8dfec7..f19fd00c7 100644 --- a/Server/data/cache/main_file_cache.idx5 +++ b/Server/data/cache/main_file_cache.idx5 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ef6807f6653e09be9b6e2299055f1132c34dc6108e8b92fbae5add2233c2d64 -size 22092 +oid sha256:32bda84b31731cd60f7bc4e90caf7d55671e966fa958d60f2ec91da16340743d +size 22188 From bb860b60e040fd884bd5f04471e78323846eb13a Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 05:32:57 +0000 Subject: [PATCH 220/306] Pest control XP formula is now authentic, includes 1% XP bonus if handing in 10 points or more and 10% XP bonus if handing in 100 points or more --- .../pestcontrol/reward/PCRewardInterface.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java b/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java index 9dc6aab16..9140bfda2 100644 --- a/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java +++ b/Server/src/main/content/minigame/pestcontrol/reward/PCRewardInterface.java @@ -15,6 +15,8 @@ import core.game.node.item.Item; import core.plugin.Plugin; import core.tools.RandomFunction; +import static core.api.ContentAPIKt.getStatLevel; + /** * Represents the pest control reward interface. * @author 'Vexia @@ -185,20 +187,36 @@ public final class PCRewardInterface extends ComponentPlugin { } /** - * Method used to calculate the experience the player can recieve in this - * skill. + * Method used to calculate the experience the player can receive in this skill. * @param player the player. * @return the experience as an integer. */ - public static double calculateExperience(final Player player, final int skillId) { - int level = player.getSkills().getStaticLevel(skillId); - double divideBy = 30;//17.5-33 ideal range - if (skillId == Skills.PRAYER) { - divideBy = 67;// 34-75 ideal range - } else if (skillId == Skills.MAGIC || skillId == Skills.RANGE) { - divideBy = 29;//19.1-31 ideal range + public static int calculateExperience(final Player player, final int skillId, final int points) { + int level = getStatLevel(player, skillId); + int N = 0; + switch (skillId) { + case Skills.PRAYER: + N = 18; + break; + case Skills.MAGIC: + case Skills.RANGE: + N = 32; + break; + case Skills.ATTACK: + case Skills.STRENGTH: + case Skills.DEFENCE: + case Skills.HITPOINTS: + N = 35; + break; } - return (int) ((level * level) / divideBy) * (player.getSkills().experienceMultiplier / 2); + int xpPerPoint = (int) ((double) (level * level) / 600) * N; + double bonus = 1.0; + if (points >= 100) { + bonus = 1.1; + } else if (points >= 10) { + bonus = 1.01; + } + return (int) (points * xpPerPoint * bonus); } /** @@ -207,7 +225,7 @@ public final class PCRewardInterface extends ComponentPlugin { * @param skillId the skillId. * @return the string to send. */ - public static final String getSkillCondition(final Player player, final int skillId) { + public static String getSkillCondition(final Player player, final int skillId) { if (player.getSkills().getStaticLevel(skillId) < 25) { return RED + "Must reach level 25 first."; } @@ -221,7 +239,7 @@ public final class PCRewardInterface extends ComponentPlugin { * @return the string. */ public static String getSkillXp(final Player player, int skillId) { - return Skills.SKILL_NAME[skillId] + " - " + (int) calculateExperience(player, skillId) + " xp"; + return Skills.SKILL_NAME[skillId] + " - " + calculateExperience(player, skillId, 1) + " xp"; } /** @@ -229,7 +247,7 @@ public final class PCRewardInterface extends ComponentPlugin { * @param skill the skill index. * @return the skill child id. */ - public static final int getSkillChild(final int skill) { + public static int getSkillChild(final int skill) { return SKILL_HEADER[skill]; } @@ -264,7 +282,7 @@ public final class PCRewardInterface extends ComponentPlugin { * Method used to confirm the reward. * @param player the player. */ - public final void confirm(final Player player) { + public void confirm(final Player player) { if (!hasReward(player)) { player.getPacketDispatch().sendMessage("Please choose a reward."); return; @@ -281,9 +299,9 @@ public final class PCRewardInterface extends ComponentPlugin { if (player.getSavedData().getActivityData().getPestPoints() >= points) { player.getSavedData().getActivityData().decreasePestPoints(points); if (reward.isSkillReward()) { - final double experience = ((int) calculateExperience(player, reward.getSkill()) * points); + int experience = calculateExperience(player, reward.getSkill(), points); player.getSkills().addExperience(reward.getSkill(), experience); - message = "The Void Knight has granted you " + (int) (experience * player.getSkills().experienceMultiplier) + " " + reward.getName() + "."; + message = "The Void Knight has granted you " + experience + " " + reward.getName() + "."; } else { if (!reward.checkItemRequirement(player, option)) { return; From be47c1d5c97ca9fafa5a970506a61af77c98b2c0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 05:35:27 +0000 Subject: [PATCH 221/306] Added cats raised to ::stats Added food cooked to ::stats --- .../skill/cooking/StandardCookingPulse.java | 14 +++++++++++- .../skill/fletching/FletchingPulse.java | 2 +- .../fletching/items/bow/StringPulse.java | 15 +++++++++++-- .../global/skill/summoning/pet/Pet.java | 3 +++ .../global/skill/summoning/pet/Pets.java | 22 ++++++++++++++++++- .../system/command/sets/StatAttributeKeys.kt | 2 ++ .../system/command/sets/StatsCommandSet.kt | 2 ++ 7 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java b/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java index c7998375a..d70856a27 100644 --- a/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java +++ b/Server/src/main/content/global/skill/cooking/StandardCookingPulse.java @@ -4,6 +4,8 @@ import content.global.skill.skillcapeperks.SkillcapePerks; import core.game.event.ResourceProducedEvent; import core.game.node.entity.impl.Animator; import core.game.node.entity.player.Player; +import core.game.node.entity.player.info.LogType; +import core.game.node.entity.player.info.PlayerMonitor; import core.game.node.entity.player.link.audio.Audio; import core.game.node.entity.skill.Skills; import core.game.node.item.GroundItemManager; @@ -15,7 +17,7 @@ import core.tools.RandomFunction; import org.rs09.consts.Items; import org.rs09.consts.Sounds; -import static core.api.ContentAPIKt.playAudio; +import static core.api.ContentAPIKt.*; import content.data.Quests; public class StandardCookingPulse extends Pulse { @@ -39,12 +41,17 @@ public class StandardCookingPulse extends Pulse { private boolean burned = false; public CookableItems properties; + private int initialAmount; + private int processedAmount; + public StandardCookingPulse(Player player, Scenery object, int initial, int product, int amount) { this.player = player; this.object = object; this.initial = initial; this.product = product; this.amount = amount; + this.initialAmount = amountInInventory(player, initial); + this.processedAmount = 0; } @Override @@ -170,6 +177,11 @@ public class StandardCookingPulse extends Pulse { player.getInventory().add(productItem); player.dispatch(new ResourceProducedEvent(productItem.getId(), 1, object, initialItem.getId())); player.getSkills().addExperience(Skills.COOKING, experience, true); + processedAmount++; + if (processedAmount > initialAmount) { + PlayerMonitor.log(player, LogType.DUPE_ALERT, "cooked item (" + player.getName() + ", " + initialItem.getName() + "): initialAmount " + initialAmount + ", processedAmount " + processedAmount); + } + player.incrementAttribute("/save:stats_manager:food_cooked", 1); } else { player.dispatch(new ResourceProducedEvent(CookableItems.getBurnt(initial).getId(), 1, object, initialItem.getId())); player.getInventory().add(CookableItems.getBurnt(initial)); diff --git a/Server/src/main/content/global/skill/fletching/FletchingPulse.java b/Server/src/main/content/global/skill/fletching/FletchingPulse.java index 218601b97..8ef3214d8 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingPulse.java +++ b/Server/src/main/content/global/skill/fletching/FletchingPulse.java @@ -85,7 +85,7 @@ public final class FletchingPulse extends SkillPulse { if ( fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT ) { item.setAmount(RandomFunction.random(3,6)); } - player.getInventory().add(item); + player.getInventory().add(item); player.getSkills().addExperience(Skills.FLETCHING, fletch.experience, true); String message = getMessage(); player.getPacketDispatch().sendMessage(message); diff --git a/Server/src/main/content/global/skill/fletching/items/bow/StringPulse.java b/Server/src/main/content/global/skill/fletching/items/bow/StringPulse.java index fd1b2c560..0d8645e44 100644 --- a/Server/src/main/content/global/skill/fletching/items/bow/StringPulse.java +++ b/Server/src/main/content/global/skill/fletching/items/bow/StringPulse.java @@ -1,7 +1,7 @@ package content.global.skill.fletching.items.bow; -import core.api.Container; -import core.api.ContentAPIKt; +import core.game.node.entity.player.info.LogType; +import core.game.node.entity.player.info.PlayerMonitor; import core.game.node.entity.player.link.diary.DiaryType; import core.game.world.map.zone.ZoneBorders; import core.game.node.entity.skill.SkillPulse; @@ -10,6 +10,8 @@ import content.global.skill.fletching.Fletching; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import static core.api.ContentAPIKt.amountInInventory; + /** * Represents the skill pulse of stringing. * @@ -27,6 +29,9 @@ public class StringPulse extends SkillPulse { */ private int amount; + private int initialAmount; + private int processedAmount; + /** * Constructs a new {@code StringbowPlugin.java} {@code Object}. * @@ -37,6 +42,8 @@ public class StringPulse extends SkillPulse { super(player, node); this.bow = bow; this.amount = amount; + this.initialAmount = amountInInventory(player, node.getId()); + this.processedAmount = 0; } @Override @@ -70,6 +77,10 @@ public class StringPulse extends SkillPulse { player.getInventory().add(new Item(bow.product)); player.getSkills().addExperience(Skills.FLETCHING, bow.experience, true); player.getPacketDispatch().sendMessage("You add a string to the bow."); + processedAmount++; + if (processedAmount > initialAmount) { + PlayerMonitor.log(player, LogType.DUPE_ALERT, "fletched item (" + player.getName() + ", " + bow.unfinished + "): initialAmount " + initialAmount + ", processedAmount " + processedAmount); + } if (bow == Fletching.String.MAGIC_SHORTBOW && (new ZoneBorders(2721, 3489, 2724, 3493, 0).insideBorder(player) diff --git a/Server/src/main/content/global/skill/summoning/pet/Pet.java b/Server/src/main/content/global/skill/summoning/pet/Pet.java index 439504c49..bb83f16d4 100644 --- a/Server/src/main/content/global/skill/summoning/pet/Pet.java +++ b/Server/src/main/content/global/skill/summoning/pet/Pet.java @@ -126,6 +126,9 @@ public final class Pet extends Familiar { // then this pet is already overgrown return; } + if (pet.isKitten(itemId)) { + owner.incrementAttribute("/save:stats_manager:cats_raised"); + } owner.getFamiliarManager().removeDetails(getItemId()); owner.getFamiliarManager().addDetails(newItemId, details); owner.getFamiliarManager().morphPet(new Item(newItemId), false, location, details.getHunger(), 0); diff --git a/Server/src/main/content/global/skill/summoning/pet/Pets.java b/Server/src/main/content/global/skill/summoning/pet/Pets.java index 75001becd..263d04aef 100644 --- a/Server/src/main/content/global/skill/summoning/pet/Pets.java +++ b/Server/src/main/content/global/skill/summoning/pet/Pets.java @@ -18,7 +18,7 @@ public enum Pets { /** * A cat/kitten pet. */ - CAT(1555, 1561, 1567, 761, 768, 774, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_1(1556, 1562, 1568, 762, 769, 775, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_2(1557, 1563, 1569, 763, 770, 776, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_3(1558, 1564, 1570, 764, 771, 777, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_4(1559, 1565, 1571, 765, 772, 778, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_5(1560, 1566, 1572, 766, 773, 779, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), HELLCAT(7583, 7582, 7581, 3505, 3504, 3503, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_7(14089, 14090, 15092, 8217, 8214, 8216, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), + CAT(1555, 1561, 1567, 761, 768, 774, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_1(1556, 1562, 1568, 762, 769, 775, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_2(1557, 1563, 1569, 763, 770, 776, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_3(1558, 1564, 1570, 764, 771, 777, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_4(1559, 1565, 1571, 765, 772, 778, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_5(1560, 1566, 1572, 766, 773, 779, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), HELLCAT(7583, 7582, 7581, 3505, 3504, 3503, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), CAT_6(14089, 14090, 15092, 8217, 8214, 8216, 0.0154320987654321, 0, 321, 319, 363, 365, 341, 339, 15264, 345, 347, 377, 379, 353, 355, 389, 391, 7944, 7946, 349, 351, 331, 329, 327, 325, 395, 397, 383, 385, 317, 315, 371, 373, 335, 333, 359, 361, 15264, 15270, 1927), /** * A clockwork cat. @@ -426,4 +426,24 @@ public enum Pets { } return -1; } + + /** + * Checks if this pet is a kitten + * @return a boolean, true if the pet is a kitten + */ + public boolean isKitten(int id) { + switch (this) { + case CAT: + case CAT_1: + case CAT_2: + case CAT_3: + case CAT_4: + case CAT_5: + case CAT_6: + case HELLCAT: + return id == babyItemId; + default: + return false; + } + } } diff --git a/Server/src/main/core/game/system/command/sets/StatAttributeKeys.kt b/Server/src/main/core/game/system/command/sets/StatAttributeKeys.kt index f39d94ee6..431cb84be 100644 --- a/Server/src/main/core/game/system/command/sets/StatAttributeKeys.kt +++ b/Server/src/main/core/game/system/command/sets/StatAttributeKeys.kt @@ -7,6 +7,8 @@ const val STATS_LOGS = "logs_chopped" const val STATS_FISH = "fish_caught" const val STATS_ROCKS = "rocks_mined" const val STATS_RC = "essence_crafted" +const val STATS_FOOD_COOKED = "food_cooked" +const val STATS_CATS_RAISED = "cats_raised" const val STATS_PK_KILLS = "player_kills" const val STATS_PK_DEATHS = "player_deaths" const val STATS_ALKHARID_GATE = "alkharid_gate" diff --git a/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt b/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt index f3899a7a1..b9b6e320c 100644 --- a/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/StatsCommandSet.kt @@ -67,6 +67,8 @@ class StatsCommandSet : CommandSet(Privilege.STANDARD) { 77 -> sendLine(player,"Rocks Mined: ${queryPlayer.getAttribute("$STATS_BASE:$STATS_ROCKS",0)}",i) 78 -> sendLine(player,"Fish Caught: ${queryPlayer.getAttribute("$STATS_BASE:$STATS_FISH",0)}",i) 79 -> sendLine(player, "Essence Crafted: ${queryPlayer.getAttribute("$STATS_BASE:$STATS_RC",0)}", i) + 80 -> sendLine(player, "Food Cooked: ${queryPlayer.getAttribute("$STATS_BASE:$STATS_FOOD_COOKED",0)}", i) + 81 -> sendLine(player, "Cats Raised: ${queryPlayer.getAttribute("$STATS_BASE:$STATS_CATS_RAISED",0)}", i) //Boss KC 82 -> sendLine(player, "KBD KC: ${globalData.bossCounters.get(BossKillCounter.KING_BLACK_DRAGON.ordinal)}",i) From f1131b7d00c35273ba74ba75e02587ac908e9769 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 07:00:13 +0000 Subject: [PATCH 222/306] Made random event teleports more robust, fixing edge cases --- .../main/content/global/ame/KidnapHelper.kt | 23 +++++++++++ .../main/content/global/ame/RandomEvents.kt | 4 +- .../ame/events/drilldemon/DrillDemonUtils.kt | 20 +++------- ...rgentDamienNPC.kt => SergeantDamienNPC.kt} | 4 +- .../ame/events/evilbob/EvilBobListeners.kt | 6 +-- .../global/ame/events/evilbob/EvilBobUtils.kt | 14 +++---- .../ame/events/freakyforester/FreakUtils.kt | 15 +++---- .../global/ame/events/maze/MazeInterface.kt | 6 +-- .../content/global/ame/events/maze/MazeNPC.kt | 7 ++-- .../ame/events/pillory/PilloryInterface.kt | 39 +++++++++---------- .../global/ame/events/pillory/PilloryNPC.kt | 8 ++-- .../quizmaster/QuizMasterDialogueFile.kt | 9 ++--- .../ame/events/quizmaster/QuizMasterNPC.kt | 8 ++-- .../surpriseexam/SupriseExamListeners.kt | 5 ++- .../events/surpriseexam/SurpriseExamUtils.kt | 25 ++++-------- .../skill/construction/HouseManager.java | 3 +- .../global/skill/construction/HouseZone.java | 8 +++- .../core/game/node/entity/player/Player.java | 19 +++++---- 18 files changed, 109 insertions(+), 114 deletions(-) create mode 100644 Server/src/main/content/global/ame/KidnapHelper.kt rename Server/src/main/content/global/ame/events/drilldemon/{SeargentDamienNPC.kt => SergeantDamienNPC.kt} (89%) diff --git a/Server/src/main/content/global/ame/KidnapHelper.kt b/Server/src/main/content/global/ame/KidnapHelper.kt new file mode 100644 index 000000000..2efc90f2d --- /dev/null +++ b/Server/src/main/content/global/ame/KidnapHelper.kt @@ -0,0 +1,23 @@ +package content.global.ame + +import core.ServerConstants +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager.TeleportType +import core.game.world.map.Location + +fun kidnapPlayer(player: Player, loc: Location, type: TeleportType) { + setAttribute(player, "kidnapped-by-random", true) + if (getAttribute(player, "/save:original-loc", null) == null) { + setAttribute(player, "/save:original-loc", player.location) + } + teleport(player, loc, type) +} + +fun returnPlayer(player: Player) { + player.locks.unlockTeleport() + val destination = getAttribute(player, "/save:original-loc", ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) + teleport(player, destination) + unlock(player) + removeAttributes(player, "/save:original-loc", "kidnapped-by-random") +} \ No newline at end of file diff --git a/Server/src/main/content/global/ame/RandomEvents.kt b/Server/src/main/content/global/ame/RandomEvents.kt index 9addefbe4..49bac5151 100644 --- a/Server/src/main/content/global/ame/RandomEvents.kt +++ b/Server/src/main/content/global/ame/RandomEvents.kt @@ -3,7 +3,7 @@ package content.global.ame import org.rs09.consts.Items import content.global.ame.events.MysteriousOldManNPC import content.global.ame.events.certer.CerterNPC -import content.global.ame.events.drilldemon.SeargentDamienNPC +import content.global.ame.events.drilldemon.SergeantDamienNPC import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC import content.global.ame.events.evilbob.EvilBobNPC import content.global.ame.events.evilchicken.EvilChickenNPC @@ -47,7 +47,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1) )), MAZE(npc = MazeNPC()), - DRILL_DEMON(npc = SeargentDamienNPC()), + DRILL_DEMON(npc = SergeantDamienNPC()), EVIL_CHICKEN(npc = EvilChickenNPC()), STRANGE_PLANT(npc = StrangePlantNPC()), SWARM(npc = SwarmNPC()), diff --git a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt index 84cba68d6..a6638fecb 100644 --- a/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt +++ b/Server/src/main/content/global/ame/events/drilldemon/DrillDemonUtils.kt @@ -1,9 +1,11 @@ package content.global.ame.events.drilldemon -import core.ServerConstants +import content.global.ame.kidnapPlayer +import content.global.ame.returnPlayer import core.api.* import core.game.interaction.QueueStrength import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import core.game.world.update.flag.context.Animation @@ -12,7 +14,6 @@ import org.rs09.consts.NPCs object DrillDemonUtils { val DD_KEY_TASK = "/save:drilldemon:task" - val DD_KEY_RETURN_LOC = "/save:original-loc" val DD_SIGN_VARP = 531 val DD_SIGN_JOG = 0 val DD_SIGN_SITUP = 1 @@ -24,10 +25,7 @@ object DrillDemonUtils { val DD_NPC = NPCs.SERGEANT_DAMIEN_2790 fun teleport(player: Player) { - if (getAttribute(player, DD_KEY_RETURN_LOC, null) == null) { - setAttribute(player, DD_KEY_RETURN_LOC, player.location) - } - teleport(player, Location.create(3163, 4819, 0)) + kidnapPlayer(player, Location.create(3163, 4819, 0), TeleportManager.TeleportType.INSTANT) player.interfaceManager.closeDefaultTabs() setComponentVisibility(player, 548, 69, true) setComponentVisibility(player, 746, 12, true) @@ -66,14 +64,8 @@ object DrillDemonUtils { } fun cleanup(player: Player) { - player.locks.unlockTeleport() - unlock(player) - val destination = getAttribute(player, DD_KEY_RETURN_LOC, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) - teleport(player, destination) - removeAttribute(player, DD_KEY_RETURN_LOC) - removeAttribute(player, DD_KEY_TASK) - removeAttribute(player, DD_CORRECT_OFFSET) - removeAttribute(player, DD_CORRECT_COUNTER) + returnPlayer(player) + removeAttributes(player, DD_KEY_TASK, DD_CORRECT_OFFSET, DD_CORRECT_COUNTER) player.interfaceManager.openDefaultTabs() setComponentVisibility(player, 548, 69, false) setComponentVisibility(player, 746, 12, false) diff --git a/Server/src/main/content/global/ame/events/drilldemon/SeargentDamienNPC.kt b/Server/src/main/content/global/ame/events/drilldemon/SergeantDamienNPC.kt similarity index 89% rename from Server/src/main/content/global/ame/events/drilldemon/SeargentDamienNPC.kt rename to Server/src/main/content/global/ame/events/drilldemon/SergeantDamienNPC.kt index f767b0554..af4e8fe3c 100644 --- a/Server/src/main/content/global/ame/events/drilldemon/SeargentDamienNPC.kt +++ b/Server/src/main/content/global/ame/events/drilldemon/SergeantDamienNPC.kt @@ -10,11 +10,11 @@ import core.game.interaction.QueueStrength import core.game.system.timer.impl.AntiMacro import core.tools.secondsToTicks -class SeargentDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) { +class SergeantDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) { override fun init() { super.init() - sendChat(player.username.capitalize() + "! Drop and give me 20!") + sendChat(player.username+ "! Drop and give me 20!") queueScript(player, 4, QueueStrength.SOFT) { stage: Int -> when (stage) { 0 -> { diff --git a/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt b/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt index b40c42bf6..f2a3e9134 100644 --- a/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt +++ b/Server/src/main/content/global/ame/events/evilbob/EvilBobListeners.kt @@ -1,5 +1,6 @@ package content.global.ame.events.evilbob +import content.global.ame.returnPlayer import core.ServerConstants import core.api.* import core.game.dialogue.FacialExpression @@ -8,8 +9,6 @@ import core.game.interaction.InteractionListener import core.game.interaction.QueueStrength import core.game.node.entity.Entity import core.game.node.entity.player.link.emote.Emotes -import core.game.node.entity.skill.Skills -import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction @@ -121,8 +120,7 @@ class EvilBobListeners : InteractionListener, MapArea { } 3 -> { sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.") - val destination = getAttribute(player, EvilBobUtils.prevLocation, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) - teleport(player, destination) + returnPlayer(player) EvilBobUtils.reward(player) EvilBobUtils.cleanup(player) resetAnimator(player) diff --git a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt index 55ef8c2db..d70eab940 100644 --- a/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt +++ b/Server/src/main/content/global/ame/events/evilbob/EvilBobUtils.kt @@ -1,8 +1,10 @@ package content.global.ame.events.evilbob -import core.ServerConstants +import content.global.ame.kidnapPlayer +import content.global.ame.returnPlayer import core.api.* import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.skill.Skills import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders @@ -14,7 +16,6 @@ import org.rs09.consts.NPCs import org.rs09.consts.Scenery object EvilBobUtils { - const val prevLocation = "/save:original-loc" const val eventComplete = "/save:evilbob:eventcomplete" const val assignedFishingZone = "/save:evilbob:fishingzone" const val attentive = "/save:evilbob:attentive" @@ -53,16 +54,11 @@ object EvilBobUtils { } fun teleport(player: Player) { - if (getAttribute(player, prevLocation, null) == null) { - setAttribute(player, prevLocation, player.location) - } - player.properties.teleportLocation = Location.create(3419, 4776, 0) + kidnapPlayer(player, Location.create(3419, 4776, 0), TeleportManager.TeleportType.INSTANT) } fun cleanup(player: Player) { - player.locks.unlockTeleport() - player.properties.teleportLocation = getAttribute(player, prevLocation, ServerConstants.HOME_LOCATION) - removeAttributes(player, assignedFishingZone, eventComplete, prevLocation, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen) + removeAttributes(player, assignedFishingZone, eventComplete, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen) removeAll(player, Items.FISHLIKE_THING_6202) removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK) removeAll(player, Items.FISHLIKE_THING_6206) diff --git a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt index e777e3c05..e247bfeb1 100644 --- a/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt +++ b/Server/src/main/content/global/ame/events/freakyforester/FreakUtils.kt @@ -1,17 +1,18 @@ package content.global.ame.events.freakyforester -import core.ServerConstants +import content.global.ame.kidnapPlayer +import content.global.ame.returnPlayer import core.api.* import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager import core.game.world.map.Location import core.game.world.map.zone.ZoneBorders import core.tools.RandomFunction object FreakUtils{ const val freakNpc = NPCs.FREAKY_FORESTER_2458 - const val freakPreviousLoc = "/save:original-loc" const val freakTask = "/save:freakyf:task" const val freakComplete = "/save:freakyf:complete" const val pheasantKilled = "freakyf:killed" @@ -28,16 +29,12 @@ object FreakUtils{ } fun teleport(player: Player) { - if (getAttribute(player, freakPreviousLoc,null) == null) { - setAttribute(player, freakPreviousLoc, player.location) - } - teleport(player, Location.create(2599, 4777 ,0)) + kidnapPlayer(player, Location.create(2599, 4777 ,0), TeleportManager.TeleportType.INSTANT) } fun cleanup(player: Player) { - player.locks.unlockTeleport() - player.properties.teleportLocation = getAttribute(player,freakPreviousLoc, ServerConstants.HOME_LOCATION) - removeAttributes(player, freakPreviousLoc, freakTask, freakComplete, pheasantKilled) + returnPlayer(player) + removeAttributes(player, freakTask, freakComplete, pheasantKilled) removeAll(player, Items.RAW_PHEASANT_6178) removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK) removeAll(player, Items.RAW_PHEASANT_6179) diff --git a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt index 8a317e57a..108d456ca 100644 --- a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt +++ b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt @@ -1,5 +1,6 @@ package content.global.ame.events.maze +import content.global.ame.returnPlayer import core.api.* import core.api.utils.WeightBasedTable import core.api.utils.WeightedItem @@ -11,7 +12,6 @@ import core.game.interaction.InteractionListener import core.game.interaction.QueueStrength import core.game.node.entity.Entity import core.game.node.entity.player.Player -import core.game.node.scenery.SceneryBuilder import core.game.system.task.Pulse import core.game.world.GameWorld.Pulser import core.game.world.map.Location @@ -24,7 +24,6 @@ class MazeInterface : InteractionListener, EventHook, MapArea { companion object { const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209 const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0] - const val MAZE_ATTRIBUTE_RETURN_LOC = "/save:original-loc" const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left" const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened" @@ -217,9 +216,8 @@ class MazeInterface : InteractionListener, EventHook, MapArea { return@queueScript delayScript(player, 3) } 2 -> { - teleport(player, getAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + returnPlayer(player) sendGraphics(Graphics(1577, 0, 0), player.location) - removeAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC) animate(player,8941) closeOverlay(player) return@queueScript delayScript(player, 1) diff --git a/Server/src/main/content/global/ame/events/maze/MazeNPC.kt b/Server/src/main/content/global/ame/events/maze/MazeNPC.kt index 973f8423d..e4befe00e 100644 --- a/Server/src/main/content/global/ame/events/maze/MazeNPC.kt +++ b/Server/src/main/content/global/ame/events/maze/MazeNPC.kt @@ -1,10 +1,12 @@ package content.global.ame.events.maze import content.global.ame.RandomEventNPC +import content.global.ame.kidnapPlayer import core.api.* import core.api.utils.WeightBasedTable import core.game.interaction.QueueStrength import core.game.node.entity.npc.NPC +import core.game.node.entity.player.link.TeleportManager import core.game.system.timer.impl.AntiMacro import core.game.world.map.Location import core.game.world.map.build.DynamicRegion @@ -28,9 +30,6 @@ class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null return@queueScript delayScript(player, 3) } 1 -> { - if (getAttribute(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, null) == null) { - setAttribute(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, player.location) - } MazeInterface.initMaze(player) // Note: This event is NOT instanced: // Sources: @@ -40,7 +39,7 @@ class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null // https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for." // https://youtu.be/FMuKZm-Ikgs (2011) // val region = DynamicRegion.create(11591) - teleport(player, MazeInterface.STARTING_POINTS.random()) // 10 random spots + kidnapPlayer(player, MazeInterface.STARTING_POINTS.random(), TeleportManager.TeleportType.INSTANT) // 10 random spots AntiMacro.terminateEventNpc(player) sendGraphics(Graphics(1577, 0, 0), player.location) animate(player,8941) diff --git a/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt index 22ff21957..f48fc76f4 100644 --- a/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt +++ b/Server/src/main/content/global/ame/events/pillory/PilloryInterface.kt @@ -1,6 +1,7 @@ package content.global.ame.events.pillory import content.global.ame.RandomEvents +import content.global.ame.returnPlayer import core.api.* import core.game.dialogue.FacialExpression import core.game.interaction.IntType @@ -42,11 +43,10 @@ import org.rs09.consts.Sounds class PilloryInterface : InterfaceListener, InteractionListener, MapArea { companion object { const val PILLORY_LOCK_INTERFACE = 189 - const val PILLORY_ATRRIBUTE_RETURN_LOC = "/save:original-loc" const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys" const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock" - const val PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct" - const val PILLORY_ATRRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct" + const val PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct" + const val PILLORY_ATTRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct" val LOCATIONS = arrayOf( // Varrock Cages @@ -64,8 +64,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { ) fun initPillory(player: Player) { - setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) + setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.") } @@ -82,8 +82,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0) player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0) - val numberToGetCorrect = getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - val correctCount = getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + val numberToGetCorrect = getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) + val correctCount = getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) for (i in 1.. 6) { // Set if lock is red or green. if (i <= correctCount) { @@ -101,12 +101,12 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1) if (keys[buttonID] == lock) { // CORRECT ANSWER - setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + 1) - if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, -1)) { + setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + 1) + if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, -1)) { player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!") sendMessage(player, "You've escaped!") - removeAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT) - removeAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER) + removeAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT) + removeAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER) closeInterface(player) queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> when (stage) { @@ -120,10 +120,9 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { 1 -> { val loot = RandomEvents.CERTER.loot!!.roll(player)[0] addItemOrDrop(player, loot.id, loot.amount) - teleport(player, getAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + returnPlayer(player) sendGraphics(Graphics(1577, 0, 0), player.location) animate(player,8941) - removeAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC) closeInterface(player) return@queueScript stopExecuting(player) } @@ -137,19 +136,19 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea { true, "", "Correct!", - "" + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + " down, " + - (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)) + " to go!") + "" + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + " down, " + + (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)) + " to go!") // Animation for the star, but it doesn't work. - player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1), false) - sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1)) + player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1), false) + sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1)) } else { // WRONG ANSWER player.dialogueInterpreter.close() player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.") - if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) { - setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1) + if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) { + setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1) } - setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) closeInterface(player) } } diff --git a/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt b/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt index 055c684dd..f833d9ce2 100644 --- a/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt +++ b/Server/src/main/content/global/ame/events/pillory/PilloryNPC.kt @@ -1,10 +1,12 @@ package content.global.ame.events.pillory import content.global.ame.RandomEventNPC +import content.global.ame.kidnapPlayer import core.api.* import core.api.utils.WeightBasedTable import core.game.interaction.QueueStrength import core.game.node.entity.npc.NPC +import core.game.node.entity.player.link.TeleportManager import core.game.system.timer.impl.AntiMacro import core.game.world.map.Location import core.game.world.update.flag.context.Graphics @@ -29,11 +31,9 @@ class PilloryNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(N return@queueScript delayScript(player, 3) } 1 -> { - if (getAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, null) == null) { - setAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, player.location) - } PilloryInterface.initPillory(player) - teleport(player, PilloryInterface.LOCATIONS.random()) // 9 random spots! + val dest = PilloryInterface.LOCATIONS.random() //9 random spots! + kidnapPlayer(player, dest, TeleportManager.TeleportType.INSTANT) AntiMacro.terminateEventNpc(player) sendGraphics(Graphics(1577, 0, 0), player.location) animate(player,8941) diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt index aba73764c..3796fac17 100644 --- a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt @@ -1,5 +1,6 @@ package content.global.ame.events.quizmaster +import content.global.ame.returnPlayer import core.ServerConstants import core.api.* import core.api.utils.WeightBasedTable @@ -8,7 +9,6 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.FacialExpression import core.game.interaction.QueueStrength import core.game.node.entity.player.Player -import core.game.world.map.Location import core.tools.END_DIALOGUE import org.rs09.consts.Components import org.rs09.consts.Items @@ -16,7 +16,6 @@ import org.rs09.consts.Items class QuizMasterDialogueFile : DialogueFile() { companion object { const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191 - const val QUIZMASTER_ATTRIBUTE_RETURN_LOC = "/save:original-loc" const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct" const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer" @@ -106,7 +105,7 @@ class QuizMasterDialogueFile : DialogueFile() { 5 -> options("1000 Coins", "Random Item").also { stage++ } 6 -> { resetAnimator(player!!) - teleport(player!!, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) + returnPlayer(player!!) when (buttonID) { 1 -> { queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int -> @@ -121,9 +120,7 @@ class QuizMasterDialogueFile : DialogueFile() { } } } - removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC) - removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT) - removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER) + removeAttributes(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER) stage = END_DIALOGUE end() } diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt index d1c6f12e9..26407a1dc 100644 --- a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterNPC.kt @@ -1,10 +1,12 @@ package content.global.ame.events.quizmaster import content.global.ame.RandomEventNPC +import content.global.ame.kidnapPlayer import core.api.* import core.api.utils.WeightBasedTable import core.game.interaction.QueueStrength import core.game.node.entity.npc.NPC +import core.game.node.entity.player.link.TeleportManager import core.game.system.timer.impl.AntiMacro import core.game.world.map.Location import core.game.world.update.flag.context.Graphics @@ -35,12 +37,8 @@ class QuizMasterNPC(var type: String = "", override var loot: WeightBasedTable? return@queueScript delayScript(player, 3) } 1 -> { - if (getAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, null) == null) { - setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, player.location) - } + kidnapPlayer(player, Location(1952, 4764, 1), TeleportManager.TeleportType.INSTANT) setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) - //MazeInterface.initMaze(player) - teleport(player, Location(1952, 4764, 1)) AntiMacro.terminateEventNpc(player) sendGraphics(Graphics(1577, 0, 0), player.location) animate(player,8941) diff --git a/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt b/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt index 3fbe1cdc7..6d8ad6b4f 100644 --- a/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SupriseExamListeners.kt @@ -10,6 +10,7 @@ import core.game.interaction.InteractionListener import core.game.interaction.IntType import content.global.handlers.iface.ExperienceInterface import core.api.MapArea +import core.api.removeItem import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction @@ -23,7 +24,7 @@ class SupriseExamListeners : InteractionListener, MapArea { return@on true } - on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open"){ player, node -> + on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open") { player, node -> val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1) if(correctDoor == -1){ @@ -42,7 +43,7 @@ class SupriseExamListeners : InteractionListener, MapArea { on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ -> player.setAttribute("caller") { skill: Int, p: Player -> - if (p.inventory.remove(Item(Items.BOOK_OF_KNOWLEDGE_11640))) { + if (removeItem(p, Items.BOOK_OF_KNOWLEDGE_11640)) { val level = p.skills.getStaticLevel(skill) val experience = level * 15.0 p.skills.addExperience(skill, experience) diff --git a/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt b/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt index 1c729efc0..01a722343 100644 --- a/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt +++ b/Server/src/main/content/global/ame/events/surpriseexam/SurpriseExamUtils.kt @@ -1,22 +1,18 @@ package content.global.ame.events.surpriseexam -import core.Server +import content.global.ame.kidnapPlayer +import content.global.ame.returnPlayer import core.api.* import core.game.node.entity.impl.PulseType import core.game.node.entity.player.Player -import core.game.node.item.GroundItemManager -import core.game.node.item.Item import core.game.system.task.Pulse import core.game.world.map.Location import org.rs09.consts.Components import org.rs09.consts.Items -import core.ServerConstants +import core.game.node.entity.player.link.TeleportManager object SurpriseExamUtils { - - val SE_KEY_LOC = "/save:original-loc" val SE_KEY_INDEX = "supexam:index" - val SE_LOGOUT_KEY = "suprise_exam" val SE_DOOR_KEY = "supexam:door" val INTER_PATTERN_CHILDS = intArrayOf(6,7,8) val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13) @@ -30,20 +26,13 @@ object SurpriseExamUtils { intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311) ) - fun teleport(player: Player){ - if (getAttribute(player, SE_KEY_LOC, null) == null) { - player.setAttribute(SE_KEY_LOC, player.location) - } - registerLogoutListener(player, SE_LOGOUT_KEY){p -> - p.location = getAttribute(p, SE_KEY_LOC, ServerConstants.HOME_LOCATION) - } - player.properties.teleportLocation = Location.create(1886, 5025, 0) + fun teleport(player: Player) { + kidnapPlayer(player, Location.create(1886, 5025, 0), TeleportManager.TeleportType.INSTANT) } fun cleanup(player: Player){ - player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC, ServerConstants.HOME_LOCATION) - clearLogoutListener(player, SE_LOGOUT_KEY) - removeAttributes(player, SE_KEY_LOC, SE_KEY_INDEX, SE_KEY_CORRECT) + returnPlayer(player) + removeAttributes(player, SE_KEY_INDEX, SE_KEY_CORRECT) player.pulseManager.run(object : Pulse(2){ override fun pulse(): Boolean { addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640) diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 372b976d2..01a37f377 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -204,7 +204,7 @@ public final class HouseManager { } /** - * Leaves this house. + * Leaves this house through the portal. * @param player The player leaving. */ public static void leave(Player player) { @@ -215,7 +215,6 @@ public final class HouseManager { if (house.isInHouse(player)) { player.animate(Animation.RESET); player.getProperties().setTeleportLocation(house.location.getExitLocation()); - removeAttribute(player, "original-loc"); } } diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index 860b38e03..ccd426c19 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -3,11 +3,12 @@ package content.global.skill.construction; import core.game.node.entity.Entity; import core.game.node.entity.player.Player; +import core.game.world.map.build.DynamicRegion; import core.game.world.map.zone.MapZone; -import core.game.world.map.zone.ZoneRestriction; import core.game.world.map.RegionManager; import core.game.world.map.Region; import core.game.system.task.Pulse; +import core.game.world.map.zone.ZoneRestriction; import static core.api.ContentAPIKt.*; @@ -90,6 +91,7 @@ public final class HouseZone extends MapZone { public boolean leave(Entity e, boolean logout) { if (e instanceof Player) { Player p = (Player) e; + // The below tears down the house if the owner was the one who left if (house == p.getHouseManager()) { house.expelGuests(p); int toRemove = previousRegion; @@ -110,7 +112,11 @@ public final class HouseZone extends MapZone { } }); } + // Clear logout listener and original-loc (if appropriate) clearLogoutListener(p, "houselogout"); + if (!getAttribute(p, "kidnapped-by-random", false)) { + removeAttribute(p, "/save:original-loc"); + } return true; } return true; diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 70f944c39..dfced34d2 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -465,14 +465,17 @@ public class Player extends Entity { // Update wealth tracking checkForWealthUpdate(false); - // Check if the player is on the map - // This is only a sanity check to detect improper usage of the 'original-loc' attribute, hence only do this work if the attribute is set - if (ContentAPIKt.getAttribute(this, "/save:original-loc", null) != null) { - int rid = location.getRegionId(); - Region r = RegionManager.forId(rid); - if (!(r instanceof DynamicRegion) && !getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) { - log(this.getClass(), Log.ERR, "Player " + getUsername() + " has the original-loc attribute set but isn't actually off-map! This indicates a bug in the code that set that attribute. The original-loc is: " + getAttribute("/save:original-loc") + ", good luck debugging!"); - ContentAPIKt.removeAttribute(this, "original-loc"); + // Check if the player is on the map, runs only every 6 seconds for performance reasons. + // This is only a sanity check to detect improper usage of the 'original-loc' attribute, hence only do this work if the attribute is set. + // Only runs when the player is not movement/interaction-locked, so that original-loc does not get wiped e.g. in the middle of the player teleporting to their POH. + if (GameWorld.getTicks() % 10 == 0 && !getLocks().isMovementLocked() && !getLocks().isInteractionLocked()) { + if (ContentAPIKt.getAttribute(this, "/save:original-loc", null) != null) { + int rid = location.getRegionId(); + Region r = RegionManager.forId(rid); + if (!(r instanceof DynamicRegion) && !getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) { + log(this.getClass(), Log.ERR, "Player " + getUsername() + " has the original-loc attribute set but isn't actually off-map! This indicates a bug in the code that set that attribute. The original-loc is " + getAttribute("/save:original-loc") + ", the current region is " + rid + ". Good luck debugging!"); + ContentAPIKt.removeAttribute(this, "original-loc"); + } } } } From 9886049429cd4c3c231484e3833b171a3966ac2a Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 16 Feb 2025 07:09:36 +0000 Subject: [PATCH 223/306] Implemented Zogre Flesh Eaters quest --- Server/data/configs/drop_tables.json | 58 +-- Server/data/configs/ground_spawns.json | 4 + Server/data/configs/npc_configs.json | 39 +- Server/data/configs/npc_spawns.json | 22 +- Server/data/configs/shops.json | 9 + .../global/skill/fletching/Fletching.java | 4 +- .../skill/fletching/FletchingListeners.kt | 30 +- .../skill/fletching/FletchingPulse.java | 29 +- .../items/arrow/HeadlessOgreArrowPulse.java | 131 ++++++ .../content/global/skill/herblore/Herbs.java | 2 +- .../skill/herblore/UnfinishedPotion.java | 1 + .../feldip/quest/chompybird/ChompyBird.kt | 22 +- .../feldip/quest/chompybird/ChompyBirdNPC.kt | 2 +- .../zogreflesheaters/BartenderDialogueFile.kt | 62 +++ .../quest/zogreflesheaters/GrishDialogue.kt | 184 +++++++++ .../quest/zogreflesheaters/GrugDialogue.kt | 31 ++ .../quest/zogreflesheaters/JiggigListeners.kt | 27 ++ .../zogreflesheaters/OgreGuardDialogue.kt | 73 ++++ .../quest/zogreflesheaters/PilgDialogue.kt | 31 ++ .../zogreflesheaters/SithikIntsDialogue.kt | 388 ++++++++++++++++++ .../quest/zogreflesheaters/SkogreBehavior.kt | 39 ++ .../zogreflesheaters/SlashBashBehavior.kt | 92 +++++ .../zogreflesheaters/UglugNarDialogue.kt | 78 ++++ .../ZavisticRarveDialogueFile.kt | 290 +++++++++++++ .../quest/zogreflesheaters/ZogreBehavior.kt | 47 +++ .../zogreflesheaters/ZogreFleshEaters.kt | 353 ++++++++++++++++ .../ZogreFleshEatersListeners.kt | 382 +++++++++++++++++ .../ZogrePotionAndFletchingListeners.kt | 109 +++++ .../ZombieBrentleVahnBehavior.kt | 40 ++ .../kandarin/guilds/WizardGuildPlugin.java | 63 --- .../yanille/dialogue/ZavisticRarveDialogue.kt | 120 ++++++ .../quest/junglepotion/JunglePotion.java | 2 +- Server/src/main/core/api/ContentAPI.kt | 7 +- .../game/global/action/SpecialLadders.java | 8 + .../game/system/command/sets/FunCommandSet.kt | 18 +- 35 files changed, 2637 insertions(+), 160 deletions(-) create mode 100644 Server/src/main/content/global/skill/fletching/items/arrow/HeadlessOgreArrowPulse.java create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/BartenderDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrishDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrugDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/JiggigListeners.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/OgreGuardDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/PilgDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SithikIntsDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SkogreBehavior.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SlashBashBehavior.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/UglugNarDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZavisticRarveDialogueFile.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreBehavior.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEaters.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEatersListeners.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogrePotionAndFletchingListeners.kt create mode 100644 Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZombieBrentleVahnBehavior.kt create mode 100644 Server/src/main/content/region/kandarin/yanille/dialogue/ZavisticRarveDialogue.kt diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 8a31d8263..db135d222 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -3262,7 +3262,7 @@ } ], "charm": [], - "ids": "73,74,75,419,420,421,422,423,424,1826,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131", + "ids": "73,74,75,419,420,421,422,423,424,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131", "description": "", "main": [ { @@ -28545,60 +28545,10 @@ "maxAmount": "1" } ], - "charm": [ - { - "minAmount": "1", - "weight": "85.8093", - "id": "0", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "10.9113", - "id": "12158", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "1.6775", - "id": "12159", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "1.6019", - "id": "12160", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "0.0", - "id": "12163", - "maxAmount": "1" - } - ], - "ids": "2044,2045,2046,2047,2048,2049,2051,2052,2053,2054,2055", + "charm": [], + "ids": "2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057", "description": "", - "main": [ - { - "minAmount": "1", - "weight": "1.0", - "id": "1", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "124.0", - "id": "0", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "3.0", - "id": "7848", - "maxAmount": "1" - } - ] + "main": [] }, { "default": [ diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json index 9b44b4f65..ca2b6f773 100644 --- a/Server/data/configs/ground_spawns.json +++ b/Server/data/configs/ground_spawns.json @@ -627,6 +627,10 @@ "item_id": "4707", "loc_data": "{1,3571,3312,0,40}-" }, + { + "item_id": "4838", + "loc_data": "{1,2593,3103,1,40}-" + }, { "item_id": "5008", "loc_data": "{1,3230,9609,0,44}-" diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 2967df677..e7358f0df 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -19219,6 +19219,21 @@ "range_level": "1", "attack_level": "1" }, + { + "examine": "A human zombie.", + "melee_animation": "5568", + "combat_audio": "931,923,922", + "defence_animation": "5567", + "death_animation": "5569", + "name": "Zombie", + "defence_level": "30", + "safespot": null, + "lifepoints": "50", + "strength_level": "30", + "id": "1826", + "range_level": "1", + "attack_level": "30" + }, { "examine": "Flies like a rock.", "melee_animation": "9454", @@ -21498,16 +21513,28 @@ "attack_level": "1" }, { + "examine": "A partially decomposing zombie ogre.", + "slayer_task": "64", + "combat_audio": "", + "melee_animation": "359", + "range_animation": "359", + "attack_speed": "6", + "magic_level": "1", + "respawn_delay": "60", + "defence_animation": "360", + "slayer_exp": "", + "weakness": "7", + "magic_animation": "359", + "death_animation": "361", "name": "Slash Bash", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "103", - "strength_level": "1", + "lifepoints": "100", + "strength_level": "120", "id": "2060", "aggressive": "true", - "range_level": "1", - "respawn_delay": "60", - "attack_level": "1" + "range_level": "100", + "attack_level": "100" }, { "examine": "I can see fish swimming in the water.", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 3684e902a..074d7ee1f 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -4717,15 +4717,27 @@ }, { "npc_id": "2044", - "loc_data": "{2486,3048,0,1,3}-" + "loc_data": "{2486,3048,0,1,3}-{2484,9392,2,1,0}-{2465,9454,2,1,0}-{2471,9422,2,1,0}-{2448,9442,2,1,0}-" }, { "npc_id": "2045", - "loc_data": "{2482,3046,0,1,3}-" + "loc_data": "{2482,3046,0,1,3}-{2459,9394,2,1,0}-{2473,9430,2,1,0}-{2478,9442,2,1,0}-{2487,9455,2,1,0}-" + }, + { + "npc_id": "2046", + "loc_data": "{2466,9389,2,1,0}-{2449,9429,0,1,0}-{2436,9452,2,1,0}-{2436,9465,2,1,0}-{2450,9460,2,1,0}-{2455,9440,2,1,0}-{2473,9439,2,1,0}-{2483,9408,2,1,0}-" }, { "npc_id": "2047", - "loc_data": "{2480,3046,0,1,3}-" + "loc_data": "{2480,3046,0,1,3}-{2477,9384,2,1,0}-{2449,9434,0,1,0}-{2437,9429,2,1,0}-{2440,9438,2,1,0}-{2458,9408,2,1,0}-" + }, + { + "npc_id": "2048", + "loc_data": "{2485,9398,2,1,0}-{2455,9435,0,1,0}-{2457,9420,2,1,0}-{2462,9431,2,1,0}-{2482,9422,2,1,0}-" + }, + { + "npc_id": "2049", + "loc_data": "{2452,9440,0,1,0}-" }, { "npc_id": "2050", @@ -4755,6 +4767,10 @@ "npc_id": "2056", "loc_data": "{2470,3040,0,0,0}-" }, + { + "npc_id": "2057", + "loc_data": "{2442,9436,2,1,0}-{2458,9413,2,1,0}-{2470,9435,2,1,0}-{2472,9460,2,1,0}-{2483,9413,2,1,0}-{2485,9447,2,1,0}-{2480,3046,0,1,0}-{2453,9393,2,1,0}-{2461,9403,2,1,0}-{2464,9380,2,1,0}-" + }, { "npc_id": "2059", "loc_data": "{2588,3088,0,1,3}-" diff --git a/Server/data/configs/shops.json b/Server/data/configs/shops.json index 0b7745e45..a84aedda9 100644 --- a/Server/data/configs/shops.json +++ b/Server/data/configs/shops.json @@ -2186,5 +2186,14 @@ "id": "256", "title": "Leon's Prototype Crossbow", "stock": "{10156,2,100}" + }, + { + "npcs": "2039", + "high_alch": "0", + "currency": "995", + "general_store": "false", + "id": "256", + "title": "Uglug's Stuffsies", + "stock": "{4844,100,10}-{10927,0,100}-{2862,100,100}-{1777,10,200}-{2876,0,500}-{2878,10,100}-{4850,0,100}-{946,5,100}-{4773,0,1000}-{4778,0,1000}-{4783,0,1000}-{4788,0,1500}-{4793,0,2000}-{4798,0,3000}-{4803,0,4000}-{4827,0,2000}" } ] \ No newline at end of file diff --git a/Server/src/main/content/global/skill/fletching/Fletching.java b/Server/src/main/content/global/skill/fletching/Fletching.java index de5a99e65..3a6c6906e 100644 --- a/Server/src/main/content/global/skill/fletching/Fletching.java +++ b/Server/src/main/content/global/skill/fletching/Fletching.java @@ -132,6 +132,7 @@ public class Fletching { YEW_LONGBOW((byte) 1,66,855,70, 75, new Animation(6688)), MAGIC_SHORTBOW((byte) 1,72,861,80, 83.3, new Animation(6683)), MAGIC_LONGBOW((byte) 1,70,859,85, 91.5, new Animation(6689)), + OGRE_COMP_BOW((byte) 1,4825,4827,30, 45, new Animation(-1)), //crossbows BRONZE_CBOW((byte) 2,9454,9174,9, 6, new Animation(6671)), @@ -266,7 +267,7 @@ public class Fletching { } private enum Items{ STANDARD(1511,FletchingItems.ARROW_SHAFT, FletchingItems.SHORT_BOW, FletchingItems.LONG_BOW, FletchingItems.WOODEN_STOCK), - ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT), + ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT, FletchingItems.OGRE_COMP_BOW), OAK(1521, FletchingItems.OAK_SHORTBOW, FletchingItems.OAK_LONGBOW, FletchingItems.OAK_STOCK), WILLOW(1519, FletchingItems.WILLOW_SHORTBOW, FletchingItems.WILLOW_LONGBOW, FletchingItems.WILLOW_STOCK), MAPLE(1517, FletchingItems.MAPLE_SHORTOW, FletchingItems.MAPLE_LONGBOW, FletchingItems.MAPLE_STOCK), @@ -304,6 +305,7 @@ public class Fletching { //Achey logs OGRE_ARROW_SHAFT(2864, 6.4, 5, 4), + OGRE_COMP_BOW(4825, 45, 30, 1), //Oak logs OAK_SHORTBOW(54, 16.5, 20, 1), diff --git a/Server/src/main/content/global/skill/fletching/FletchingListeners.kt b/Server/src/main/content/global/skill/fletching/FletchingListeners.kt index 52ae6f94b..464a0b6ff 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingListeners.kt +++ b/Server/src/main/content/global/skill/fletching/FletchingListeners.kt @@ -1,12 +1,13 @@ package content.global.skill.fletching -import core.game.node.entity.skill.Skills -import content.global.skill.fletching.Fletching +import content.data.Quests import content.global.skill.fletching.items.arrow.ArrowHeadPulse import content.global.skill.fletching.items.arrow.HeadlessArrowPulse +import content.global.skill.fletching.items.arrow.HeadlessOgreArrowPulse import content.global.skill.fletching.items.bow.StringPulse import content.global.skill.fletching.items.crossbow.LimbPulse import core.api.* +import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.net.packet.PacketRepository import core.net.packet.context.ChildPositionContext @@ -34,7 +35,9 @@ class FletchingListeners : InteractionListener { val MITH_GRAPPLE = Items.MITH_GRAPPLE_9418 val ROPE_GRAPPLE = Items.MITH_GRAPPLE_9419 val ARROW_SHAFT = Items.ARROW_SHAFT_52 + val OGRE_ARROW_SHAFT = Items.OGRE_ARROW_SHAFT_2864 val FLETCHED_SHAFT = Items.HEADLESS_ARROW_53 + val FLIGHTED_OGRE_ARROW = Items.FLIGHTED_OGRE_ARROW_2865 val UNFINISHED_ARROWS = Fletching.ArrowHeads.values().map(Fletching.ArrowHeads::unfinished).toIntArray() val FEATHERS = intArrayOf(FEATHER_314,STRIPY_FEATHER_10087,RED_FEATHER_10088,BLUE_FEATHER_10089,YELLOW_FEATHER_10090,ORANGE_FEATHER_10091) val UNSTRUNG_BOWS = Fletching.String.values().map(Fletching.String::unfinished).toIntArray() @@ -44,6 +47,14 @@ class FletchingListeners : InteractionListener { onUseWith(IntType.ITEM,STRINGS,*UNSTRUNG_BOWS){ player, string, bow -> val enum = Fletching.stringMap[bow.id] ?: return@onUseWith false + + if (bow.id == Items.UNSTRUNG_COMP_BOW_4825) { + // You shouldn't be able to string a bow + if (getQuestStage(player, Quests.ZOGRE_FLESH_EATERS) < 8) { + player.packetDispatch.sendMessage("You must have started Zogre Flesh Eaters and asked Grish to string this.") + return@onUseWith true + } + } if(enum.string != string.id){ player.sendMessage("That's not the right kind of string for this.") return@onUseWith true @@ -78,6 +89,21 @@ class FletchingListeners : InteractionListener { return@onUseWith true } + onUseWith(IntType.ITEM,OGRE_ARROW_SHAFT,*FEATHERS){ player, shaft, feather -> + val handler: SkillDialogueHandler = + object : SkillDialogueHandler(player, SkillDialogue.MAKE_SET_ONE_OPTION, Item(FLIGHTED_OGRE_ARROW)) { + override fun create(amount: Int, index: Int) { + player.pulseManager.run(HeadlessOgreArrowPulse(player, shaft.asItem(), Item(feather.id, 4), amount)) + } + + override fun getAll(index: Int): Int { + return player.inventory.getAmount(FLIGHTED_OGRE_ARROW) + } + } + handler.open() + return@onUseWith true + } + onUseWith(IntType.ITEM,FLETCHED_SHAFT,*UNFINISHED_ARROWS){ player, shaft, unfinished -> val head = Fletching.arrowHeadMap[unfinished.id] ?: return@onUseWith false val handler: SkillDialogueHandler = diff --git a/Server/src/main/content/global/skill/fletching/FletchingPulse.java b/Server/src/main/content/global/skill/fletching/FletchingPulse.java index 8ef3214d8..b02e40572 100644 --- a/Server/src/main/content/global/skill/fletching/FletchingPulse.java +++ b/Server/src/main/content/global/skill/fletching/FletchingPulse.java @@ -37,6 +37,11 @@ public final class FletchingPulse extends SkillPulse { */ private int amount = 0; + /** + * Represents the amount to arrows fletched (for ogre arrow shafts which is a random number from 2-6). + */ + private int finalAmount = 0; + /** * Constructs a new {@code FletchingPulse.java} {@code Object}. * @param player @@ -63,6 +68,17 @@ public final class FletchingPulse extends SkillPulse { return false; } } + if (fletch == Fletching.FletchingItems.OGRE_COMP_BOW) { + // Technically, this isn't supposed to show up till you've asked Grish. + if (player.getQuestRepository().getQuest(Quests.ZOGRE_FLESH_EATERS).getStage(player) < 8) { + player.getPacketDispatch().sendMessage("You must have started Zogre Flesh Eaters and asked Grish to make this."); + return false; + } + if (!player.getInventory().contains(2859, 1)) { + player.getPacketDispatch().sendMessage("You need to have Wolf Bones in order to make this."); + return false; + } + } return true; } @@ -83,7 +99,16 @@ public final class FletchingPulse extends SkillPulse { if (player.getInventory().remove(node)) { final Item item = new Item(fletch.id,fletch.amount); if ( fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT ) { - item.setAmount(RandomFunction.random(3,6)); + // The amount of shafts given is random; between two and six will be made. + finalAmount = RandomFunction.random(2,6); + item.setAmount(finalAmount); + } + if ( fletch == Fletching.FletchingItems.OGRE_COMP_BOW ) { + if (!player.getInventory().contains(2859, 1)) { + return false; + } else { + player.getInventory().remove(new Item(2859)); + } } player.getInventory().add(item); player.getSkills().addExperience(Skills.FLETCHING, fletch.experience, true); @@ -111,6 +136,8 @@ public final class FletchingPulse extends SkillPulse { switch (fletch) { case ARROW_SHAFT: return "You carefully cut the wood into 15 arrow shafts."; + case OGRE_ARROW_SHAFT: + return "You carefully cut the wood into " + finalAmount + " arrow shafts."; default: return "You carefully cut the wood into " + (StringUtils.isPlusN(fletch.getItem().getName()) ? "an" : "a") + " " + fletch.getItem().getName().replace("(u)", "").trim() + "."; } diff --git a/Server/src/main/content/global/skill/fletching/items/arrow/HeadlessOgreArrowPulse.java b/Server/src/main/content/global/skill/fletching/items/arrow/HeadlessOgreArrowPulse.java new file mode 100644 index 000000000..fd7af6731 --- /dev/null +++ b/Server/src/main/content/global/skill/fletching/items/arrow/HeadlessOgreArrowPulse.java @@ -0,0 +1,131 @@ +package content.global.skill.fletching.items.arrow; + +import core.game.node.entity.player.Player; +import core.game.node.entity.skill.SkillPulse; +import core.game.node.entity.skill.Skills; +import core.game.node.item.Item; +import org.rs09.consts.Items; + +import static core.api.ContentAPIKt.hasSpaceFor; +import static core.api.ContentAPIKt.sendDialogue; + +/** + * Represents the arrow pulse for creating unfinished ogre arrows. + * @author 'Vexia + */ +public final class HeadlessOgreArrowPulse extends SkillPulse { + + /** + * Represents the headless ogre arrow item. + */ + private final Item HEADLESS_ARROW = new Item(Items.FLIGHTED_OGRE_ARROW_2865); + + /** + * Represents the ogre arrow shaft item. + */ + private final Item ARROW_SHAFT = new Item(Items.OGRE_ARROW_SHAFT_2864); + + /** + * Represents the feather items. + */ + private static final Item[] FEATHER = new Item[] { + new Item(Items.FEATHER_314, 4), + }; + + /** + * The feather being used. + */ + private Item feather; + + /** + * Represents the amount to make. + */ + private int sets; + + /** + * Constructs a new {@code ArrowPulse.java} {@code Object}. + * @param player the player. + * @param node the node. + */ + public HeadlessOgreArrowPulse(Player player, Item node, Item feather, int sets) { + super(player, node); + this.sets = sets; + this.feather = feather; + } + + @Override + public boolean checkRequirements() { + if (!player.getInventory().containsItem(ARROW_SHAFT)) { + player.getDialogueInterpreter().sendDialogue("You don't have any arrow shafts."); + return false; + } + if (feather == null || !player.getInventory().containsItem(feather)) { + player.getDialogueInterpreter().sendDialogue("You don't have any feathers."); + return false; + } + if (!hasSpaceFor(player, HEADLESS_ARROW.asItem())) { + sendDialogue(player, "You do not have enough inventory space."); + return false; + } + return true; + } + + @Override + public void animate() { + } + + @Override + public boolean reward() { + int featherAmount = player.getInventory().getAmount(feather); + int shaftAmount = player.getInventory().getAmount(ARROW_SHAFT); + if (getDelay() == 1) { + super.setDelay(3); + } + if (featherAmount >= 24 && shaftAmount >= 6) { + feather.setAmount(24); + ARROW_SHAFT.setAmount(6); + player.getPacketDispatch().sendMessage("You attach 24 feathers to 6 ogre arrow shafts."); + } else { + int amount = Math.min(featherAmount / 4, shaftAmount); + feather.setAmount(amount*4); + ARROW_SHAFT.setAmount(amount); + player.getPacketDispatch().sendMessage(amount == 1 + ? "You attach a feathers to a shaft." : "You attach " + amount * 4 + " feathers to " + amount + " ogre arrow shafts."); + } + if (player.getInventory().remove(feather, ARROW_SHAFT)) { + HEADLESS_ARROW.setAmount(ARROW_SHAFT.getAmount()); + player.getSkills().addExperience(Skills.FLETCHING, HEADLESS_ARROW.getAmount(), true); + player.getInventory().add(HEADLESS_ARROW); + } + HEADLESS_ARROW.setAmount(1); + feather.setAmount(1); + ARROW_SHAFT.setAmount(1); + if (!player.getInventory().containsItem(ARROW_SHAFT)) { + return true; + } + if (!player.getInventory().containsItem(feather)) { + return true; + } + sets--; + return sets <= 0; + } + + @Override + public void message(int type) { + } + + /** + * Gets the feather item. + * @return the item. + */ + private Item getFeather() { + int length = FEATHER.length; + for (int i = 0; i < length; i++) { + Item f = FEATHER[i]; + if (player.getInventory().containsItem(f)) { + return f; + } + } + return null; + } +} diff --git a/Server/src/main/content/global/skill/herblore/Herbs.java b/Server/src/main/content/global/skill/herblore/Herbs.java index 5ee4959eb..1973162f1 100644 --- a/Server/src/main/content/global/skill/herblore/Herbs.java +++ b/Server/src/main/content/global/skill/herblore/Herbs.java @@ -7,7 +7,7 @@ import core.game.node.item.Item; * @author 'Vexia */ public enum Herbs { - GUAM(new Item(199), 2.5, 3, new Item(249)), MARRENTILL(new Item(201), 3.8, 5, new Item(251)), TARROMIN(new Item(203), 5, 11, new Item(253)), HARRALANDER(new Item(205), 6.3, 20, new Item(255)), RANARR(new Item(207), 7.5, 25, new Item(257)), TOADFLAX(new Item(3049), 8, 30, new Item(2998)), SPIRIT_WEED(new Item(12174), 7.8, 35, new Item(12172)), IRIT(new Item(209), 8.8, 40, new Item(259)), AVANTOE(new Item(211), 10, 48, new Item(261)), KWUARM(new Item(213), 11.3, 54, new Item(263)), SNAPDRAGON(new Item(3051), 11.8, 59, new Item(3000)), CADANTINE(new Item(215), 12.5, 65, new Item(265)), LANTADYME(new Item(2485), 13.1, 67, new Item(2481)), DWARF_WEED(new Item(217), 13.8, 70, new Item(267)), TORSTOL(new Item(219), 15, 75, new Item(269)), SNAKE_WEED(new Item(1525), 2.5, 3, new Item(1526)), ARDRIGAL(new Item(1527), 2.5, 3, new Item(1528)), SITO_FOIL(new Item(1529), 2.5, 3, new Item(1530)), VOLENCIA_MOSS(new Item(1531), 2.5, 3, new Item(1532)), ROGUES_PUSE(new Item(1533), 2.5, 3, new Item(1534)); + GUAM(new Item(199), 2.5, 3, new Item(249)), MARRENTILL(new Item(201), 3.8, 5, new Item(251)), TARROMIN(new Item(203), 5, 11, new Item(253)), HARRALANDER(new Item(205), 6.3, 20, new Item(255)), RANARR(new Item(207), 7.5, 25, new Item(257)), TOADFLAX(new Item(3049), 8, 30, new Item(2998)), SPIRIT_WEED(new Item(12174), 7.8, 35, new Item(12172)), IRIT(new Item(209), 8.8, 40, new Item(259)), AVANTOE(new Item(211), 10, 48, new Item(261)), KWUARM(new Item(213), 11.3, 54, new Item(263)), SNAPDRAGON(new Item(3051), 11.8, 59, new Item(3000)), CADANTINE(new Item(215), 12.5, 65, new Item(265)), LANTADYME(new Item(2485), 13.1, 67, new Item(2481)), DWARF_WEED(new Item(217), 13.8, 70, new Item(267)), TORSTOL(new Item(219), 15, 75, new Item(269)), SNAKE_WEED(new Item(1525), 2.5, 3, new Item(1526)), ARDRIGAL(new Item(1527), 2.5, 3, new Item(1528)), SITO_FOIL(new Item(1529), 2.5, 3, new Item(1530)), VOLENCIA_MOSS(new Item(1531), 2.5, 3, new Item(1532)), ROGUES_PURSE(new Item(1533), 0, 8, new Item(1534)); /** * Represents the herb item. diff --git a/Server/src/main/content/global/skill/herblore/UnfinishedPotion.java b/Server/src/main/content/global/skill/herblore/UnfinishedPotion.java index 699a03b74..aa6e48d27 100644 --- a/Server/src/main/content/global/skill/herblore/UnfinishedPotion.java +++ b/Server/src/main/content/global/skill/herblore/UnfinishedPotion.java @@ -9,6 +9,7 @@ import core.game.node.item.Item; public enum UnfinishedPotion { GUAM(Herbs.GUAM.getProduct(), 3, new Item(91)), MARRENTILL(Herbs.MARRENTILL.getProduct(), 5, new Item(93)), + ROGUES_PURSE(Herbs.ROGUES_PURSE.getProduct(), 5, new Item(4840)), TARROMIN(Herbs.TARROMIN.getProduct(), 12, new Item(95)), HARRALANDER(Herbs.HARRALANDER.getProduct(), 22, new Item(97)), RANARR(Herbs.RANARR.getProduct(), 30, new Item(99)), diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt index 73e8940d1..2ca5b5079 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBird.kt @@ -256,27 +256,6 @@ class ChompyBird : Quest(Quests.BIG_CHOMPY_BIRD_HUNTING, 35, 34, 2, Vars.VARP_QU return@onUseWith true } - onUseWith(IntType.ITEM, Items.OGRE_ARROW_SHAFT_2864, Items.FEATHER_314) { player, used, with -> - val shaftAmount = amountInInventory(player, used.id) - val featherAmount = amountInInventory(player, with.id) - var maxAmount = min(shaftAmount, featherAmount) - - submitIndividualPulse(player, object : Pulse(3) { - override fun pulse() : Boolean { - val iterAmount = min(maxAmount, 6) - if (removeItem(player, Item(Items.OGRE_ARROW_SHAFT_2864, iterAmount)) && removeItem(player, Item(Items.FEATHER_314, iterAmount))) - { - addItem(player, Items.FLIGHTED_OGRE_ARROW_2865, iterAmount) - rewardXP(player, Skills.FLETCHING, 0.9 * iterAmount) - maxAmount -= iterAmount - } - return maxAmount == 0 - } - }) - - return@onUseWith true - } - onUseWith(IntType.ITEM, Items.WOLF_BONES_2859, Items.CHISEL_1755) { player, used, with -> val maxAmount = amountInInventory(player, used.id) @@ -324,6 +303,7 @@ class ChompyBird : Quest(Quests.BIG_CHOMPY_BIRD_HUNTING, 35, 34, 2, Vars.VARP_QU val amountThisIter = min(6, getMaxAmount()) if (removeItem(player, Item(used.id, amountThisIter)) && removeItem(player, Item(with.id, amountThisIter))) { addItem(player, Items.OGRE_ARROW_2866, amountThisIter) + sendMessage(player, "You make $amountThisIter ogre arrows.") rewardXP(player, Skills.FLETCHING, 6.0) } } diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdNPC.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdNPC.kt index 8f0b000ed..337f30ac2 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdNPC.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/ChompyBirdNPC.kt @@ -164,7 +164,7 @@ class ChompyBirdNPC : AbstractNPC, InteractionListener { return@on true } - on(Items.OGRE_BOW_2883, IntType.ITEM, "check kills") { player, _ -> + on(intArrayOf(Items.OGRE_BOW_2883, Items.COMP_OGRE_BOW_4827), IntType.ITEM, "check kills") { player, _ -> val amount = player.getAttribute("chompy-kills", 0) sendDialogue(player, "You have killed $amount chompy birds.") return@on true diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/BartenderDialogueFile.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/BartenderDialogueFile.kt new file mode 100644 index 000000000..b93f3a8ed --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/BartenderDialogueFile.kt @@ -0,0 +1,62 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression +import org.rs09.consts.Items + +class BartenderDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onPredicate { _ -> dialogueNum == 1 } + .branch { player -> + return@branch if (getAttribute(player, ZogreFleshEaters.attributeAskedAboutTankard, false)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .playerl("Hello there, I found this tankard in an ogre tomb cavern. It has the emblem of this Inn on it and I wondered if you knew anything about it?") + .npcl("Oh yes, this is Brentle's mug...I'm surprised he left it just lying around down some cave. He's quite protective of it.") + .playerl("Brentle you say? So you knew him then?") + .npcl("Yeah, this belongs to 'Brentle Vahn', he's quite a common customer, though I've not seen him in a while.") + .npcl(FacialExpression.THINKING, "He was talking to some shifty looking wizard the other day. I don't know his name, but I'd recognise him if I saw him.") + .playerl("Hmm, I'm sorry to tell you this, but Brentle Vahn is dead - I believe he was murdered.") + .npcl(FacialExpression.EXTREMELY_SHOCKED, "Noooo! I'm shocked...") + .npcl("...but not surprised. He was a good customer...but I knew he would sell his sword arm and do many a dark deed if paid enough.") + .npcl(FacialExpression.SAD, "If you need help bringing the culprit to justice, you let me know.") + .endWith { _, player -> + setAttribute(player, ZogreFleshEaters.attributeAskedAboutTankard, true) + } + branch.onValue(1) + .playerl("Hello again. Can you tell me what you know about this tankard again please?") + .npcl("Oh yes, Brentle's tankard. Yeah, you've shown me this already. It belonged to Brentle Vahn, he was quite a common customer, though I've not seen him in a while.") + .npcl("He was talking to some shifty looking wizard the other day. I don't know his name, but I'd recognise him if I saw him.") + .npcl(FacialExpression.SAD, "If you need help bringing the culprit to justice, you let me know.") + .end() + } + + b.onPredicate { _ -> dialogueNum == 2 } + .iteml(Items.SITHIK_PORTRAIT_4814, "You show the portrait to the Inn keeper.") + .npcl("Yeah, that's the guy who was talking to Brentle Vahn the other day! Look at those eyes, never a more shifty looking pair will you ever see!") + .playerl("Hmm, you've just identified the man who I think sent Brentle Vahn to his death.") + .playerl("I'm trying to bring him to justice with the Wizards' Guild grand secretary. Do you think you could sign this portrait to say that he was talking to Brentle Vahn.") + .npcl("I can and I will!") + .betweenStage { df, player, _, _ -> + if (removeItem(player, Items.SITHIK_PORTRAIT_4814)) { + addItemOrDrop(player, Items.SIGNED_PORTRAIT_4816) + } + } + .iteml(Items.SIGNED_PORTRAIT_4816, "The Dragon Inn bartender signs the portrait.") + .playerl("Many thanks for your help, it's really very good of you.") + .npcl("Not at all, just doing my part.") + .end() + + + b.onPredicate { _ -> dialogueNum == 3 } + .iteml(Items.SITHIK_PORTRAIT_4815, "You show the sketch to the Inn keeper.") + .npcl("Who's that? I mean, I guess it's a picture of a person isn't it? Sorry...you've got me? And before you ask, you're not putting it up on my wall!") + .playerl("It's a portrait of Sithik Ints...don't you recognise him?") + .npcl("I'm sorry, I really am, but I just don't see it...can you make a better picture?") + .playerl("I'll try...") + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrishDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrishDialogue.kt new file mode 100644 index 000000000..7e518f0ff --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrishDialogue.kt @@ -0,0 +1,184 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import content.region.kandarin.quest.templeofikov.TempleOfIkov +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class GrishDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return GrishDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GrishDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.GRISH_2038) + } +} +class GrishDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(ZogreFleshEaters.questName, 0) + .playerl(FacialExpression.FRIENDLY, "Hello there, what's going on here?") + .npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...wha's you's doing here? Yous be cleverer to be running so da sickies from da zogres don't dead ya.") + + .let { builder -> + val returnJoin = b.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("I'm just looking around thanks.") + .npcl(FacialExpression.OLD_NORMAL, "Yous creature won'ts see muchly in dis place...just da zogries coming wiv da sickies.") + .goto(returnJoin) + optionBuilder.option_playerl("What do you mean sickies?") + .npc(FacialExpression.OLD_NORMAL, "Da zogries comin wiv da sickies...yous get bashed by da", "zogries and get da sickies...den you gonna be like da", "zogries.") + .playerl(FacialExpression.FRIENDLY, "Sorry, I just don't understand...") + .betweenStage { df, player, _, _ -> + animate(npc!!, 2090) + setAttribute(player, ZogreFleshEaters.attributeAskedAboutSickies, true) + } + .npc(FacialExpression.OLD_NORMAL, "Da sickies is when yous creature goes like orange till", "green and then goes 'Urggghhhh!'", "~ Grish imitates falling down with only the white of his", "eyes visible. ~") + .goto(returnJoin); + optionBuilder.option_playerl("What are Zogres?") + .npcl(FacialExpression.OLD_NORMAL, "a Zogres are da bigun nasties wiv da sickies, deys old pals of Grish but deys jig in Jiggig when dey's full home is deep in da dirt, dey's is not da same dead'uns like was before.") + .goto(returnJoin); + optionBuilder.optionIf("Can I help in any way?") { player -> return@optionIf getAttribute(player, ZogreFleshEaters.attributeAskedAboutSickies, false) } + .playerl(FacialExpression.FRIENDLY, "Can I help in any way?") + .branch { player -> + return@branch if (ZogreFleshEaters.requirements(player)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .npcl(FacialExpression.OLD_NORMAL, "Sorry, yous creatures, but yous is too green behind da ears for dis job Grish finks.") + .playerl(FacialExpression.ANGRY, "No, I'm not!") + .npcl(FacialExpression.OLD_ANGRY1, "Yes you are!") + .playerl(FacialExpression.ANGRY, "No, I'm not!") + .npcl(FacialExpression.OLD_ANGRY1, "Yes you are and that's final!") + .end() + branch.onValue(1) + .npcl(FacialExpression.OLD_NORMAL, "Yes creatures...yous does good fings for Grish and learn why Zogries at Jiggig and den get da Zogries back in da ground.") + .playerl("Oh, so you want me to find out why the Zogres have appeared and then find a way of burying them?") + .npcl(FacialExpression.OLD_NORMAL, "Is what Grish says! But dis is da biggy danger fing yous creatures...yous be geddin' sickies most surely...yous needs be ready..wiv da foodies un da glug-glugs.") + .playerl("Right, so you think there's a good chance that I can get ill from this, so I need to get some food and something to drink?") + .npcl(FacialExpression.OLD_NORMAL, "Yea creatures, yous just say what Grish says...not know own wordies creature?") + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Hmm, sorry, it sounds a bit too dangerous.") + .npcl(FacialExpression.OLD_NORMAL, "Yous creature is not a stoopid one...stays out of dere, like clever Grish. Yous can paint circles on chest and be da Shaman too!") + .playerl("Hmm, is it too late to reconsider?") + .end() + optionBuilder.option_playerl("Ok, I'll check things out then and report back.") + .npcl(FacialExpression.OLD_NORMAL, "Is yous creatures really, really sure yous wanna do dis creatures..we's got no glug-glugs for da sickies? We's knows nuffin for da going of da sickies?") + .options() + .let { optionBuilder2 -> + optionBuilder2.option_playerl("Yes, I'm really sure!") + .npcl(FacialExpression.OLD_NORMAL,"Dats da good fing yous creature...yous does Grish a good fing. But yous know dat yous get sickies and mebe get dead!") + .playerl("If that's your idea of a pep talk, I have to say that it leaves a lot to be desired.") + .npcl(FacialExpression.OLD_NORMAL,"Yous creatures is alus says funny stuff...speaks proper like Grish!") + .manualStage() { df, player, _, _ -> + sendDoubleItemDialogue(player, Items.COOKED_CHOMPY_2878, Items.SUPER_RESTORE3_3026, "Grish hands you some food and two potions.") + } + .npcl(FacialExpression.OLD_NORMAL,"Der's yous go creatures...da best me's do for yous...and be back wivout da sickies.") + .endWith { _, player -> + if(getQuestStage(player, ZogreFleshEaters.questName) == 0) { + // Trying to prevent players from spamming to get more super restores. + addItemOrDrop(player, Items.COOKED_CHOMPY_2878, 3) + addItemOrDrop(player, Items.SUPER_RESTORE3_3026, 2) + setQuestStage(player, ZogreFleshEaters.questName, 1) + } + } + optionBuilder2.option_playerl("Hmm, sorry, it sounds a bit too dangerous.") + .npcl(FacialExpression.OLD_NORMAL, "Yous creature is not a stoopid one...stays out of dere, like clever Grish. Yous can paint circles on chest and be da Shaman too!") + .end() + } + } + + } + optionBuilder.option_playerl("Sorry, I have to go.") + .end() + } + } + + b.onQuestStages(ZogreFleshEaters.questName, 1,2,3,4,5,6) + .npcl(FacialExpression.OLD_NORMAL, "Yous creature dun da fing yet? Da zogries going in da dirt full home?") + .playerl("Nope, I haven't figured out why the zogres are here yet.") + .end() + + b.onQuestStages(ZogreFleshEaters.questName, 7) + .npcl(FacialExpression.OLD_NORMAL,"Yous creature dun da fing yet? Da zogries going in da ground?") + .playerl("I found who's responsible for the Zogres being here.") + .npcl(FacialExpression.OLD_NORMAL,"Where is da creature? Me's wants to squeeze him till he's a deadun...") + .playerl("The person responsible is a wizard named 'Sithik Ints' and he's going to be in serious trouble. He told me that the spell which raised the zogres from the ground will last forever.") + .playerl("I'm sorry to say, but you'll have to move the site of your ceremonial dancing somewhere else.") + .npcl(FacialExpression.OLD_NORMAL,"Dat is da bad fing creature...we's needs new Jiggig for da fallin' down jig.") + .playerl("Yes, that's right, you'll need to create a new ceremonial dance area.") + .npcl(FacialExpression.OLD_NORMAL,"Urghhh...not good fing creature, yous gotta get da ogrish old fings for da making new jiggig special. You's creature needs da key for getting in da low bury place.") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.OGRE_GATE_KEY_4839) + } + .iteml(Items.OGRE_GATE_KEY_4839, "Grish gives you a crudely crafted key.") + .playerl("Oh, so you want me to go back in there and look for something for you?") + .npcl(FacialExpression.OLD_NORMAL,"Yeah creature, yous gotta get da ogrish old fings for da making new jiggig and proper in da special way.") + .endWith { _, player -> + if(getQuestStage(player, ZogreFleshEaters.questName) == 7) { + setQuestStage(player, ZogreFleshEaters.questName, 8) + } + } + + b.onQuestStages(ZogreFleshEaters.questName, 8) + .npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?") + .branch { player -> + return@branch if (inInventory(player, Items.OGRE_GATE_KEY_4839)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .playerl("Nope, not yet.") + .npcl(FacialExpression.OLD_NORMAL, "Yous gets 'em quick tho, cos we'ze wonna do da new Jiggig place...") + .end() + branch.onValue(0) + .playerl("I lost the key you gave me.") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.OGRE_GATE_KEY_4839) + } + .iteml(Items.OGRE_GATE_KEY_4839, "Grish gives you a crudely crafted key.") + .end() + } + + b.onQuestStages(ZogreFleshEaters.questName, 9) + .branch { player -> + return@branch if (inInventory(player, Items.OGRE_ARTEFACT_4818)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?") + .playerl("No sorry, I don't have them yet.") + .npcl(FacialExpression.OLD_NORMAL, "Yous creatures get dem for me soon doh, yes?") + .end() // There's all the default dialogue here, but I'm lazy again. + + branch.onValue(1) + .npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?") + .playerl("Yeah, I have them here!") + .npcl(FacialExpression.OLD_NORMAL, "Dat is da goodly fing yous creature, now's we's can make da new Jiggig place away from zogries! Yous been da big helpy fing yous creature, Grish wishin' yous good stuff for da next fings for creature.") + .npcl(FacialExpression.OLD_HAPPY, "~ Grish seems very pleased about the return of the artefacts. ~") + .playerl("Thanks, that's very nice of you!") + .endWith { _, player -> + if (removeItem(player, Items.OGRE_ARTEFACT_4818)) { + if (getQuestStage(player, ZogreFleshEaters.questName) == 9) { + finishQuest(player, ZogreFleshEaters.questName) + } + } + } + } + + b.onQuestStages(ZogreFleshEaters.questName, 100) + .playerl("How's everything going now?") + .npcl(FacialExpression.OLD_NORMAL,"All da zogries stayin' in da oldie Jiggig, we's gonna do da new Jiggig someways else. Yous creature da good- un for geddin' da oldie fings...") + // More default dialogue, but lazy. + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrugDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrugDialogue.kt new file mode 100644 index 000000000..6081288cf --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/GrugDialogue.kt @@ -0,0 +1,31 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.openDialogue +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class GrugDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return GrugDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, GrugDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.GRUG_2041) + } +} +class GrugDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .npcl(FacialExpression.OLD_NORMAL, "Ukk...I's dun fer...me's don't feel legsies anymore!") + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/JiggigListeners.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/JiggigListeners.kt new file mode 100644 index 000000000..718e26efc --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/JiggigListeners.kt @@ -0,0 +1,27 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.FacialExpression +import core.game.interaction.InteractionListener +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class JiggigListeners : InteractionListener { + override fun defineListeners() { + on(Scenery.OGRE_COFFIN_6848, SCENERY, "open") { player, node -> + // https://youtu.be/HnRcW2iM8es + replaceScenery(node as core.game.node.scenery.Scenery, Scenery.OGRE_COFFIN_6890, 10) + return@on true + } + + on(NPCs.UGLUG_NAR_2039, NPC, "trade") { player, node -> + if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { + openNpcShop(player, NPCs.UGLUG_NAR_2039) + } else { + sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.", FacialExpression.OLD_NORMAL) + } + return@on true + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/OgreGuardDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/OgreGuardDialogue.kt new file mode 100644 index 000000000..6f5193687 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/OgreGuardDialogue.kt @@ -0,0 +1,73 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.QueueStrength +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class OgreGuardDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return OgreGuardDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, OgreGuardDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.OGRE_GUARD_2042) + } +} +class OgreGuardDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(ZogreFleshEaters.questName, 0) + .npcl(FacialExpression.OLD_NORMAL, "Yous needs ta stay away from dis place... yous get da sickies and mebe yous goes to dead if yous da unlucky fing.") + .playerl("Ok, thanks.") + .end() + + b.onQuestStages(ZogreFleshEaters.questName, 1) + .npcl(FacialExpression.OLD_NORMAL, "Yous needs ta stay away from dis place... yous get da sickies and mebe yous goes to dead if yous da unlucky fing.") + .playerl(FacialExpression.FRIENDLY, "But Grish has asked me to look into this place and find out why all the undead ogres are here.") + .npcl(FacialExpression.OLD_NORMAL, "Ok, dat is da big, big scary, danger fing! You's sure you's wants to go in?") + .playerl(FacialExpression.FRIENDLY, "Yes, I'm sure.") + .npcl(FacialExpression.OLD_NORMAL, "Ok, I opens da stoppa's for yous creature.") + .endWith { _, player -> + lock(player, 4) + face(npc!!, Location(2456, 3049, 0)) + // Lesson learnt here, endWith kills the npc object so tie the queueScript with the npc instead, not the player. + queueScript(npc!!, 2, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + animate(npc!!, 2102) + return@queueScript delayScript(npc!!, Animation(2102).duration) + } + 1 -> { + if(getQuestStage(player, ZogreFleshEaters.questName) == 1) { + setQuestStage(player, ZogreFleshEaters.questName, 2) + } + setVarbit(player, ZogreFleshEaters.varbitGateBashed, 1) + unlock(player) + face(npc!!, player.location) + sendNPCDialogue(player, NPCs.OGRE_GUARD_2042, "Ok der' yous goes!", FacialExpression.OLD_NORMAL) + return@queueScript stopExecuting(npc!!) + } + else -> return@queueScript stopExecuting(npc!!) + } + } + } + + b.onQuestStages(ZogreFleshEaters.questName, 2,3,4,5,6,7,8,9,10,100) + .npcl(FacialExpression.OLD_NORMAL, "Hey yous tryin' not to get da sickies else yous be da sick-un and mebe get to be a dead-un if yous be da unlucky fing.") + .playerl(FacialExpression.FRIENDLY, "Don't worry, I know how to take care of myself.") + .end() + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/PilgDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/PilgDialogue.kt new file mode 100644 index 000000000..6eee48feb --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/PilgDialogue.kt @@ -0,0 +1,31 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class PilgDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return PilgDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, PilgDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.PILG_2040) + } +} +class PilgDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onPredicate { _ -> true } + .npcl(FacialExpression.OLD_NORMAL, "Dey got me in da belly, mees gutsies feel like had a dead dead dog dinner.") + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SithikIntsDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SithikIntsDialogue.kt new file mode 100644 index 000000000..789251861 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SithikIntsDialogue.kt @@ -0,0 +1,388 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import core.tools.END_DIALOGUE +import core.tools.RandomFunction +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +/** This NPC is a scenery. */ +//@Initializable +//class SithikIntsDialogue (player: Player? = null) : DialoguePlugin(player) { +// override fun newInstance(player: Player): DialoguePlugin { +// return SithikIntsDialogue(player) +// } +// override fun handle(interfaceId: Int, buttonId: Int): Boolean { +// openDialogue(player, SithikIntsDialogueFile(), npc) +// return false +// } +// override fun getIds(): IntArray { +// return intArrayOf(NPCs.SITHIK_INTS_2061, NPCs.SITHIK_INTS_2062) +// } +//} +class SithikIntsDialogue : InteractionListener { + override fun defineListeners() { + on(Scenery.SITHIK_INTS_6888, SCENERY, "talk-to") { player, node -> + openDialogue(player, SithikIntsDialogueFile(), NPC(NPCs.SITHIK_INTS_2061)) + return@on true + } + on(Scenery.SITHIK_INTS_6889, SCENERY, "talk-to") { player, node -> + openDialogue(player, SithikIntsOgreFormDialogueFile(), NPC(NPCs.SITHIK_INTS_2062)) + return@on true + } + + on(Scenery.DRAWERS_6875, SCENERY, "search") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ } + 1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE } + } + } + }) + } else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 && + (!inInventory(player, Items.BOOK_OF_PORTRAITURE_4817) || + !inInventory(player, Items.PAPYRUS_970) || + !inInventory(player, Items.CHARCOAL_973) + )) { + if (hasSpaceFor(player, Item(Items.BOOK_OF_PORTRAITURE_4817, 3))) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> { + if (!inInventory(player, Items.PAPYRUS_970) && !inInventory(player, Items.CHARCOAL_973)) { + sendDoubleItemDialogue(player, Items.CHARCOAL_973, Items.PAPYRUS_970, "You find some charcoal and papyrus.") + addItemOrDrop(player, Items.PAPYRUS_970) + addItemOrDrop(player, Items.CHARCOAL_973) + stage++ + } else if (!inInventory(player, Items.PAPYRUS_970)) { + sendItemDialogue(player, Items.PAPYRUS_970, "You find some papyrus.") + addItemOrDrop(player, Items.PAPYRUS_970) + stage++ + } else if (!inInventory(player, Items.CHARCOAL_973)) { + sendItemDialogue(player, Items.CHARCOAL_973, "You find some charcoal.") + addItemOrDrop(player, Items.CHARCOAL_973) + stage++ + } else { + sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You also find a book on portraiture.") + addItemOrDrop(player, Items.BOOK_OF_PORTRAITURE_4817) + stage = END_DIALOGUE + } + } + 1 -> { + sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You also find a book on portraiture.") + addItemOrDrop(player, Items.BOOK_OF_PORTRAITURE_4817) + stage = END_DIALOGUE + } + } + } + }) + } else { + sendDialogue(player, "You see some items in the drawer, but you need 3 free inventory spaces to take them.") + } + } else { + sendMessage(player, "You search but find nothing of significance.") + } + return@on true + } + + on(Scenery.CUPBOARD_6876, SCENERY, "search") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ } + 1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE } + } + } + }) + } else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 && !inInventory(player, Items.NECROMANCY_BOOK_4837)) { + if (hasSpaceFor(player, Item(Items.NECROMANCY_BOOK_4837))) { + addItemOrDrop(player, Items.NECROMANCY_BOOK_4837) + sendItemDialogue(player, Items.NECROMANCY_BOOK_4837, "You find a book on Necromancy.") + setAttribute(player, ZogreFleshEaters.attributeFoundNecromanticBook, true) + } else { + sendDialogue(player, "You see an item in the cupboard, but you don't have space to put it in your inventory.") + } + } else { + sendMessage(player, "You search but find nothing of significance.") + } + return@on true + } + + onUseWith(IntType.SCENERY, Items.NECROMANCY_BOOK_4837, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player,"Aha! A necromantic book! What's this doing here then?").also { stage++ } + 1 -> sendItemDialogue(player, Items.NECROMANCY_BOOK_4837, "You show the Necromantic book to Sithik.").also { stage++ } + 2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh..I'm not quite sure actually...where did you find that then?").also { stage++ } + 3 -> sendPlayerDialogue(player,"I found it in this cupboard! What do you have to say for yourself?").also { stage++ } + 4 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh yes, that's right...I remember now. It's for my research, there's nothing really dangerous about it, unless it falls into the wrong hands. I'm sure it's pretty safe with me.").also { stage++ } + 5 -> sendPlayerDialogue(player,"Hmmm, likely story!").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + on(Scenery.WARDROBE_6877, SCENERY, "search") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ } + 1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE } + } + } + }) + } else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 && !inInventory(player, Items.BOOK_OF_HAM_4829)) { + if (hasSpaceFor(player, Item(Items.BOOK_OF_HAM_4829))) { + addItemOrDrop(player, Items.BOOK_OF_HAM_4829) + sendItemDialogue(player, Items.BOOK_OF_HAM_4829, "You find a book on Philosophy written by the 'Human's Against Monsters' leader, Johanhus Albrect.") + setAttribute(player, ZogreFleshEaters.attributeFoundHamBook, true) + } else { + sendDialogue(player, "You see an item in the wardrobe, but you don't have space to put it in your inventory.") + } + } else { + sendMessage(player, "You search but find nothing of significance.") + } + return@on true + } + + onUseWith(IntType.SCENERY, Items.BOOK_OF_HAM_4829, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player,"What's this then?").also { stage++ } + 1 -> sendItemDialogue(player, Items.BOOK_OF_HAM_4829, "You show the HAM book to Sithik.").also { stage++ } + 2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "What do you mean? It's a book by the respected HAM leader Johanhus Ulsbrecht, that man speaks for a lot of people who are unhappy with the current state of affairs.").also { stage++ } + 3 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Can you honestly tell me that you've not had to fight for your life against the odd monster or two?").also { stage++ } + 4 -> sendPlayerDialogue(player,"Hmm, that may be true, but I don't universally hate all monsters, whereas I have a sneaking suspicion that you do...and ogres in particular!").also { stage++ } + 5 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmm, that's an interesting theory, care to back it up with any facts?").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + onUseWith(IntType.SCENERY, Items.PAPYRUS_970, Scenery.SITHIK_INTS_6888) { player, used, with -> + if(inInventory(player, Items.CHARCOAL_973)) { + if (removeItem(player, used)) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh lovely! You're making my portrait! Let me see it afterwards!", FacialExpression.FRIENDLY).also { stage++ } + 1 -> sendDialogue(player, "You begin sketching the irritable Sithik.").also { animate(player, 909); stage++ } + 2 -> { + val skill = Skills.CRAFTING + val level: Int = getDynLevel(player, skill) + getFamiliarBoost(player, skill) + val ratio = RandomFunction.getSkillSuccessChance(0.0, 80.0, level) + + if (ratio > 0.5) { + // Passed + sendItemDialogue(player, Items.SITHIK_PORTRAIT_4814, "You get a portrait of Sithik.") + addItemOrDrop(player, Items.SITHIK_PORTRAIT_4814) + } else { + // Failed + sendItemDialogue(player, Items.SITHIK_PORTRAIT_4815, "You get a portrait of Sithik.") + addItemOrDrop(player, Items.SITHIK_PORTRAIT_4815) + } + setAttribute(player, ZogreFleshEaters.attributeMadePortrait, true) + stage = END_DIALOGUE + } + } + } + }) + } + } else { + sendDialogue(player, "You have no charcoal with which to sketch this subject.") + } + return@onUseWith true + } + + onUseWith(IntType.SCENERY, Items.BOOK_OF_PORTRAITURE_4817, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player,"Oh, so explain this then?").also { stage++ } + 1 -> sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You show the book on portraiture to Sithik.").also { stage++ } + 2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "It's my hobby...I'm interested in portraiture, but all art in general. It's fun, you should try it.").also { stage++ } + 3 -> sendPlayerDialogue(player,"How do I do it...").also { stage++ } + 4 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Well...you could start by reading the book!").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + onUseWith(IntType.SCENERY, Items.SITHIK_PORTRAIT_4814, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player, "Here you go, what do you think?").also { stage++ } + 1 -> sendItemDialogue(player, Items.SITHIK_PORTRAIT_4814, "You show the sketch...").also { stage++ } + 2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmmm, well it's not the most flattering of portraits, but I like the 'honesty' of the work...well done.").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + onUseWith(IntType.SCENERY, Items.SITHIK_PORTRAIT_4815, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player, "Here you go, what do you think?").also { stage++ } + 1 -> sendItemDialogue(player, Items.SITHIK_PORTRAIT_4815, "You show the sketch...").also { stage++ } + 2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmmm, well it's an interesting interpretation, but not really classic realist representation is it? It's not my favourite, but I like the 'truth' of the work...well done.").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + on(Items.CUP_OF_TEA_4838, ITEM, "take") { player, node -> + sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing? Leave my tea alone!", FacialExpression.ANNOYED) + return@on true + } + + onUseWith(IntType.SCENERY, Items.STRANGE_POTION_4836, Scenery.SITHIK_INTS_6888) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendPlayerDialogue(player,"Here, try some of this potion, it'll make you feel better!").also { stage++ } + 1 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Err, yuck...no way am I taking any potions or medication off you...I don't trust you!").also { stage = END_DIALOGUE } + } + } + }) + return@onUseWith true + } + + onUseWith(IntType.GROUNDITEM, Items.STRANGE_POTION_4836, Items.CUP_OF_TEA_4838) { player, _, with -> + if(getQuestStage(player, ZogreFleshEaters.questName) == 5) { + if (removeItem(player, Items.STRANGE_POTION_4836)) { + sendItemDialogue(player, Items.STRANGE_POTION_4836, "You pour some of the potion into the cup. Zavistic said it may take some time to have an effect.") + addItemOrDrop(player, Items.SAMPLE_BOTTLE_3377) + } + setQuestStage(player, ZogreFleshEaters.questName, 6) + } + return@onUseWith true + } + } +} + +class SithikIntsDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(ZogreFleshEaters.questName, 0, 1, 2) + .npcl(FacialExpression.ANNOYED, "Hey... who gave you permission to come in here! Get out, get out I say.") + .playerl("Alright, alright... keep your night cap on.") + .end() + + b.onQuestStages(ZogreFleshEaters.questName, 3, 4, 5, 6) + .npcl(FacialExpression.ANNOYED, "Hey... who gave you permission to come in here! Get out, get out I say.") + .playerl("Zavistic Rarve said that I could come and talk to you and ask you a few questions.") + .betweenStage { df, player, _, _ -> + if (getQuestStage(player, ZogreFleshEaters.questName) == 3) { + setQuestStage(player, ZogreFleshEaters.questName, 4) + } + } + .npcl(FacialExpression.ANNOYED, "Oh, Zavistic...why...why would he send you to me?") + + .let { builder -> + val returnJoin = b.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Do you know anything about the undead ogres at Jiggig?") + .npcl("Er...undead ogres...no, sorry, no idea what you're talking about there.") + .playerl("Hmm, is that right...") + .npcl("Well, yes, yes it is. If I knew something, I'd tell you.") + .npcl("Anyway, dead ogres you say? How strange? That must be a strange sight?") + .playerl("Very well, if you don't know anything about it, you won't mind if I look around then?") + .npcl("Well,err....well, actually yes I do mind...it's my place and I don't want strangers going through my things.") + .goto(returnJoin) + + optionBuilder.option_playerl("What do you do?") + .npcl("I'm a scholarly student of the magical arts. When I was younger I used to be an adventurer, probably just like yourself. But I lost interest in the constant fighting, looting and gaining abilities.") + .npcl("Instead I decided to focus my attention and time to study the purer form of the lost arts.") + .playerl("The lost arts? What are they?") + .npcl("Ignorant people call them the 'dark arts'. I'm talking about Necromancy, the power to bring the dead back to life - the power of the gods! Surely the most awesome power known to man.") + .playerl("Hmm, well I guess I must be an ignorant person then, because bringing the dead back to life sounds very unnatural.") + .goto(returnJoin) + + optionBuilder.option_playerl("Do you mind if I look around?") + .npcl("Well,err....well, actually yes I do mind...it's my place and I don't want strangers going through my things.") + .playerl("Well, I'm going to have a look around anyway, if you're not involved in this whole thing, you won't have anything to hide.") + .npcl("Why, if I was a few years younger I'd give you a good hiding!") + .playerl("I'm sure!") + .goto(returnJoin) + + optionBuilder.option_playerl("Ok, thanks.") + .end() + } + builder.goto(returnJoin) + } + } +} + +class SithikIntsOgreFormDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(ZogreFleshEaters.questName, 7,8,9,100) + /* + There are some after first time dialogue, but who reads this... + .npcl("Arghhhh..what do you want now...you've turned me into a beast!") + .playerl("I've got some questions for you...and you'd better answer them well or else!") + .npcl("Ok, ok, I'll tell you anything, just turn me back into a human again!") + */ + .npcl(FacialExpression.OLD_DEFAULT, "Arghhhh..what's happened to me...you beast!") + .playerl("It's your own fault, you shouldn't have lied about your involvement with the undead Ogres at Jiggig. The potion will wear off once you've told the truth!") + .npcl(FacialExpression.OLD_DEFAULT, "Ok, ok, I admit it, I got Brentle Vahn to cast the spell to put an end to those awful Ogres...they're just disgusting creatures...") + .playerl("Ok, that's a start...now I want some answers.") + .let { builder -> + val returnJoin = b.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option("How do I remove the effects of the spell from the area?") + .playerl("How do I remove the effects of the spell from the area? The ogres want to get their ceremonial dance area back and can't do that with undead walking all over it.") + .npcl(FacialExpression.OLD_DEFAULT, "Unfortunately you can't. The spell is permanent, it will last forever, the only option you have is to move the ceremonial area.") + .playerl("You're an evil man and I'm going to make you pay for this...you can stay like that forever as far as I'm concerned.") + .npcl(FacialExpression.OLD_DEFAULT, "No...no, let me try to make amends...please I can help you. Just don't leave me like this.") + .goto(returnJoin) + + optionBuilder.option_playerl("How do I get rid of the undead ogres?") + .npcl(FacialExpression.OLD_DEFAULT, "Ok, similar spells have been cast before and the only way to deal with the resulting creatures is to cordon off the area and not go in there again.") + .npcl(FacialExpression.OLD_DEFAULT, "The undead creatures usually manifest some sort of disease so it's best to attack them from a distance with a ranged weapon.") + .npcl(FacialExpression.OLD_DEFAULT, "Normal missiles like arrows and darts do very little damage to them because they're designed to destroy internal organs. This is a waste of time with undead creatures like undead ogres.") + .playerl("Yeah, clearly so what should we use?") + .npcl(FacialExpression.OLD_DEFAULT, "From my research it looks like a flat ended arrow was designed called a 'Brutal arrow'. This does large amounts of crushing damage to the creature. You can make them by using larger arrows.") + .npcl(FacialExpression.OLD_DEFAULT, "I think some Ogre hunters make them. But instead of adding an arrow tip, you hammer a large nail into the end of the shaft.") + .goto(returnJoin) + + optionBuilder.option_playerl("How do I get rid of the disease?") + .npcl(FacialExpression.OLD_DEFAULT, "My research shows that two jungle based herbs can be used, one is found near river tributaries and looks like a vine, the other is found in caves and grows on the wall.") + .npcl(FacialExpression.OLD_DEFAULT, "It's quite well camouflaged so it's unlikely that you'll find it.") + .playerl("We'll see about that!") + .goto(returnJoin) + + optionBuilder.option_playerl("Sorry, I have to go.") + .npcl(FacialExpression.OLD_DEFAULT, "But...you can't just leave me here like this!") + .end() + } + builder.goto(returnJoin) + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SkogreBehavior.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SkogreBehavior.kt new file mode 100644 index 000000000..4b309bbc9 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SkogreBehavior.kt @@ -0,0 +1,39 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.getOrStartTimer +import core.api.inEquipment +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.system.timer.impl.Disease +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class SkogreBehavior : NPCBehavior(*skogreIds) { + companion object { + private val skogreIds = intArrayOf( + NPCs.SKOGRE_2050, + NPCs.SKOGRE_2056, + NPCs.SKOGRE_2057, + ) + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) { + return + } + state.estimatedHit = (state.estimatedHit * 0.25).toInt() + if (state.secondaryHit > 0) { + state.secondaryHit = (state.secondaryHit * 0.25).toInt() + } + } + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + val disease = getOrStartTimer(victim, 10) + disease.hitsLeft = 10 + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SlashBashBehavior.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SlashBashBehavior.kt new file mode 100644 index 000000000..169984ce0 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/SlashBashBehavior.kt @@ -0,0 +1,92 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import content.global.handlers.item.equipment.special.DragonfireSwingHandler +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.combat.CombatSwingHandler +import core.game.node.entity.combat.MultiSwingHandler +import core.game.node.entity.combat.equipment.SwitchAttack +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.system.timer.impl.Disease +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.tools.RandomFunction +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class SlashBashBehavior : NPCBehavior(NPCs.SLASH_BASH_2060) { + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + if (attacker is Player) { + if (attacker == getAttribute(self, "target", null)) { + return true + } + sendMessage(attacker, "It's not after you...") + } + return false + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + if (victim is Player) { + val disease = getOrStartTimer(victim, 25) + disease.hitsLeft = 25 + } + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) { + return + } + state.estimatedHit = (state.estimatedHit * 0.25).toInt() + if (state.secondaryHit > 0) { + state.secondaryHit = (state.secondaryHit * 0.25).toInt() + } + } + } + + override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { + super.onDropTableRolled(self, killer, drops) + if (killer is Player && getQuestStage(killer, ZogreFleshEaters.questName) == 8) { + drops.add(Item(Items.ZOGRE_BONES_4812, 2)) + drops.add(Item(Items.OURG_BONES_4834, 3)) + drops.add(Item(Items.OGRE_ARTEFACT_4818)) + setQuestStage(killer, ZogreFleshEaters.questName, 9) + removeAttribute(killer, ZogreFleshEaters.attributeSlashBashInstance) + } + } + + var clearTime = 0 + override fun tick(self: NPC): Boolean { + val player: Player? = getAttribute(self, "target", null) + // You have 500 ticks to kill this guy + if (clearTime++ > 500) { + poofClear(self) + clearTime = 0 + if (player != null) { + removeAttribute(player, ZogreFleshEaters.attributeSlashBashInstance) + } + + } + return true + } + + /** MELEE Swing */ + private val COMBAT_HANDLER = MultiSwingHandler(SwitchAttack(CombatStyle.MELEE.swingHandler, Animation(359))) + /** RANGE Swing (Projectile) */ + private val COMBAT_HANDLER_FAR = MultiSwingHandler(SwitchAttack(CombatStyle.RANGE.swingHandler, Animation(359), Graphics(499))) + + override fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler): CombatSwingHandler { + val victim = self.properties.combatPulse.getVictim() ?: return original + if (victim !is Player) return original + + return if (victim.location.getDistance(self.location) >= 2) + COMBAT_HANDLER_FAR + else + COMBAT_HANDLER + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/UglugNarDialogue.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/UglugNarDialogue.kt new file mode 100644 index 000000000..aab0bfee9 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/UglugNarDialogue.kt @@ -0,0 +1,78 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class UglugNarDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return UglugNarDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, UglugNarDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.UGLUG_NAR_2039) + } +} +class UglugNarDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(ZogreFleshEaters.questName, 0) + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Hey, what's going on here?") + .npcl(FacialExpression.OLD_NORMAL, "Dem's dead ogre's come out of the ground...dey's makin' da rest of us into sick-ums ...and dead-uns.") + .playerl("That doesn't sound good!") + .npcl(FacialExpression.OLD_NORMAL, "Grish want's da person go down der - see what's what!") + .end() + optionBuilder.option_playerl("What are you selling?") + .npcl(FacialExpression.OLD_NORMAL, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.") + .end() + optionBuilder.option_playerl("Ok, thanks.") + .end() + } + + b.onQuestStages(ZogreFleshEaters.questName, 1,2,3,4,5,6,7,8,9,10,100) + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("Hello again.") + .branch { player -> + return@branch if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...yous did good fings gedin that glug-glugs for da sickies! All is ogries pepels are not gettin dead cos of you.") + .end() + branch.onValue(0) + .npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...yous still here?") + .playerl("Yeah, I'm going to help Grish by figuring out what went on here.") + .npcl(FacialExpression.OLD_NORMAL, "If yous finds somefin for da sickies, yous brings to me...and I's give you bright pretties, den me make more for alls pepels.") + .playerl("Hmm, ok. I'll try to bear that in mind.") + .end() + } + + optionBuilder.option_playerl("What are you selling?") + .branch { player -> + return@branch if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl(FacialExpression.OLD_NORMAL, "Me's showin' you da stufsies for yous creatures!") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + branch.onValue(0) + .npcl(FacialExpression.OLD_NORMAL, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.") + .end() + } + + optionBuilder.option_playerl("Ok, thanks.") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZavisticRarveDialogueFile.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZavisticRarveDialogueFile.kt new file mode 100644 index 000000000..1954334b1 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZavisticRarveDialogueFile.kt @@ -0,0 +1,290 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.item.Item +import org.rs09.consts.Items + +class ZavisticRarveDialogueFile : DialogueBuilderFile() { + + companion object { + private fun hasEvidences(player: Player): Int { + var count = 0 + if (inInventory(player, Items.NECROMANCY_BOOK_4837)) { count++ } + if (inInventory(player, Items.BOOK_OF_HAM_4829)) { count++ } + if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { count++ } + if (inInventory(player, Items.SIGNED_PORTRAIT_4816)) { count++ } + return count + } + + fun dialogueBlackPrismAndTornPage(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("There's some undead ogre activity over at Jiggig, I've found some clues, I wondered if you'd have a look at them.") + .manualStage() { df, player, _, _ -> + sendDoubleItemDialogue(player, Items.BLACK_PRISM_4808, Items.TORN_PAGE_4809, "You show the prism and the necromantic half page to the aged wizard.") + } + .npcl("Hmmm, now this is interesting! Where did you get these from?") + .playerl("I got them from a nearby Ogre tomb, it's recently been infested with zombie ogres and I'm trying to work out what happened there.") + .npcl("This is very troubling @name, very troubling indeed. While it's permitted for learned members of our order to research the 'dark arts', it's absolutely forbidden to make use of such magic.") + .playerl("Do you have any leads on people that I might talk to regarding this?") + .npcl("Well a wizard by the name of 'Sithik Ints' was doing some research in this area. He may know something about it. He's lodged at that guest house to the North, though he's ill and isn't able to leave his room.") + .npcl("Why not go and talk to him, poke around a bit and see if anything comes up. Let me know how you get on. However, I doubt that 'Sithik' had anything to do with it.") + .npcl("Hmm, that black prism seems to have some magical protection. Once you've finished with this item, bring it back to me would you. I may have a reward for you.") + } + + fun dialogueGoodPortrait(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Look, I made a portrait of Sithik.") + .iteml(Items.SITHIK_PORTRAIT_4814, "You show the portrait of Sithik to Zavistic.") + .npcl("Hmm, great...but I already know what he looks like!") + } + + fun dialogueBadPortrait(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Look, I made a portrait of Sithik.") + .iteml(Items.SITHIK_PORTRAIT_4815, "You show the sketch...") + .npcl("Who the demonikin is that? Is it meant to be a portrait of Sithik, it doesn't look anything like him!") + } + + // Too lazy to do this, but this gets mentioned whenever you've shown him one of the evidence (but not all). + fun dialogueSeenEvidenceBefore(builder: DialogueBuilder): DialogueBuilder { + return builder + .npcl("Yeah, you've shown me this before...if this is all the evidence you have?") + .playerl("Please just look at it again...") + .npcl("Ok, let me look then.") + } + } + + override fun create(b: DialogueBuilder) { + b.onQuestStages(ZogreFleshEaters.questName, 2) + .let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) } + .branch { player -> + return@branch if (inInventory(player, Items.BLACK_PRISM_4808) && inInventory(player, Items.TORN_PAGE_4809) ) { + 3 + } else if (inInventory(player, Items.BLACK_PRISM_4808) ) { + 2 + } else if (inInventory(player, Items.TORN_PAGE_4809) ) { + 1 + } else { + 0 + } + }.let { branch -> + branch.onValue(3) + .let{ dialogueBlackPrismAndTornPage(it) } + .endWith { _, player -> + if(getQuestStage(player, ZogreFleshEaters.questName) == 2) { + setQuestStage(player, ZogreFleshEaters.questName, 3) + } + } + + branch.onValue(2) + .playerl("There's some undead ogre activity over at 'Jiggig', and the ogres have asked me to look into it. I think I've found a clue and I wonder if you could take a look at it for me?") + .iteml(Items.BLACK_PRISM_4808, "You show the black prism to the aged wizard.") + .npcl("Hmmm, well this is an uncommon spell component. On its own it's useless, but with certain necromantic spells it can be very powerful. Did you find anything else there?") + .branch { player -> + return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { 1 } else { 0 } + }.let { branch2 -> + val returnJoin = b.placeholder() + branch2.onValue(0) + .goto(returnJoin) + branch2.onValue(1) + .iteml(Items.DRAGON_INN_TANKARD_4811, "You show the tankard to Zavistic.") + .playerl("Well, I found this...") + .npcl("Hmmm, no, that's not really associated with this to be honest. Did you find anything else there?") + .goto(returnJoin) + return@let returnJoin.builder() + } + .playerl("Not really.") + .npcl("I don't know what to say then, there isn't enough to go on with the clues you've shown me so far. I'd suggest going back to search a bit more, but you may just be wasting your time?") + .npcl("Hmm, but this prism does seem to have some magical protection. Once you've finished with this item, bring it back to me would you? I may have a reward for you!") + .playerl("Sure...I mean, I'll try if I remember.") + .end() + + branch.onValue(1) + .playerl("There's some undead ogre activity over at Jiggig, I've found a clue that you may be able to help with.") + .iteml(Items.TORN_PAGE_4809, "You show the necromantic half page to the aged wizard.") + .npcl("Hmm, this is a half torn spell page, it requires another spell component to be effective. Did you find anything else there?") + .branch { player -> + return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { 1 } else { 0 } + }.let { branch2 -> + val returnJoin = b.placeholder() + branch2.onValue(0) + .goto(returnJoin) + branch2.onValue(1) + .iteml(Items.DRAGON_INN_TANKARD_4811, "You show the tankard to Zavistic.") + .playerl("Well, I found this...") + .npcl("Hmmm, no, that's not really associated with this to be honest. Did you find anything else there?") + .goto(returnJoin) + return@let returnJoin.builder() + } + .playerl("Not really.") + .npcl("I don't know what to say then, there isn't enough to go on with the clues you've shown me so far. I'd suggest going back to search a bit more, but you may just be wasting your time?") + .end() + + branch.onValue(0) + .let { builder -> + content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder) + } + } + + + b.onQuestStages(ZogreFleshEaters.questName, 3,4) + .let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) } + .let { builder -> + val returnJoin = b.placeholder() + builder.goto(returnJoin) + return@let returnJoin.builder().options() + .let { optionBuilder -> + val continuePath = b.placeholder() + optionBuilder.option("What did you say I should do?") + .playerl("What did you say I should do?") + .npcl("You should go and have a chat with Sithik Ints, he's in that house just to the north. He's a lodger and has a room upstairs. Just tell him that I sent you to see him. He should be fine once you've mentioned my name.") + .goto(returnJoin) + optionBuilder.option_playerl("Where is Sithik?") + .npcl("He's in that house just to the north, less than a few seconds walk away. He's a lodger and has a room upstairs...he's not very well though.") + .goto(returnJoin) + optionBuilder.optionIf("I have an item that I'd like you to look at.") { player -> return@optionIf hasEvidences(player) == 1 } + .goto(continuePath) + optionBuilder.optionIf("I have an item that I'd like you to look at.") { player -> return@optionIf hasEvidences(player) > 1 } + .goto(continuePath) + optionBuilder.option("I want to ask about the magic guild") + .let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(it) } + optionBuilder.option_playerl("Sorry, I have to go.") + .end() + + return@let continuePath.builder() + } + } + .branch { player -> + return@branch if (inInventory(player, Items.NECROMANCY_BOOK_4837) ) { 1 } else { 0 } + }.let { branch -> + val continuePath = b.placeholder() + branch.onValue(1) + .iteml(Items.NECROMANCY_BOOK_4837, "You show the Necromancy book to Zavistic.") + .playerl("I have this necromancy book as evidence that Sithik is involved with the undead ogres at Jiggig.") + .npcl("Ok, so he's researching necromancy...it doesn't mean anything in itself.") + .playerl("Yes, but if you look, you can see that there is a half torn page which matches the page I found at Jiggig.") + .npcl("Hmm, yes, but someone could have stolen that from him and then gone and cast it without his permission or to try and deliberately implicate him.") + .goto(continuePath) + branch.onValue(0) + .goto(continuePath) + return@let continuePath.builder() + } + .branch { player -> + return@branch if (inInventory(player, Items.BOOK_OF_HAM_4829) ) { 1 } else { 0 } + }.let { branch -> + val continuePath = b.placeholder() + branch.onValue(1) + .iteml(Items.BOOK_OF_HAM_4829, "You show the HAM book to Zavistic.") + .playerl("Look, this book proves that Sithik hates all monsters and most likely Ogres with a passion.") + .npcl("So what, hating monsters isn't a crime in itself...although I suppose that it does give a motive if Sithik was involved. On its own, it's not enough evidence though.") + .goto(continuePath) + branch.onValue(0) + .goto(continuePath) + return@let continuePath.builder() + } + .branch { player -> + return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811) ) { 1 } else { 0 } + }.let { branch -> + val continuePath = b.placeholder() + branch.onValue(1) + .iteml(Items.DRAGON_INN_TANKARD_4811, "You show the dragon Inn Tankard to Zavistic.") + .playerl("This is the tankard I found on the remains of Brentle Vahn!") + .npcl("That doesn't mean anything in itself, you could have gotten that from anywhere. Even from the Dragon Inn tavern! There isn't anything to link Brentle Vahn with Sithik Ints.") + .goto(continuePath) + branch.onValue(0) + .goto(continuePath) + return@let continuePath.builder() + } + .branch { player -> + return@branch if (inInventory(player, Items.SIGNED_PORTRAIT_4816) ) { 1 } else { 0 } + }.let { branch -> + val continuePath = b.placeholder() + branch.onValue(1) + .iteml(Items.SIGNED_PORTRAIT_4816, "You show the signed portrait of Sithik to Zavistic.") + .playerl("This is a portrait of Sithik, signed by the landlord of the Dragon Inn saying that he saw Sithik and Brentle Vahn together.") + .npcl("Hmmm, well that is interesting.") + .goto(continuePath) + branch.onValue(0) + .goto(continuePath) + return@let continuePath.builder() + } + .branch { player -> + return@branch if (hasEvidences(player) == 4) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .npcl("However, there isn't enough evidence for me to take the issue further at this point. If you find any further evidence bring it to me.") + .end() + return@let branch + } + .onValue(1) + .npcl("And I'm starting to think that Sithik may be involved. Here, take this potion and give some to Sithik. It'll bring on a change which should solicit some answers - tell him the effects won't revert until he's told the truth.") + .iteml(Items.STRANGE_POTION_4836 ,"Zavistic hands you a strange looking potion bottle and takes all the evidence you've accumulated so far.") + .endWith { _, player -> + if(getQuestStage(player, ZogreFleshEaters.questName) in 3..4) { + if (removeItem(player, Items.NECROMANCY_BOOK_4837) && + removeItem(player, Items.BOOK_OF_HAM_4829) && + removeItem(player, Items.DRAGON_INN_TANKARD_4811) && + removeItem(player, Items.SIGNED_PORTRAIT_4816)) { + addItemOrDrop(player, Items.STRANGE_POTION_4836) + } + setQuestStage(player, ZogreFleshEaters.questName, 5) + } + } + b.onQuestStages(ZogreFleshEaters.questName, 5) + .let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) } + .npcl("Have you used that potion yet?") + .branch { player -> + return@branch if (inInventory(player, Items.STRANGE_POTION_4836) ) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .playerl("No, not yet, what was I supposed to do again?") + .npcl("Try to use the potion on Sithik somehow, he should undergo an interesting transformation, though you'll probably want to leave the house in case there are any side effects. Then go back and question Sithik and tell") + .npcl("him the effects won't wear off until he tells the truth. In fact, that's not exactly true, but I'm sure it'll be an extra incentive to get him to be honest.") + .let { builder -> + content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder) + } + branch.onValue(0) + .playerl("Well, actually, I've lost it, could I have another one please?") + .npcl("Sure, but don't lose it this time.") + .iteml(Items.STRANGE_POTION_4836 ,"Zavistic hands you a bottle of strange potion.") + .endWith { _, player -> + addItemOrDrop(player, Items.STRANGE_POTION_4836) + } + } + + + b.onQuestStages(ZogreFleshEaters.questName, 6,7,8,9) + .let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) } + .npcl("Don't you worry about Sithik, he's not likely to be moving from his bed for a long time. When he eventually does get better, he's going to be sent before a disciplinary tribunal, then we'll sort out what's what.") + .playerl("Thanks for your help with all of this.") + .npcl("Ooohh, no thanks required. It's I who should be thanking you my friend...your investigative mind has shown how vigilant we really should be for this type of evil use of the magical arts.") + .let { builder -> + content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder) + } + } +} + +/** Dialogues when you use stuff on him. */ +class ZavisticRarveUseItemsDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + // SITHIK_PORTRAIT_4814 + b.onPredicate { _ -> dialogueNum == 3 } + .let{ZavisticRarveDialogueFile.dialogueGoodPortrait(it)} + .end() + + // SITHIK_PORTRAIT_4815 + b.onPredicate { _ -> dialogueNum == 4 } + .let{ZavisticRarveDialogueFile.dialogueBadPortrait(it)} + .end() + + // SIGNED_PORTRAIT_4816 + b.onPredicate { _ -> dialogueNum == 5 } + // That would continue the conversation as above if you normally talk to him. + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreBehavior.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreBehavior.kt new file mode 100644 index 000000000..1e00271d5 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreBehavior.kt @@ -0,0 +1,47 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.getOrStartTimer +import core.api.inEquipment +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.system.timer.impl.Disease +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class ZogreBehavior : NPCBehavior(*zogreIds) { + companion object { + private val zogreIds = intArrayOf( + NPCs.ZOGRE_2044, + NPCs.ZOGRE_2045, + NPCs.ZOGRE_2046, + NPCs.ZOGRE_2047, + NPCs.ZOGRE_2048, + NPCs.ZOGRE_2049, + NPCs.ZOGRE_2051, + NPCs.ZOGRE_2052, + NPCs.ZOGRE_2053, + NPCs.ZOGRE_2054, + NPCs.ZOGRE_2055, + ) + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) { + return + } + state.estimatedHit = (state.estimatedHit * 0.25).toInt() + if (state.secondaryHit > 0) { + state.secondaryHit = (state.secondaryHit * 0.25).toInt() + } + } + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + val disease = getOrStartTimer(victim, 10) + disease.hitsLeft = 10 + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEaters.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEaters.kt new file mode 100644 index 000000000..6ed8c9010 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEaters.kt @@ -0,0 +1,353 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import content.data.Quests +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items + +/** + * Zogre Flesh Eaters Quest + * + * 1 - Talked to Grish + * 2 - Smashed Barricade + * 2 Cont' - Collected Stuff Underground + * A - Black Prism from Coffin + * B - Half Torn Page from Broken Lecturn + * C - Tankard from Backpack (Kill the Zombie which turns out to be Brentle Vahn) + * 3 - Talked to Zavistic Rarve with A & B only, points to where Sithik Ints is + * 4 - Talked to Sithik and challenged to incriminate him + * 4 Cont' - Collected Evidence + * A - Tankard from 2C after talking to Innkeeper + * B - Portrait of Sithik using papyrus and charcoal with questionable drawing skills + * C - Book of HAM philosophy from drawer + * D - Necromantic book + * 5 - Incriminate Sithik to Zavistic Rarve and given potion + * 6 - Turned Sithik into an Ogre with potion + * 7 - Talked to Grish + * 8 - Get Key from Grish + * 9 - Killed Slash Bash + * 100 - Returned to Grish with Ogre Artifact + * + * This quest journal is the worst; there's typos, and it is out of order. + * + * if (VARPBIT[487] > 12) return 2; if (VARPBIT[487 == 0) return 0; return 1; }; + * define_varbit 487 455 0 4 + * + */ +@Initializable +class ZogreFleshEaters : Quest(Quests.ZOGRE_FLESH_EATERS, 40, 39, 1, 455, 0, 1, 13) { + companion object { + val questName = Quests.ZOGRE_FLESH_EATERS + const val varbitGateBashed = 496 + const val varbitOgreCoffin = 488 + const val varbitSithikOgre = 495 + + const val attributeAskedAboutSickies = "quest:zogreflesheaters-askedaboutsickies" + + // 2A + const val attributeSearchedCoffin = "/save:quest:zogreflesheaters-searchedcoffin" + const val attributeBrokeLockCoffin = "/save:quest:zogreflesheaters-brokelockcoffin" + const val attributeOpenedCoffin = "/save:quest:zogreflesheaters-openedcoffin" // You can fail apparently... + const val attributeFoundBlackPrism = "/save:quest:zogreflesheaters-foundblackprism" + // 2B + const val attributeFoundHalfTornPage = "/save:quest:zogreflesheaters-foundhalftornpage" + // 2C + const val attributeFoughtZombie = "/save:quest:zogreflesheaters-foughtzombie" + const val attributeFoundTankard = "/save:quest:zogreflesheaters-foundtankard" + // 4A + const val attributeAskedAboutTankard = "quest:zogreflesheaters-askedabouttankard" + // 4B + const val attributeMadePortrait = "/save:quest:zogreflesheaters-madeportrait" + // 4C + const val attributeFoundHamBook = "/save:quest:zogreflesheaters-foundhambook" + // 4D + const val attributeFoundNecromanticBook = "/save:quest:zogreflesheaters-foundnecromanticbook" + + const val attributeSlashBashInstance = "/save:quest:zogreflesheaters-slashbashinstance" + + // Open Uglug Nar Shop with Relicym balm + const val attributeOpenUglugNarShop = "/save:quest:zogreflesheaters-openuglugnarshop" + + fun requirements(player: Player): Boolean { + return arrayOf( + hasLevelStat(player, Skills.RANGE, 30), + hasLevelStat(player, Skills.SMITHING, 4), + hasLevelStat(player, Skills.HERBLORE, 8), + isQuestComplete(player, Quests.JUNGLE_POTION), + isQuestComplete(player, Quests.BIG_CHOMPY_BIRD_HUNTING), + ).all { it } + } + } + + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 11 + var stage = getStage(player) + + var started = getQuestStage(player, questName) > 0 + + if (!started) { + line(player, "I can !!start?? this quest by talking to !!Grish?? at the Ogrish", line++, false) + line(player, "ceremonial dance place called !!Jiggig??.", line++, false) + line(player, "To start this !!quest?? I should complete these quests:-", line++, false) + line(player, "!!Jungle Potion.??", line++, isQuestComplete(player, Quests.JUNGLE_POTION)) + line(player, "!!Big Chompy Bird Hunting.??", line++, isQuestComplete(player, Quests.BIG_CHOMPY_BIRD_HUNTING)) + line(player, "It would help if I had the following skills levels:-", line++, false) + line(player, "!!Ranged level : 30??", line++, hasLevelStat(player, Skills.RANGE, 30)) + line(player, "!!Fletching level : 30??", line++, hasLevelStat(player, Skills.FLETCHING, 30)) + line(player, "!!Smithing level : 4??", line++, hasLevelStat(player, Skills.SMITHING, 4)) + line(player, "!!Herblore level : 8??", line++, hasLevelStat(player, Skills.HERBLORE, 8)) + line(player, "Must be able to defeat a !!level 111?? foe.", line++, false) + } else if (stage < 100) { + + line(player, "I started this quest by talking to Grish, he asked me to", line++, true) + line(player, "check out the underground area where some Zombie ogres", line++, true) + line(player, "(Zogres) were coming from.", line++, true) + + if (stage >= 2) { + line(player, "I have to find a way into the ceremonial dance area and", line++, true) + line(player, "then underground.", line++, true) + line(player, "I persuaded a guard to let me past, I only had to mention", line++, true) + line(player, "Grish's name and the guard smashed the barricade down. I", line++, true) + line(player, "can enter now.", line++, true) + } else if (stage >= 1) { + line(player, "I have to find a way into the ceremonial dance area and", line++, false) + line(player, "then underground.", line++, false) + } + + if (stage >= 2) { + // Set 2A (Stays) + if (getAttribute(player, attributeFoundBlackPrism, false) || stage >= 3) { + line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true) + line(player, "side.", line++, true) + line(player, "I have forced the lock on a coffin, maybe I can open it", line++, true) + line(player, "now?", line++, true) + line(player, "I've !!opened?? the !!coffin?? and retrieved a !!black prism??, this", line++, stage >= 3) + line(player, "may be useful.", line++, stage >= 3) + } else if (getAttribute(player, attributeOpenedCoffin, false)) { + line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true) + line(player, "side.", line++, true) + line(player, "I have forced the lock on a coffin, maybe I can open it", line++, true) + line(player, "now?", line++, true) + line(player, "I've !!opened?? the !!coffin??, maybe there's something in it.", line++, false) + } else if (getAttribute(player, attributeBrokeLockCoffin, false)) { + line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true) + line(player, "side.", line++, true) + line(player, "I have forced the lock on a !!coffin??, maybe I can open it", line++, false) + line(player, "now?", line++, false) + } else if (getAttribute(player, attributeSearchedCoffin, false)) { + line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true) + line(player, "side.", line++, true) + } + } + + if (stage >= 2) { + // Set 2B (Stays) + if (getAttribute(player, attributeFoundHalfTornPage, false) || stage >= 3) { + line(player, "I found a !!half torn page?? from a !!necromatic spellbook??,", line++, stage >= 3) + line(player, "maybe this is a !!clue???", line++, stage >= 3) + } + } + + // 4 - This is the weirdest shit that is out of place. (Stays) This appears after talking to Sithik Int. + if (stage >= 4) { + line(player, "I have shown the prism and torn page to the grand", line++, true) + line(player, "secretary of the wizards guild.", line++, true) + } + + // Set 2C (Does not stay) + if (stage in 2..4 && getAttribute(player, attributeFoundTankard, false)) { + line(player, "I killed a !!human zombie?? which dropped a !!backpack??. The", line++, stage >= 3) + line(player, "!!backpack?? had the name !!'B. Vahn'?? on it, inside the !!backpack??", line++, stage >= 3) + line(player, "I found a !!tankard??.", line++, stage >= 3) + } else if (stage in 2..4 && getAttribute(player, attributeFoughtZombie, false)) { + line(player, "I killed a !!human zombie?? which dropped a !!backpack??.", line++, stage >= 3) + } + + // Stays until you find all the 3X stuff above. + if (stage in 2..4 && !(getAttribute(player, attributeFoundBlackPrism, false) && + getAttribute(player, attributeFoundHalfTornPage, false) && + getAttribute(player, attributeFoundTankard, false))) { + line(player, "I need to find out what happened here.", line++, false) // Cleared when the 3 sets above are done. + } + + // Set 4A (Does not stay) + if (stage in 2..4 && getAttribute(player, attributeAskedAboutTankard, false)) { + line(player, "The 'Dragon Inn' !!Innkeeper?? says the tankard belongs to", line++, false) + line(player, "one of his locals called !!Brentle Vahn??. He was seen talking", line++, false) + line(player, "to a !!wizard?? the other day.", line++, false) // Cleared after handed in with the rest + } + + // 3 Zavistic Rarve seen prism and page - lines disappears right after... + if (stage == 3) { + line(player, "I have shown the !!prism?? and the !!necromantic page?? to", line++, false) + line(player, "Zavistic Rarve. He's told me about a !!wizard?? named", line++, false) + line(player, "!!Sithik Ints?? who might have some information.", line++, false) + } + + // 4 Spoken with Sithik + if (stage >= 4) { + line(player, "I've spoken to !!Sithik??, I need to see if he was !!involved??", line++, stage >= 5) + line(player, "with the !!Undead Ogres at 'Jiggig'?? in some way.", line++, stage >= 5) + } + + // Only stays for 4 + if (stage == 4) { + if (getAttribute(player, attributeMadePortrait, false)) { + line(player, "I've made a !!portrait?? of !!Sithik??...not sure what this will do?", line++, false) + } + if (getAttribute(player, attributeFoundHamBook, false)) { + line(player, "I've found a !!book?? on !!HAM philosophy??...what does this prove?", line++, false) + } + if (getAttribute(player, attributeFoundNecromanticBook, false)) { + line(player, "I've found a !!necromantic book??...what does this prove?", line++, false) + } + } + + // 4 - Who the hell knows why this is here. (Stays) This appears after getting the potion. + if (stage >= 5) { + line(player, "I've talked to Zavistic Rarve regarding the prism and the", line++, true) + line(player, "torn page, he gave some information on a student called", line++, true) + line(player, "Sithik Ints, he may know more about what's happening", line++, true) + line(player, "here.", line++, true) + } + + // Beyond this is legit + if (stage >= 5) { + line(player, "Zavistic has given me some sort of !!potion??, apparently I", line++, stage >= 6) + line(player, "need to give it to !!Sithik??.", line++, stage >= 6) + } + + if (stage >= 7) { + line(player, "I came back into Sithik's room to find that he had been", line++, true) + line(player, "turned into an Ogre!", line++, true) + } else if (stage >= 6) { + line(player, "I have put some of the !!potion?? into !!Sithik's tea??, the !!potion??", line++, false) + line(player, "will take some time to act. Perhaps I should !!get out of??", line++, false) + line(player, "!!here?? in case there are any !!side effects???", line++, false) + } + + if (stage >= 8) { + line(player, "Sithik has told me how to make 'brutal arrows', which", line++, true) + line(player, "should be more effective against Zogres.", line++, true) + + line(player, "Sithik has given me some pointers on how I can make a", line++, true) + line(player, "cure disease potion, though I'm still not sure exactly which", line++, true) + line(player, "herbs I should use.", line++, true) + } else if (stage >= 7) { + line(player, "!!Sithik?? has told me that there is no way I can remove the", line++, false) + line(player, "effects of the !!necromantic curse spell?? from the !!Jiggig??", line++, false) + line(player, "area. I'll have to go back and let !!Grish?? know.", line++, false) + + line(player, "!!Sithik?? has told me how to make !!'brutal arrows'??, which", line++, false) + line(player, "should be more !!effective?? against !!Zogres??.", line++, false) + + line(player, "!!Sithik?? has given me some pointers on how I can make a", line++, false) + line(player, "!!cure disease potion??, though I'm still not sure exactly which", line++, false) + line(player, "!!herbs?? I should use.", line++, false) + } + + if (stage >= 9) { + line(player, "I've told Grish to relocated the dance area, but he needs", line++, true) + line(player, "me to get something from the tomb to so that he can do", line++, true) // "tomb to so" is authentic [sic] + line(player, "this.", line++, true) + line(player, "I need to go back into the tomb and look for some 'old'", line++, true) + line(player, "items that Grish has asked for.", line++, true) + line(player, "I should return the !!artifact?? to !!Grish??.", line++, false) + } else if (stage >= 8) { + line(player, "I've told Grish to relocated the dance area, but he needs", line++, true) + line(player, "me to get something from the tomb to so that he can do", line++, true) // "tomb to so" is authentic [sic] + line(player, "this.", line++, true) + line(player, "I need to go back into the !!tomb?? and look for some !!'old'??", line++, false) + line(player, "!!items?? that !!Grish?? has asked for.", line++, false) + } + + } else { + // The ending is COMPLETELY replaced from this entire shitshow of a quest log. + line(player, "I talked to Grish in the Jiggig area which is swarming with", line++, true) + line(player, "Zombie Ogres (Zogres) These disgusting creatures carry", line++, true) + line(player, "disease and are quite dangerous so the Ogres weren't", line++, true) + line(player, "too keen to try and sort them out.", line++, true) + + line(player, "I talked to an ogre called Grish who asked me to look into", line++, true) + line(player, "the problem. After some searching around in a tomb, I", line++, true) + line(player, "found some clues which pointed me to the human", line++, true) + line(player, "habitation of Yannile.", line++, true) + + line(player, "With the help of Zavistic Rarve, the grand secretary of", line++, true) + line(player, "the Wizards guild I was able to piece the clues together", line++, true) + line(player, "and discover that a Wizard named 'Sithik Ints' was", line++, true) + line(player, "responsible.", line++, true) + + line(player, "Unfortunately I couldn't remove the curse from the area,", line++, true) + line(player, "however, I was able to return some important artefacts to", line++, true) + line(player, "Grish, who can now set up a new ceremonial dance area for", line++, true) + line(player, "the ogres of Gu' Tanoth.", line++, true) + + line(player, "Sithik Ints also told me how to make Brutal arrows which are", line++, true) + line(player, "more effective against Zogres, and he also told me how to", line++, true) + line(player, "make a disease balm.", line++, true) + line++ + line(player,"QUEST COMPLETE!", line) + } + } + + override fun reset(player: Player) { + setVarp(player, varbitGateBashed, 0, true) + removeAttribute(player, attributeAskedAboutSickies) + removeAttribute(player, attributeSearchedCoffin) + removeAttribute(player, attributeBrokeLockCoffin) + removeAttribute(player, attributeOpenedCoffin) + removeAttribute(player, attributeFoundBlackPrism) + removeAttribute(player, attributeFoundHalfTornPage) + removeAttribute(player, attributeFoughtZombie) + removeAttribute(player, attributeFoundTankard) + removeAttribute(player, attributeAskedAboutTankard) + removeAttribute(player, attributeMadePortrait) + removeAttribute(player, attributeFoundHamBook) + removeAttribute(player, attributeFoundNecromanticBook) + removeAttribute(player, attributeOpenUglugNarShop) + + } + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed Zogre Flesh Eaters!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.OGRE_ARTEFACT_4818, 240, 277, 5) + + drawReward(player,"1 Quest Point.", ln++) + drawReward(player,"Can now make Brutal Arrows", ln++) + drawReward(player,"and cure disease potions.", ln++) + drawReward(player,"2000 Ranged, Fletching and", ln++) + drawReward(player,"Herblore XP", ln++) + + player.skills.addExperience(Skills.RANGE, 2000.0) + player.skills.addExperience(Skills.FLETCHING, 2000.0) + player.skills.addExperience(Skills.HERBLORE, 2000.0) + } + + override fun setStage(player: Player, stage: Int) { + super.setStage(player, stage) + this.updateVarps(player) + } + + override fun updateVarps(player: Player) { + if(getQuestStage(player, questName) >= 2) { + setVarbit(player, varbitGateBashed, 1, true) + } else { + setVarbit(player, varbitGateBashed, 0, true) + } + if(getQuestStage(player, questName) >= 7) { + setVarbit(player, varbitSithikOgre, 1, true) + } else { + setVarbit(player, varbitSithikOgre, 0, true) + } + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEatersListeners.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEatersListeners.kt new file mode 100644 index 000000000..bd16a02b6 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogreFleshEatersListeners.kt @@ -0,0 +1,382 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.world.map.Direction +import core.game.world.map.Location +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class ZogreFleshEatersListeners : InteractionListener { + + companion object { + @JvmStatic + fun ladderMakesSithikTurnIntoOgre(player: Player) { + if(getQuestStage(player, ZogreFleshEaters.questName) == 6) { + setQuestStage(player, ZogreFleshEaters.questName, 7) + setVarbit(player, ZogreFleshEaters.varbitSithikOgre, 1) + } + } + } + + override fun defineListeners() { + // Stairs and doors + on(Scenery.STAIRS_6841, SCENERY, "climb-down") { player, node -> + sendMessage(player, "You climb down the steps.") + if (node.location == Location(2443, 9417, 2)) { + teleport(player, Location(2442, 9417, 0)) + } else { + teleport(player, Location(2477, 9437, 2)) + } + return@on true + } + on(Scenery.STAIRS_6842, SCENERY, "climb-up") { player, node -> + sendMessage(player, "You climb up the steps.") + if (node.location == Location(2443, 9417, 0)) { + teleport(player, Location(2447, 9417, 2)) + } else { + teleport(player, Location(2485, 3045, 0)) + } + return@on true + } + on(Scenery.OGRE_STONE_DOOR_6871, SCENERY, "open") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) >= 9) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else if (inInventory(player, Items.OGRE_GATE_KEY_4839)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + sendMessage(player, "You use the Ogre Tomb Key to unlock the door.") + } else { + sendMessage(player, "The door is locked.") + } + return@on true + } + + on(Scenery.OGRE_STONE_DOOR_6872, SCENERY, "open") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) >= 9) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else if (inInventory(player, Items.OGRE_GATE_KEY_4839)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + sendMessage(player, "You use the Ogre Tomb Key to unlock the door.") + } else { + sendMessage(player, "The door is locked.") + } + return@on true + } + + // Stage 2 + on(Scenery.CRUSHED_BARRICADE_6881, SCENERY, "climb-over") { player, node -> + if (player.location.x < 2456) { + val distance = player.location.getDistance(Location(2457, 3049, 0)).toInt() + forceMove(player, player.location, Location(2457, 3049, 0), 0, distance * 15, null, 1236) + } else { + val distance = player.location.getDistance(Location(2455, 3049, 0)).toInt() + forceMove(player, player.location, Location(2455, 3049, 0), 0, distance * 15, null, 1236) + } + return@on true + } + on(Scenery.CRUSHED_BARRICADE_6882, SCENERY, "climb-over") { player, node -> + if (player.location.x < 2456) { + val distance = player.location.getDistance(Location(2457, 3048, 0)).toInt() + forceMove(player, player.location, Location(2457, 3048, 0), 0, distance * 15, null, 1236) + } else { + val distance = player.location.getDistance(Location(2455, 3048, 0)).toInt() + forceMove(player, player.location, Location(2455, 3048, 0), 0, distance * 15, null, 1236) + } + return@on true + } + + // Stage 2A + on(Scenery.OGRE_COFFIN_6844, SCENERY, "search") { player, node -> + if (getVarbit(player, ZogreFleshEaters.varbitOgreCoffin) == 0) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendDialogueLines(player, "You search the coffin and find a small geometrically shaped hole in", "the side. It looks as if this hole was made with a considerable amount", "of force, maybe the thing which made the hole is still inside?").also { stage++ } + 1 -> sendDialogueLines(player, "The lock looks quite crude, with some skill and a slender blade, you", "may be able to force it.").also { stage = END_DIALOGUE } + } + } + }) + } else if (getVarbit(player, ZogreFleshEaters.varbitOgreCoffin) == 1) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendDialogueLines(player, "The lid looks heavy, but now that you've unlocked it, you may be", "able to lift it. You prepare yourself.").also { stage++ } + 1 -> playerl("Urrrgggg.").also { sendChat(player, "Urrrgggg."); stage++ } + 2 -> playerl("Aarrrgghhh!").also { sendChat(player, "Aarrrgghhh!"); stage++ } + // Supposed to have a failure state here. + 3 -> playerl("Raarrrggggg! Yes!").also { sendChat(player, "Raarrrggggg! Yes!"); stage++ } + 4 -> sendDialogueLines(player, "You eventually manage to lift the lid.").also { + setVarbit(player, ZogreFleshEaters.varbitOgreCoffin, 3, true) + stage = END_DIALOGUE + } + } + } + }) + } + return@on true + } + onUseWith(IntType.SCENERY, Items.KNIFE_946, Scenery.OGRE_COFFIN_6844) { player, _, _ -> + sendItemDialogue(player, Items.KNIFE_946, + "With some skill you manage to slide the blade along the lock edge and click into place the teeth of the primitive mechanism.") + setVarbit(player, ZogreFleshEaters.varbitOgreCoffin, 1, true) + return@onUseWith true + } + + on(Scenery.OGRE_COFFIN_6845, SCENERY, "search") { player, node -> + sendItemDialogue(player, Items.BLACK_PRISM_4808, + "You find a creepy looking black prism inside.") + addItemOrDrop(player, Items.BLACK_PRISM_4808) + return@on true + } + + on(Items.BLACK_PRISM_4808, ITEM, "look-at") { player, node -> + sendItemDialogue(player, Items.BLACK_PRISM_4808, + "It looks like a smokey black gem of some sort...very creepy. Some magical force must have prevented it from being shattered when it hit the coffin.") + return@on true + } + + // Stage 2B + on(Scenery.BROKEN_LECTURN_6846, SCENERY, "search") { player, node -> + sendMessage(player, "You search the broken down lecturn.") + if (inInventory(player, Items.TORN_PAGE_4809)) { + sendMessage(player, "You find nothing.") + } else { + sendItemDialogue(player, Items.TORN_PAGE_4809, + "You find a half torn page...it has spidery writing all over it.") + addItemOrDrop(player, Items.TORN_PAGE_4809) + } + return@on true + } + + on(Items.TORN_PAGE_4809, ITEM, "read") { player, node -> + sendDialogue(player, "You don't manage to understand all of it as there is only a half page here. But it seems the spell was used to place a curse on an area and for all time raise the dead.") + return@on true + } + + // Stage 2C + on(Scenery.SKELETON_6893, SCENERY, "search") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) >= 2){ + if (getAttribute(player, ZogreFleshEaters.attributeFoughtZombie, false)) { + + if (inInventory(player, Items.RUINED_BACKPACK_4810)) { + sendMessage(player, "You find nothing on the corpse.") + } else { + sendMessage(player, "You find another backpack.") + addItemOrDrop(player, Items.RUINED_BACKPACK_4810) + } + } else { + // Zombie time. + sendMessage(player, "Something screams into life right in front of you.") + val npc = NPC(NPCs.ZOMBIE_1826) + npc.isRespawn = false + npc.isWalks = false + npc.location = Location(2442, 9459, 2) + npc.direction = Direction.NORTH + npc.init() + npc.attack(player) + } + } else { + // At no point should this be reached since you need to start the quest anyway. + sendMessage(player, "You find nothing on the corpse.") + } + return@on true + } + on(Items.RUINED_BACKPACK_4810, ITEM, "open") { player, node -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> { + sendItemDialogue(player, Items.RUINED_BACKPACK_4810, + "Just before you open the backpack, you notice a small leather patch with the moniker: 'B.Vahn', on it.").also { stage++ } + sendItemZoomOnInterface(player, 241, 1, Items.RUINED_BACKPACK_4810, 230) + } + 1 -> sendItemDialogue(player, Items.DRAGON_INN_TANKARD_4811, + "You find an interesting looking tankard.").also { + setAttribute(player, ZogreFleshEaters.attributeFoundTankard, true) + if(removeItem(player, node)) { + addItem(player, Items.ROTTEN_FOOD_2959) + addItem(player, Items.KNIFE_946) + addItem(player, Items.DRAGON_INN_TANKARD_4811) + } + stage++ + } + 2 -> sendDoubleItemDialogue(player, Items.KNIFE_946, Items.ROTTEN_FOOD_2959, "You find a knife and some rotten food, the backpack is ripped to shreds.").also { + sendMessage(player, "You find a knife and some rotten food.") + sendMessage(player, "You find an interesting looking tankard.") + stage = END_DIALOGUE + } + } + } + }) + return@on true + } + + + on(Items.DRAGON_INN_TANKARD_4811, ITEM, "look-at") { player, node -> + sendItemDialogue(player, Items.DRAGON_INN_TANKARD_4811, + "A stout ceramic tankard with a Dragon Emblem on the side, the words, 'Ye Olde Dragon Inn' are inscribed in the bottom.") + return@on true + } + + // Zavistic Bell, Stage 2,3,4,5,6 and on (Actually should be standalone. + on(Scenery.BELL_6847, SCENERY, "ring") { player, node -> + sendMessage(player, "You ring the bell.") + // TODO: Make Zavistic appear at the bell area. + openDialogue(player, content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile(), NPC(NPCs.ZAVISTIC_RARVE_2059)) + return@on true + } + + // Stage 4A + onUseWith(IntType.NPC, Items.DRAGON_INN_TANKARD_4811, NPCs.BARTENDER_739) { player, used, with -> + openDialogue(player, BartenderDialogueFile(1), with as NPC) + return@onUseWith true + } + onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4814, NPCs.BARTENDER_739) { player, used, with -> + // The good portrait + openDialogue(player, BartenderDialogueFile(2), with as NPC) + return@onUseWith true + } + onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4815, NPCs.BARTENDER_739) { player, used, with -> + // The bad portrait + openDialogue(player, BartenderDialogueFile(3), with as NPC) + return@onUseWith true + } + on(Items.SIGNED_PORTRAIT_4816, ITEM, "look-at") { player, node -> + sendItemDialogue(player, Items.SIGNED_PORTRAIT_4816, + "You see an image of Sithik with a message underneath 'I, the bartender of the Dragon Inn, do swear that this is a true likeness of the wizzy who was talking to Brentle Vahn, my customer the other day.'") + return@on true + } + onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4814, NPCs.ZAVISTIC_RARVE_2059) { player, used, with -> + // The good portrait + openDialogue(player, ZavisticRarveUseItemsDialogueFile(3), with as NPC) + return@onUseWith true + } + onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4815, NPCs.ZAVISTIC_RARVE_2059) { player, used, with -> + // The bad portrait + openDialogue(player, ZavisticRarveUseItemsDialogueFile(4), with as NPC) + return@onUseWith true + } + + + // Stage 4B + on(Items.BOOK_OF_PORTRAITURE_4817, ITEM, "read") { player, node -> + sendDialogueLines(player, + "All interested artisans should really consider taking up the hobby of", + "portraiture. To do so, one uses a piece of papyrus on the intended", + "subject to initiate a likeness drawing activity.") + return@on true + } + + // Stage 4C + on(Items.BOOK_OF_HAM_4829, ITEM, "read") { player, node -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> { + sendDialogue(player, + "You read this book for a while, it seems to be some sort of political "+ + "manifesto about how the king doesn't do enough to safeguard the "+ + "citizens of the realm from the monsters that still thrive within the "+ + "borders. ").also { stage++ } + // This is the original, but it is too big for this to handle. +// sendDialogueLines(player, +// "You read this book for a while, it seems to be some sort of political", +// "manifesto about how the king doesn't do enough to safeguard the", +// "citizens of the realm from the monsters that still thrive within the", +// "borders. It sends out a rallying to all people who would want to", +// "stop monsters, to join the HAM movement.").also { stage++ } + } + 1 -> sendDialogue(player, "It sends out a rallying to all people who would want to stop monsters, to join the HAM movement.").also { stage++ } + 2 -> sendPlayerDialogue(player, "Hmm, Sithik must really hate monsters then, I wonder if he hates ogres in particular?").also { + stage = END_DIALOGUE + } + } + } + }) + return@on true + } + + // Stage 4D + on(Items.NECROMANCY_BOOK_4837, ITEM, "read") { player, node -> + sendDialogueLines(player, + "This book uses very strange language and some", + "incomprehensible symbols. It has a very dark and evil feeling to", + "it. As you're looking through the book, you notice that", + "one of the pages has been torn and half of it is missing.") + return@on true + } + + onUseWith(IntType.ITEM, Items.NECROMANCY_BOOK_4837, Items.TORN_PAGE_4809) { player, _, _ -> + sendDoubleItemDialogue(player, Items.NECROMANCY_BOOK_4837, Items.TORN_PAGE_4809, + "The torn page matches exactly the part where a torn out page is missing from the book. You feel sure that this page came from this book.") + return@onUseWith true + } + + // Uglug Nar Shop + onUseWith(IntType.NPC, intArrayOf(Items.RELICYMS_BALM1_4848, Items.RELICYMS_BALM2_4846, Items.RELICYMS_BALM3_4844, Items.RELICYMS_BALM4_4842), NPCs.UGLUG_NAR_2039) { player, used, with -> + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> sendItemDialogue(player, used.id,"You show the potion to Uglug Nar.").also { stage++ } + 1 -> playerl("Hey, here you go! I brought you some of the potion which should cure the disease. You said that you would buy some from me.").also { + if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { + stage = 2 + } else { + stage = 3 + } + } + 2 -> sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Yous creatures is da funny ones... yous already solds me's ones now..and us can now sell un to yous!", FacialExpression.OLD_NORMAL).also { stage = END_DIALOGUE } + 3 -> sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Yous creatures done da good fing...yous get many bright pretties for dis...!", FacialExpression.OLD_NORMAL).also { stage++ } + 4 -> sendDoubleItemDialogue(player, Item(Items.COINS_995, 1000), used as Item, "You sell the potion and get 1000 coins in return.").also { + if (removeItem(player, used)) { + addItemOrDrop(player, Items.COINS_995, 1000) + setAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, true) + } + stage = END_DIALOGUE + } + } + } + }) + return@onUseWith true + } + + // Stage 8 to 9 + on(Scenery.STAND_6897, SCENERY, "search") { player, node -> + if (getQuestStage(player, ZogreFleshEaters.questName) == 8 && + getAttribute(player, ZogreFleshEaters.attributeSlashBashInstance, null) == null + ) { + // Zombie time. + sendMessage(player, "Something stirs behind you!") + val npc = NPC(NPCs.SLASH_BASH_2060) + setAttribute(player, ZogreFleshEaters.attributeSlashBashInstance, npc) + setAttribute(npc, "target", player) + npc.isRespawn = false + npc.isWalks = false + npc.location = Location(2478, 9446, 0) + npc.direction = Direction.EAST + npc.init() + npc.attack(player) + } else if (getQuestStage(player, ZogreFleshEaters.questName) > 8) { + if (inInventory(player, Items.OGRE_ARTEFACT_4818)) { + sendMessage(player, "You find nothing on the stand.") + } else { + sendMessage(player, "You find another artifact.") + addItemOrDrop(player, Items.OGRE_ARTEFACT_4818) + } + } else { + // At no point should this be reached since you need to start the quest anyway. + sendMessage(player, "You find nothing on the stand.") + } + return@on true + } + } +} diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogrePotionAndFletchingListeners.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogrePotionAndFletchingListeners.kt new file mode 100644 index 000000000..ca14c0f1c --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZogrePotionAndFletchingListeners.kt @@ -0,0 +1,109 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import org.rs09.consts.Items +import kotlin.math.min + +public enum class BrutalArrows(val nailItem: Int, val level: Int, val product: Int, val exp: Double) { + BRONZE_BRUTAL(Items.BRONZE_NAILS_4819, 7, Items.BRONZE_BRUTAL_4773, 8.4), + IRON_BRUTAL(Items.IRON_NAILS_4820, 18, Items.IRON_BRUTAL_4778, 15.6), + STEEL_BRUTAL(Items.STEEL_NAILS_1539, 33, Items.STEEL_BRUTAL_4783, 30.6), + BLACK_BRUTAL(Items.BLACK_NAILS_4821, 38, Items.BLACK_BRUTAL_4788, 39.0), + MITHRIL_BRUTAL(Items.MITHRIL_NAILS_4822, 49, Items.MITHRIL_BRUTAL_4793, 45.0), + ADAMANT_BRUTAL(Items.ADAMANTITE_NAILS_4823, 62, Items.ADAMANT_BRUTAL_4798, 61.2), + RUNE_BRUTAL(Items.RUNE_NAILS_4824, 77, Items.RUNE_BRUTAL_4803, 75.0) + ; + + companion object { + @JvmField + val nailItemMap = values().associateBy { it.nailItem } + val nailItemArray = nailItemMap.values.map { it.nailItem }.toIntArray() + } +} +/** + * This handles potions and fletching related to zogre flesh eaters. + * + * Relicym's Balm is unique to zogre flesh eaters. + * Maybe move this to herblore when it can handle quest requirements better. + */ +class ZogrePotionAndFletchingListeners : InteractionListener { + + override fun defineListeners() { + // ROGUES_PURSE_POTIONUNF_4840 is already in UnfinishedPotion.java + onUseWith(IntType.ITEM, Items.ROGUES_PURSE_POTIONUNF_4840, Items.CLEAN_SNAKE_WEED_1526) { player, used, with -> + if (!hasLevelStat(player, Skills.HERBLORE, 8)) { + sendMessage(player, "You need a herblore level of 8 to make this mix.") + return@onUseWith true + } + if (getQuestStage(player, ZogreFleshEaters.questName) < 7) { + sendMessage(player, "You need to have partially completed Zogre Flesh Eaters to make this mix.") + return@onUseWith true + } + + if(removeItem(player, used) && removeItem(player, with)) { + sendMessage(player, "You add the snake weed to the rogues purse solution and make Relicyms Balm.") + addItem(player, Items.RELICYMS_BALM4_4842) + rewardXP(player, Skills.HERBLORE, 40.0) + } + return@onUseWith true + } + + // FletchingListeners.kt + // ACHEY_TREE_LOGS_2862 -> UNSTRUNG_COMP_BOW_4825 -> COMP_OGRE_BOW_4827 + // Requirement to wield comp ogre bow. + onEquip(Items.COMP_OGRE_BOW_4827) { player, _ -> + if (getQuestStage(player, ZogreFleshEaters.questName) >= 8){ + return@onEquip true + } + sendMessage(player, "You need to complete part of Zogre Flesh Eaters to equip this.") + return@onEquip false + } + + + onUseWith(IntType.ITEM, BrutalArrows.nailItemArray, Items.FLIGHTED_OGRE_ARROW_2865) { player, used, with -> + fun getMaxAmount(_unused: Int = 0): Int { + val tips = amountInInventory(player, used.id) + val shafts = amountInInventory(player, with.id) + return min(tips, shafts) + } + + fun process() { + val amountThisIter = min(6, getMaxAmount()) + if (removeItem(player, Item(used.id, amountThisIter)) && removeItem(player, Item(with.id, amountThisIter))) { + addItem(player, BrutalArrows.nailItemMap[used.id]!!.product, amountThisIter) + sendMessage(player, "You make $amountThisIter brutal arrows.") + rewardXP(player, Skills.FLETCHING, BrutalArrows.nailItemMap[used.id]!!.exp) + } + } + + if (getQuestStage(player, ZogreFleshEaters.questName) < 7) { + sendMessage(player, "You need to complete part of Zogre Flesh Eaters to make these.") + return@onUseWith true + } + + if (getStatLevel(player, Skills.FLETCHING) < BrutalArrows.nailItemMap[used.id]!!.level) { + sendMessage(player, "You need a Fletching level of " + BrutalArrows.nailItemMap[used.id]!!.level + " to make these.") + return@onUseWith true + } + + sendSkillDialogue(player) { + create { id, amount -> + runTask( + player, + delay = 2, + repeatTimes = min(amount, getMaxAmount() / 6 + 1), + task = ::process + ) + } + calculateMaxAmount(::getMaxAmount) + withItems(Item(BrutalArrows.nailItemMap[used.id]!!.product, 5)) + } + return@onUseWith true + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZombieBrentleVahnBehavior.kt b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZombieBrentleVahnBehavior.kt new file mode 100644 index 000000000..d24485447 --- /dev/null +++ b/Server/src/main/content/region/kandarin/feldip/quest/zogreflesheaters/ZombieBrentleVahnBehavior.kt @@ -0,0 +1,40 @@ +package content.region.kandarin.feldip.quest.zogreflesheaters + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.system.timer.impl.Disease +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +/** The zombie you have to fight when you click on the skeleton. */ +class ZombieBrentleVahnBehavior : NPCBehavior(NPCs.ZOMBIE_1826) { + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + val disease = getOrStartTimer(victim, 10) + disease.hitsLeft = 10 + } + + override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList) { + super.onDropTableRolled(self, killer, drops) + // Drops backpack when killed. + if (killer is Player && getQuestStage(killer, ZogreFleshEaters.questName) in 2..4) { + drops.add(Item(Items.RUINED_BACKPACK_4810)) + setAttribute(killer, ZogreFleshEaters.attributeFoughtZombie, true) + } + } + + var clearTime = 0 + override fun tick(self: NPC): Boolean { + // You have 400 ticks to kill this guy + if (clearTime++ > 400) { + clearTime = 0 + poofClear(self) + } + return true + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java b/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java index 18e653c14..1322bf19c 100644 --- a/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java +++ b/Server/src/main/content/region/kandarin/guilds/WizardGuildPlugin.java @@ -36,7 +36,6 @@ public final class WizardGuildPlugin extends OptionHandler { SceneryDefinition.forId(2155).getHandlers().put("option:open", this); SceneryDefinition.forId(1722).getHandlers().put("option:climb-up", this); new WizardDistentorDialogue().init(); - new ZavisticRarveDialogue().init(); new ProfessorImblewynDialogue().init(); new WizardFrumsconeDialogue().init(); new RobeStoreDialogue().init(); @@ -176,68 +175,6 @@ public final class WizardGuildPlugin extends OptionHandler { } - /** - * Represents the dialogue used for zavistic rarve. - * @author 'Vexia - * @version 1.0 - */ - public final class ZavisticRarveDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code ZavisticRarveDialogue} {@code Object}. - */ - public ZavisticRarveDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code ZavisticRarveDialogue} {@code Object}. - * @param player the player. - */ - public ZavisticRarveDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new ZavisticRarveDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - npc("What are you doing...Oh, it's you...sorry...didn't", "realise... what can I do for you?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - player("Thanks for your help with all of this."); - stage = 1; - break; - case 1: - npc("Ooohh, no thanks required. It's I who should be", "thanking you my friend...your investigative mind has", "shown how vigilant we really should be for this type of", "evil use of the magical arts."); - stage = 2; - break; - case 2: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 2059 }; - } - - } - /** * Represents the wizard distentor dialogue. * @author 'Vexia diff --git a/Server/src/main/content/region/kandarin/yanille/dialogue/ZavisticRarveDialogue.kt b/Server/src/main/content/region/kandarin/yanille/dialogue/ZavisticRarveDialogue.kt new file mode 100644 index 000000000..9ccbedc95 --- /dev/null +++ b/Server/src/main/content/region/kandarin/yanille/dialogue/ZavisticRarveDialogue.kt @@ -0,0 +1,120 @@ +package content.region.kandarin.yanille.dialogue + +import content.region.kandarin.feldip.quest.zogreflesheaters.ZogreFleshEaters +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class ZavisticRarveDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return ZavisticRarveDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, ZavisticRarveDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.ZAVISTIC_RARVE_2059) + } +} +class ZavisticRarveDialogueFile : DialogueBuilderFile() { + + companion object { + fun dialogueInitialTalk(builder: DialogueBuilder) : DialogueBuilder { + return builder + .branch { player -> + return@branch if (getQuestStage(player, ZogreFleshEaters.questName) > 3 /* || hand in the sand quest */) { + 1 + } else { + 0 + } + }.let { branch2 -> + val returnJoin = builder.placeholder() + branch2.onValue(1) + .npcl("What are you doing...Oh, it's you...sorry...didn't realise...what can I do for you?") + // There is a fork here if you are doing hand in the sand. + .goto(returnJoin) + branch2.onValue(0) + .npcl("What are you doing bothering me? Don't you think some of us have work to do?") + .playerl("I thought you were here to help?") + .npcl("Well... I am, I suppose, anyway... we're very busy here, hurry up, what do you want?") + .goto(returnJoin) + return@let returnJoin.builder() + } + } + + fun dialogueInitialTalkViaBell(builder: DialogueBuilder) : DialogueBuilder { + return builder + .branch { player -> + return@branch if (getQuestStage(player, ZogreFleshEaters.questName) > 3 /* || hand in the sand quest */) { + 1 + } else { + 0 + } + }.let { branch2 -> + val returnJoin = builder.placeholder() + branch2.onValue(1) + .npcl("What are you doing...Oh, it's you...sorry...didn't realise...what can I do for you?") + .goto(returnJoin) + branch2.onValue(0) + .npcl("What are you doing ringing that bell?! Don't you think some of us have work to do?") + .playerl("But I was told to ring the bell if I wanted some attention.") + .npcl("Well...anyway...we're very busy here, hurry up what do you want?") + .goto(returnJoin) + return@let returnJoin.builder() + } + } + + fun defaultTalk(continueBuilder: DialogueBuilder) { + continueBuilder.let { builder -> + val returnJoin = builder.placeholder() + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option_playerl("What is there to do in the Wizards' Guild?") + .npcl("This is the finest wizards' establishment in the land.") + .npcl("We have magic portals to the other towers of wizardry around Gielinor.") + .npcl("We have a particularly wide collection of runes in our rune shop.") + .npcl("We sell some of the finest mage robes in the land and we have a training area full of zombies for you to practice your magic on.") + .goto(returnJoin) + optionBuilder.option_playerl("What are the requirements to get in the Wizards' Guild?") + .npcl("You need a magic level of 66, the high magic energy level is too dangerous for anyone below that level.") + .goto(returnJoin) + optionBuilder.option_playerl("What do you do in the Guild?") + .npcl("I'm the Grand Secretary for the Wizards' Guild, I have lots of correspondence to keep up with, as well as attending to the discipline of the more problematic guild members.") + .goto(returnJoin) + optionBuilder.option_playerl("Ok, thanks.") + .end() + } + builder.goto(returnJoin) + } + } + } + + + override fun create(b: DialogueBuilder) { + + b.onPredicate { player -> isQuestComplete(player, ZogreFleshEaters.questName) } + .let { dialogueInitialTalk(it) } + .let { defaultTalk(it) } + + // This is during the ZogreFleshEaters quest + b.onPredicate { player -> isQuestInProgress(player, ZogreFleshEaters.questName, 2, 99) } + .manualStage() { df, player, _, _ -> + openDialogue(player, content.region.kandarin.feldip.quest.zogreflesheaters.ZavisticRarveDialogueFile(), npc!!) + } + .end() + + b.onPredicate { _ -> true } + .let { dialogueInitialTalk(it) } + .let { defaultTalk(it) } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java index 763b7656c..5639c3b20 100644 --- a/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java +++ b/Server/src/main/content/region/karamja/quest/junglepotion/JunglePotion.java @@ -115,7 +115,7 @@ public final class JunglePotion extends Quest { }); } }, - PALM_TREE(2577, Herbs.ARDRIGAL, 20, "You are looking for Ardrigal. It is related to the palm", "and grows in its brothers shady profusion."), SITO_FOIL(2579, Herbs.SITO_FOIL, 30, "You are looking for Sito Foil, and it grows best where", "the ground has been blackened by the living flame."), VOLENCIA_MOSS(2581, Herbs.VOLENCIA_MOSS, 40, "You are looking for Volencia Moss. It clings to rocks", "for its existence. It is difficult to see, so you must", "search for it well."), ROGUES_PURSE(32106, Herbs.ROGUES_PUSE, 50, "It inhabits the darkness of the underground, and grows", "in the caverns to the north. A secret entrance to the", "caverns is set into the northern cliffs, be careful Bwana.") { + PALM_TREE(2577, Herbs.ARDRIGAL, 20, "You are looking for Ardrigal. It is related to the palm", "and grows in its brothers shady profusion."), SITO_FOIL(2579, Herbs.SITO_FOIL, 30, "You are looking for Sito Foil, and it grows best where", "the ground has been blackened by the living flame."), VOLENCIA_MOSS(2581, Herbs.VOLENCIA_MOSS, 40, "You are looking for Volencia Moss. It clings to rocks", "for its existence. It is difficult to see, so you must", "search for it well."), ROGUES_PURSE(32106, Herbs.ROGUES_PURSE, 50, "It inhabits the darkness of the underground, and grows", "in the caverns to the north. A secret entrance to the", "caverns is set into the northern cliffs, be careful Bwana.") { @Override public void search(final Player player, final Scenery object) { final Animation animation = Animation.create(2097); diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 091a196df..ec322b555 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -1818,8 +1818,11 @@ fun sendItemDialogue(player: Player, item: Any, message: String) { * @param item2 the ID of the second item to show * @param message the text to display */ -fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: String) { - player.dialogueInterpreter.sendDoubleItemMessage(item1, item2, message) +fun sendDoubleItemDialogue(player: Player, item1: Any, item2: Any, message: String) { + when (item1) { + is Item -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Item, message) + is Int -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Int, message) + } } /** diff --git a/Server/src/main/core/game/global/action/SpecialLadders.java b/Server/src/main/core/game/global/action/SpecialLadders.java index 96636a068..1e96aec6f 100644 --- a/Server/src/main/core/game/global/action/SpecialLadders.java +++ b/Server/src/main/core/game/global/action/SpecialLadders.java @@ -3,6 +3,7 @@ package core.game.global.action; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.diary.DiaryType; import core.game.world.map.Location; +import content.region.kandarin.feldip.quest.zogreflesheaters.ZogreFleshEatersListeners; import java.util.Arrays; import java.util.HashMap; @@ -80,6 +81,13 @@ public enum SpecialLadders implements LadderAchievementCheck { PATERDOMUS_TEMPLE_STAIRCASE_SOUTH_DOWN(new Location(3415, 3486,1), new Location(3414, 3486,0)), PHASMATYS_BAR_DOWN(new Location(3681,3498,0), new Location(3682,9961,0)), PHASMATYS_BAR_UP(new Location(3682,9962,0), new Location(3681,3497,0)), + YANNILE_HOUSE_DOWN(new Location(2597, 3107,1), new Location(2597, 3107,0)), + YANNILE_HOUSE_UP(new Location(2597, 3107,0), new Location(2597, 3107,1)) { + @Override + public void checkAchievement(Player player) { + ZogreFleshEatersListeners.ladderMakesSithikTurnIntoOgre(player); + } + }, SEERS_VILLAGE_SPINNING_HOUSE_ROOFTOP_UP(new Location(2715,3472,1), new Location(2714,3472,3)) { @Override public void checkAchievement(Player player) { diff --git a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt index 4db7d398f..ec69cdd72 100644 --- a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt @@ -36,18 +36,28 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) { /** * Force animation + messages on all NPCs in a radius of 10 from the player. + * Add an optional 3rd argument if cycling through a range of animation ids. */ - define("npcanim", Privilege.ADMIN, "::npcanim Animation ID") { player, args -> + define("npcanim", Privilege.ADMIN, "::npcanim Animation ID Optional: End Animation ID") { player, args -> if (args.size < 2) { reject(player, "Syntax error: ::npcanim ") } npcs = RegionManager.getLocalNpcs(player.location, 10) for (n in npcs) { - n.sendChat(args.slice(1 until args.size).joinToString(" ")) n.lock(6) n.faceTemporary(player, 6) - n.animator.animate(Animation(args[1].toInt())) - n.animate(Animation.create(-1), 6) + if (args.size == 2) { + n.sendChat(args.slice(1 until args.size).joinToString(" ")) + n.animate(Animation(args[1].toInt())) + n.animate(Animation.create(-1), 6) + } + if (args.size == 3) { + var count = 0 + for(animNum in args[1].toInt()..args[2].toInt()) { + count++ + n.animate(Animation(animNum), count*6) + } + } } } From 104533c11d0c84b866c2d53851f1128f5f22ced2 Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Sun, 16 Feb 2025 07:40:42 +0000 Subject: [PATCH 224/306] Corrected stats, levels and combat styles of many familiars --- Server/data/configs/npc_configs.json | 903 ++++++++++++++++++--------- 1 file changed, 608 insertions(+), 295 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index e7358f0df..ca5e4ad0a 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -61072,17 +61072,21 @@ { "examine": "A bird. Literally terrifying.", "melee_animation": "1010", + "range_animation": "0", + "magic_level": "50", "respawn_delay": "0", - "defence_animation": "1011", - "death_animation": "1012", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "1013", "name": "Spirit terrorbird", - "defence_level": "1", + "defence_level": "50", "safespot": null, "lifepoints": "74", - "strength_level": "1", + "strength_level": "50", "id": "6794", - "range_level": "1", - "attack_level": "1" + "range_level": "50", + "attack_level": "50" }, { "examine": "A bird. Literally terrifying.", @@ -61145,18 +61149,23 @@ "attack_level": "18" }, { + "examine": "Wax on", + "melee_animation": "8069", + "range_animation": "0", + "magic_level": "60", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8065", "name": "Praying mantis", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "10", - "melee_animation": "8064", - "strength_level": "1", + "lifepoints": "107", + "strength_level": "60", "id": "6798", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "8066" + "range_level": "60", + "attack_level": "60" }, { "examine": "Wax on", @@ -61178,18 +61187,23 @@ "attack_level": "60" }, { + "examine": "He ent such a bad guy.", + "melee_animation": "7853", + "range_animation": "0", + "magic_level": "60", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7854", "name": "Giant ent", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "10", - "melee_animation": "7853", - "strength_level": "1", + "lifepoints": "111", + "strength_level": "60", "id": "6800", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7852" + "range_level": "60", + "attack_level": "60" }, { "examine": "He ent such a bad guy.", @@ -61211,18 +61225,23 @@ "attack_level": "60" }, { + "examine": "Serpentine.", + "melee_animation": "8152", + "range_animation": "0", + "magic_level": "55", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8153", "name": "Spirit cobra", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "10", - "melee_animation": "8152", - "strength_level": "1", + "lifepoints": "90", + "strength_level": "55", "id": "6802", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "8154" + "range_level": "55", + "attack_level": "55" }, { "examine": "Serpentine.", @@ -61244,18 +61263,23 @@ "attack_level": "55" }, { + "examine": "Face the thing that should not be!", + "melee_animation": "7786", + "range_animation": "0", + "magic_level": "65", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7780", "name": "Spirit dagannoth", - "defence_level": "1", + "defence_level": "65", "safespot": null, - "lifepoints": "10", - "melee_animation": "7786", - "strength_level": "1", + "lifepoints": "115", + "strength_level": "65", "id": "6804", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7785" + "range_level": "65", + "attack_level": "65" }, { "examine": "Face the thing that should not be!", @@ -61326,19 +61350,24 @@ "attack_level": "19" }, { + "examine": "Kneel before squid!", "combat_style": "2", - "melee_animation": "7970", + "melee_animation": "7963", + "range_animation": "0", + "magic_level": "50", "respawn_delay": "0", - "defence_animation": "7967", - "death_animation": "7979", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "7964", "name": "Karamthulhu overlord", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "82", + "strength_level": "50", "id": "6809", - "range_level": "1", - "attack_level": "1" + "range_level": "50", + "attack_level": "50" }, { "examine": "Kneel before squid!", @@ -61419,23 +61448,28 @@ "defence_animation": "7742" }, { - "combat_style": "1", + "examine": "Definitely not teenaged", + "combat_style": "0", "melee_animation": "8286", + "range_animation": "0", + "magic_level": "55", "respawn_delay": "0", - "defence_animation": "8287", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8285", "name": "War tortoise", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "348", - "strength_level": "1", + "lifepoints": "95", + "strength_level": "55", "id": "6815", - "range_level": "1", - "attack_level": "1" + "range_level": "55", + "attack_level": "55" }, { "examine": "Definitely not teenaged", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8286", "range_animation": "0", "magic_level": "55", @@ -61465,19 +61499,24 @@ "attack_level": "1" }, { + "examine": "It's an extra-planar little blood hoover.", "combat_style": "2", - "melee_animation": "7675", + "melee_animation": "8910", + "range_animation": "0", + "magic_level": "50", "respawn_delay": "0", - "defence_animation": "7670", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7671", "name": "Abyssal parasite", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "77", + "strength_level": "50", "id": "6818", - "range_level": "1", - "attack_level": "1" + "range_level": "50", + "attack_level": "50" }, { "examine": "It's an extra-planar little blood hoover.", @@ -61500,18 +61539,23 @@ "attack_level": "50" }, { + "examine": "Lurking like only a lurker can.", + "melee_animation": "7680", + "range_animation": "0", + "magic_level": "55", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7684", "name": "Abyssal lurker", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "10", - "melee_animation": "7680", - "strength_level": "1", + "lifepoints": "88", + "strength_level": "55", "id": "6820", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7681" + "range_level": "55", + "attack_level": "55" }, { "examine": "Lurking like only a lurker can.", @@ -61638,19 +61682,24 @@ "attack_level": "17" }, { - "examine": "It's mean and green.", + "examine": "It's mean and green!", "melee_animation": "8208", + "range_animation": "0", + "attack_speed": "5", + "magic_level": "55", "respawn_delay": "0", - "defence_animation": "8205", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8209", "name": "Stranger plant", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "91", + "strength_level": "55", "id": "6827", - "range_level": "1", - "attack_level": "1" + "range_level": "55", + "attack_level": "55" }, { "examine": "It's mean and green!", @@ -61712,18 +61761,24 @@ "attack_level": "16" }, { + "examine": "Surprisingly slime-free.", + "combat_style": "1", + "melee_animation": "7795", + "range_animation": "0", + "magic_level": "18", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7797", "name": "Desert wyrm", - "defence_level": "1", + "defence_level": "18", "safespot": null, - "lifepoints": "47", - "melee_animation": "7795", - "strength_level": "1", + "lifepoints": "25", + "strength_level": "18", "id": "6831", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7796" + "range_level": "18", + "attack_level": "18" }, { "examine": "Surprisingly slime-free.", @@ -61747,6 +61802,26 @@ }, { "examine": "If you think he's evil", + "combat_style": "1", + "melee_animation": "8248", + "range_animation": "0", + "magic_level": "42", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8250", + "name": "Evil turnip", + "defence_level": "42", + "safespot": null, + "lifepoints": "60", + "strength_level": "42", + "id": "6833", + "range_level": "42", + "attack_level": "42" + }, + { + "examine": "If you think he's evil", + "combat_style": "1", "melee_animation": "8248", "range_animation": "0", "magic_level": "42", @@ -61764,18 +61839,23 @@ "attack_level": "42" }, { + "examine": "It vants to suck my blood!", + "melee_animation": "8275", + "range_animation": "0", + "magic_level": "31", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8276", "name": "Vampire bat", - "defence_level": "1", + "defence_level": "31", "safespot": null, - "lifepoints": "20", - "melee_animation": "8275", - "strength_level": "1", + "lifepoints": "44", + "strength_level": "31", "id": "6835", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "8274" + "range_level": "31", + "attack_level": "31" }, { "examine": "It vants to suck my blood!", @@ -61797,19 +61877,24 @@ "attack_level": "31" }, { + "examine": "Salt and vinegaroon.", "melee_animation": "6254", + "range_animation": "0", "combat_audio": "3611,3612,3610", + "magic_level": "19", "respawn_delay": "0", - "defence_animation": "6255", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "6256", "name": "Spirit scorpion", - "defence_level": "1", + "defence_level": "19", "safespot": null, - "lifepoints": "67", - "strength_level": "1", + "lifepoints": "27", + "strength_level": "19", "id": "6837", - "range_level": "1", - "attack_level": "1" + "range_level": "19", + "attack_level": "19" }, { "examine": "Salt and vinegaroon.", @@ -61866,6 +61951,7 @@ "lifepoints": "101", "strength_level": "60", "id": "6840", + "bonuses": "90,50,50,60,90,80,50,30,40,100,0,0,0,0,0", "range_level": "60", "attack_level": "60" }, @@ -61911,18 +61997,23 @@ "attack_level": "17" }, { + "examine": "It's like a little suction pump with eyes.", + "melee_animation": "7657", + "range_animation": "0", + "magic_level": "49", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7656", "name": "Bloated leech", - "defence_level": "1", + "defence_level": "49", "safespot": null, - "lifepoints": "10", - "melee_animation": "7657", - "strength_level": "1", + "lifepoints": "70", + "strength_level": "49", "id": "6843", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7655" + "range_level": "49", + "attack_level": "49" }, { "examine": "It's like a little suction pump with eyes.", @@ -61944,18 +62035,23 @@ "attack_level": "49" }, { + "examine": "Violent little so-and-so.", + "melee_animation": "7928", + "range_animation": "0", + "magic_level": "32", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7925", "name": "Honey badger", - "defence_level": "1", + "defence_level": "32", "safespot": null, - "lifepoints": "10", - "melee_animation": "7928", - "strength_level": "1", + "lifepoints": "45", + "strength_level": "32", "id": "6845", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7927" + "range_level": "32", + "attack_level": "32" }, { "examine": "Violent little so-and-so.", @@ -62041,6 +62137,7 @@ "lifepoints": "105", "strength_level": "60", "id": "6850", + "bonuses": "93,90,65,90,30,40,50,50,60,40,0,0,0,0,0", "range_level": "60", "attack_level": "60" }, @@ -62070,7 +62167,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "magic_level": "1", "respawn_delay": "0", @@ -62088,7 +62185,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "range_animation": "0", "magic_level": "1", @@ -62109,7 +62206,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "magic_level": "25", "respawn_delay": "0", @@ -62128,7 +62225,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "range_animation": "0", "magic_level": "25", @@ -62150,7 +62247,7 @@ }, { "examine": "He's just a big bully!", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "magic_level": "28", "respawn_delay": "0", @@ -62168,7 +62265,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "range_animation": "0", "magic_level": "28", @@ -62189,7 +62286,7 @@ }, { "examine": "He's just a big bully", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "magic_level": "30", "respawn_delay": "0", @@ -62208,7 +62305,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "range_animation": "0", "magic_level": "30", @@ -62229,7 +62326,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "attack_speed": "", "magic_level": "35", @@ -62249,7 +62346,7 @@ }, { "examine": "He's just a big bully.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8024", "range_animation": "0", "magic_level": "35", @@ -62304,18 +62401,23 @@ "attack_level": "40" }, { + "examine": "Well", + "melee_animation": "7816", + "range_animation": "0", + "magic_level": "55", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7818", "name": "Smoke devil", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "10", - "melee_animation": "7816", - "strength_level": "1", + "lifepoints": "87", + "strength_level": "55", "id": "6865", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7817" + "range_level": "55", + "attack_level": "55" }, { "examine": "Well", @@ -62337,18 +62439,23 @@ "attack_level": "55" }, { + "examine": "Putting all three of its best feet forward.", + "melee_animation": "7896", + "range_animation": "0", + "magic_level": "40", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7897", "name": "Bull ant", - "defence_level": "1", + "defence_level": "40", "safespot": null, - "lifepoints": "10", - "melee_animation": "7896", - "strength_level": "1", + "lifepoints": "57", + "strength_level": "40", "id": "6867", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7900" + "range_level": "40", + "attack_level": "40" }, { "examine": "Putting all three of its best feet forward.", @@ -62412,19 +62519,24 @@ "attack_level": "1" }, { - "melee_animation": "853", + "examine": "I suppose it could smell worse", + "melee_animation": "7769", + "range_animation": "0", "attack_speed": "5", + "magic_level": "28", "respawn_delay": "0", - "defence_animation": "851", - "death_animation": "852", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "7770", "name": "Compost mound", - "defence_level": "1", + "defence_level": "28", "safespot": null, - "lifepoints": "96", - "strength_level": "1", + "lifepoints": "40", + "strength_level": "28", "id": "6871", - "range_level": "1", - "attack_level": "1" + "range_level": "28", + "attack_level": "28" }, { "examine": "I suppose it could smell worse", @@ -62488,21 +62600,26 @@ "attack_level": "112" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit cockatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6875", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62527,21 +62644,26 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit guthatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6877", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62566,22 +62688,27 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", "combat_audio": "703,705,704", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit saratrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6879", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62607,21 +62734,26 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit zamatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6881", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62646,21 +62778,26 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit pengatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6883", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62685,21 +62822,26 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit coraxatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6885", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62724,21 +62866,26 @@ "attack_level": "43" }, { + "examine": "If looks could kill... Wait", "start_gfx": "1467", "combat_style": "2", "melee_animation": "7762", + "range_animation": "0", + "magic_level": "43", "respawn_delay": "0", - "defence_animation": "7761", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7763", "name": "Spirit vulatrice", - "defence_level": "1", + "defence_level": "43", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "61", + "strength_level": "43", "id": "6887", - "range_level": "1", + "range_level": "43", "projectile": "1468", - "attack_level": "1" + "attack_level": "43" }, { "examine": "If looks could kill... Wait", @@ -62763,20 +62910,23 @@ "attack_level": "43" }, { - "examine": "The only creature with a mouth big enough to hold a cannonball.", + "examine": "The only creature with a mouth big enough to fit a cannon ball into.", "melee_animation": "7260", + "range_animation": "0", "magic_level": "55", "respawn_delay": "0", - "defence_animation": "7257", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7256", "name": "Barker toad", - "defence_level": "1", + "defence_level": "55", "safespot": null, - "lifepoints": "10", + "lifepoints": "94", "strength_level": "55", "id": "6889", "range_level": "55", - "attack_level": "1" + "attack_level": "55" }, { "examine": "The only creature with a mouth big enough to fit a cannon ball into.", @@ -63040,6 +63190,7 @@ "combat_style": "2", "melee_animation": "8304", "attack_speed": "5", + "magic_level": "28", "respawn_delay": "0", "defence_animation": "8306", "death_animation": "8305", @@ -63388,18 +63539,23 @@ "attack_level": "28" }, { + "examine": "On Gielinor", + "melee_animation": "8569", + "range_animation": "0", + "magic_level": "50", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8570", "name": "Spirit jelly", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "melee_animation": "8569", - "strength_level": "1", + "lifepoints": "78", + "strength_level": "50", "id": "6992", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "8571" + "range_level": "50", + "attack_level": "50" }, { "examine": "On Gielinor", @@ -63421,19 +63577,24 @@ "attack_level": "50" }, { + "examine": "Hail to the Queen", "combat_style": "1", - "melee_animation": "8519", + "melee_animation": "6223", + "range_animation": "0", + "magic_level": "25", "respawn_delay": "0", - "defence_animation": "8518", - "death_animation": "8517", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "6228", "name": "Spirit kalphite", - "defence_level": "1", + "defence_level": "25", "safespot": null, - "lifepoints": "77", - "strength_level": "1", + "lifepoints": "35", + "strength_level": "25", "id": "6994", - "range_level": "1", - "attack_level": "1" + "range_level": "25", + "attack_level": "25" }, { "examine": "Hail to the Queen", @@ -65198,7 +65359,7 @@ "attack_level": "1" }, { - "combat_style": "1", + "combat_style": "0", "melee_animation": "8222", "magic_level": "70", "respawn_delay": "0", @@ -65216,7 +65377,7 @@ }, { "examine": "Do you hear duelling banjos?", - "combat_style": "1", + "combat_style": "0", "melee_animation": "8222", "range_animation": "0", "magic_level": "65", @@ -65276,6 +65437,24 @@ "range_level": "25", "attack_level": "28" }, + { + "examine": "It spins.", + "melee_animation": "8172", + "range_animation": "0", + "magic_level": "34", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8176", + "name": "Void spinner", + "defence_level": "34", + "safespot": null, + "lifepoints": "48", + "strength_level": "34", + "id": "7333", + "range_level": "34", + "attack_level": "34" + }, { "examine": "It spins.", "melee_animation": "8172", @@ -65295,21 +65474,28 @@ "attack_level": "34" }, { + "examine": "This one will burn right through the net!", + "combat_style": "1", + "melee_animation": "7863", + "range_animation": "0", + "magic_level": "60", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7864", "name": "Forge regent", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "10", - "melee_animation": "7863", - "strength_level": "1", + "lifepoints": "108", + "strength_level": "60", "id": "7335", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7865" + "range_level": "60", + "attack_level": "60" }, { "examine": "This one will burn right through the net!", + "combat_style": "1", "melee_animation": "7863", "range_animation": "0", "magic_level": "60", @@ -65328,18 +65514,23 @@ "attack_level": "60" }, { + "examine": "Fast cat is fast.", + "melee_animation": "5228", + "range_animation": "0", + "magic_level": "50", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "5230", "name": "Spirit larupia", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "melee_animation": "5228", - "strength_level": "1", + "lifepoints": "81", + "strength_level": "50", "id": "7337", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "5227" + "range_level": "50", + "attack_level": "50" }, { "examine": "Fast cat is fast.", @@ -65362,6 +65553,7 @@ }, { "examine": "It'll kill your enemies, and makes a great cup of tea.", + "combat_style": "1", "melee_animation": "7879", "range_animation": "422", "magic_level": "70", @@ -65383,6 +65575,7 @@ }, { "examine": "It'll kill your enemies, and makes a great cup of tea.", + "combat_style": "1", "melee_animation": "7879", "range_animation": "422", "magic_level": "70", @@ -65404,24 +65597,29 @@ "attack_level": "70" }, { - "combat_style": "1", + "examine": "Made of lava.", + "combat_style": "0", "melee_animation": "7980", + "range_animation": "0", + "magic_level": "65", "respawn_delay": "0", - "defence_animation": "7981", - "death_animation": "7692", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "7979", "name": "Lava titan", - "defence_level": "1", + "defence_level": "65", "safespot": null, - "lifepoints": "528", - "strength_level": "1", + "lifepoints": "115", + "strength_level": "65", "id": "7341", "bonuses": "100,120,90,100,90,90,40,50,0,0,0,0,0,0,0", - "range_level": "1", - "attack_level": "1" + "range_level": "65", + "attack_level": "65" }, { "examine": "Made of lava.", - "combat_style": "1", + "combat_style": "0", "melee_animation": "7980", "range_animation": "0", "magic_level": "65", @@ -65442,6 +65640,7 @@ }, { "examine": "The King of the Titans!", + "combat_style": "1", "melee_animation": "8183", "range_animation": "8183", "magic_level": "70", @@ -65464,6 +65663,7 @@ }, { "examine": "The King of the Titans!", + "combat_style": "1", "melee_animation": "8183", "range_animation": "8183", "magic_level": "70", @@ -65522,18 +65722,23 @@ "attack_level": "60" }, { + "examine": "If a normal black cat is bad luck", + "melee_animation": "5989", + "range_animation": "0", + "magic_level": "60", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "5990", "name": "Talon beast", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "10", - "melee_animation": "5989", - "strength_level": "1", + "lifepoints": "110", + "strength_level": "60", "id": "7347", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "5988" + "range_level": "60", + "attack_level": "60" }, { "examine": "If a normal black cat is bad luck", @@ -65555,18 +65760,23 @@ "attack_level": "60" }, { - "death_animation": "7979", - "name": "Abyssal titan", - "defence_level": "1", - "safespot": null, - "lifepoints": "667", + "examine": "Big", "melee_animation": "7693", - "strength_level": "1", - "id": "7349", - "range_level": "1", + "range_animation": "0", + "magic_level": "70", "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7691" + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "7692", + "name": "Abyssal titan", + "defence_level": "70", + "safespot": null, + "lifepoints": "125", + "strength_level": "70", + "id": "7349", + "range_level": "70", + "attack_level": "70" }, { "examine": "Big", @@ -65589,6 +65799,26 @@ }, { "examine": "It torches.", + "combat_style": "2", + "melee_animation": "8235", + "range_animation": "0", + "magic_level": "34", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8236", + "name": "Void torcher", + "defence_level": "34", + "safespot": null, + "lifepoints": "48", + "strength_level": "34", + "id": "7351", + "range_level": "34", + "attack_level": "34" + }, + { + "examine": "It torches.", + "combat_style": "2", "melee_animation": "8235", "range_animation": "0", "magic_level": "34", @@ -65606,21 +65836,28 @@ "attack_level": "34" }, { + "examine": "Looks a little...volatile.", + "combat_style": "1", + "melee_animation": "7755", + "range_animation": "0", + "magic_level": "29", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7758", "name": "Giant chinchompa", - "defence_level": "1", + "defence_level": "29", "safespot": null, - "lifepoints": "1", - "melee_animation": "7755", - "strength_level": "1", + "lifepoints": "41", + "strength_level": "29", "id": "7353", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7753" + "range_level": "29", + "attack_level": "29" }, { "examine": "Looks a little...volatile.", + "combat_style": "1", "melee_animation": "7755", "range_animation": "0", "magic_level": "29", @@ -65640,6 +65877,7 @@ }, { "examine": "Scorching!", + "combat_style": "2", "melee_animation": "7834", "range_animation": "7834", "attack_speed": "5", @@ -65663,6 +65901,7 @@ }, { "examine": "Scorching!", + "combat_style": "2", "melee_animation": "7834", "range_animation": "7834", "attack_speed": "5", @@ -65777,24 +66016,29 @@ "attack_level": "40" }, { - "combat_style": "1", + "examine": "This bat burned down the belfry.", + "combat_style": "2", "melee_animation": "8257", + "range_animation": "0", "attack_speed": "3", + "magic_level": "22", "respawn_delay": "0", - "defence_animation": "8256", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "8258", "name": "Spirit Tz-Kih", - "defence_level": "1", + "defence_level": "22", "safespot": null, - "lifepoints": "62", - "strength_level": "1", + "lifepoints": "31", + "strength_level": "22", "id": "7361", - "range_level": "1", - "attack_level": "1" + "range_level": "22", + "attack_level": "22" }, { "examine": "This bat burned down the belfry.", - "combat_style": "1", + "combat_style": "2", "melee_animation": "8257", "range_animation": "0", "attack_speed": "3", @@ -65814,19 +66058,24 @@ "attack_level": "22" }, { + "examine": "Those spikes are pretty big!", "start_gfx": "1367", - "melee_animation": "5228", + "melee_animation": "5229", + "range_animation": "0", + "magic_level": "50", "respawn_delay": "0", - "defence_animation": "5227", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "5230", "name": "Spirit graahk", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "81", + "strength_level": "50", "id": "7363", - "range_level": "1", - "attack_level": "1" + "range_level": "50", + "attack_level": "50" }, { "examine": "Those spikes are pretty big!", @@ -65849,19 +66098,24 @@ "attack_level": "50" }, { + "examine": "Those teeth are pretty big!", "start_gfx": "1365", "melee_animation": "5228", + "range_animation": "0", + "magic_level": "50", "respawn_delay": "0", - "defence_animation": "5227", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "5230", "name": "Spirit kyatt", - "defence_level": "1", + "defence_level": "50", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "81", + "strength_level": "50", "id": "7365", - "range_level": "1", - "attack_level": "1" + "range_level": "50", + "attack_level": "50" }, { "examine": "Those teeth are pretty big!", @@ -65883,6 +66137,24 @@ "range_level": "50", "attack_level": "50" }, + { + "examine": "It shifts.", + "melee_animation": "8131", + "range_animation": "0", + "magic_level": "34", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8133", + "name": "Void shifter", + "defence_level": "34", + "safespot": null, + "lifepoints": "48", + "strength_level": "34", + "id": "7367", + "range_level": "34", + "attack_level": "34" + }, { "examine": "It shifts.", "melee_animation": "8131", @@ -65901,6 +66173,24 @@ "range_level": "34", "attack_level": "34" }, + { + "examine": "It ravages.", + "melee_animation": "8086", + "range_animation": "0", + "magic_level": "34", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8087", + "name": "Void ravager", + "defence_level": "34", + "safespot": null, + "lifepoints": "48", + "strength_level": "34", + "id": "7370", + "range_level": "34", + "attack_level": "34" + }, { "examine": "It ravages.", "melee_animation": "8086", @@ -65939,22 +66229,27 @@ "attack_level": "60" }, { + "examine": "It's like a little stomach on wings.", + "melee_animation": "7994", + "range_animation": "0", + "magic_level": "60", + "respawn_delay": "0", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", "death_animation": "7996", "name": "Ravenous locust", - "defence_level": "1", + "defence_level": "60", "safespot": null, - "lifepoints": "10", - "melee_animation": "7994", - "strength_level": "1", + "lifepoints": "100", + "strength_level": "60", "id": "7374", - "range_level": "1", - "respawn_delay": "0", - "attack_level": "1", - "defence_animation": "7995" + "range_level": "60", + "attack_level": "60" }, { "examine": "He is an iron man!", - "combat_style": "1", + "combat_style": "0", "melee_animation": "7946", "magic_level": "65", "respawn_delay": "0", @@ -65973,7 +66268,7 @@ }, { "examine": "He is an iron man!", - "combat_style": "1", + "combat_style": "0", "melee_animation": "7946", "combat_audio": "0,0,0", "magic_level": "65", @@ -65992,6 +66287,24 @@ "range_level": "65", "attack_level": "65" }, + { + "examine": "Where did I put the marshmallows?", + "melee_animation": "8080", + "range_animation": "0", + "magic_level": "46", + "defence_animation": "0", + "weakness": "10", + "magic_animation": "0", + "death_animation": "8078", + "name": "Pyrelord", + "defence_level": "46", + "safespot": null, + "lifepoints": "65", + "strength_level": "46", + "id": "7377", + "range_level": "46", + "attack_level": "46" + }, { "examine": "Where did I put the marshmallows?", "melee_animation": "8080", From 486ca4bb19e377182a24bd5450be7772678a93d6 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 16 Feb 2025 09:33:56 +0000 Subject: [PATCH 225/306] Implemented Desert Treasure quest --- Server/data/configs/item_configs.json | 18 +- Server/data/configs/npc_configs.json | 262 ++++++-- Server/data/configs/npc_spawns.json | 140 +++- .../handlers/scenery/SignpostListener.kt | 60 +- .../skill/slayer/dungeon/SmokeDungeon.java | 2 +- .../desert/bandits/handlers/BanditDialogue.kt | 63 ++ .../desert/handlers/KhardianDesertPlugin.java | 47 -- .../deserttreasure/ArchaeologistDialogue.kt | 278 +++++--- .../quest/deserttreasure/AzzanadraDialogue.kt | 59 ++ .../quest/deserttreasure/BartenderDialogue.kt | 155 +++++ .../quest/deserttreasure/DamisBehavior.kt | 81 +++ .../quest/deserttreasure/DesertTreasure.kt | 607 +++++++++++++++--- .../deserttreasure/DesertTreasureListeners.kt | 464 +++++++++++++ .../quest/deserttreasure/DessousBehavior.kt | 142 ++++ .../deserttreasure/DiamondOfBloodListeners.kt | 134 ++++ .../deserttreasure/DiamondOfIceListeners.kt | 168 +++++ .../DiamondOfShadowListeners.kt | 265 ++++++++ .../deserttreasure/DiamondOfSmokeListeners.kt | 180 ++++++ .../quest/deserttreasure/EblisDialogue.kt | 328 ++++++++++ .../deserttreasure/EblisMirrorsDialogue.kt | 127 ++++ .../quest/deserttreasure/FareedBehavior.kt | 76 +++ .../FatherAndMotherTrollBehavior.kt | 75 +++ .../FatherAndMotherTrollDialogue.kt | 170 +++++ .../quest/deserttreasure/IceTrollBehavior.kt | 35 + .../quest/deserttreasure/IceTrollDialogue.kt | 35 + .../quest/deserttreasure/KamilBehavior.kt | 79 +++ .../quest/deserttreasure/MalakDialogue.kt | 262 ++++++++ .../quest/deserttreasure/PyramidArea.kt | 314 +++++++++ .../quest/deserttreasure/RasoloDialogue.kt | 217 +++++++ .../quest/deserttreasure/RuantunDialogue.kt | 83 +++ .../quest/deserttreasure/TranslationBook.kt | 185 ++++++ .../deserttreasure/TrollChildDialogue.kt | 142 ++++ .../desert/ullek/handlers/UllekListeners.kt | 15 + .../region/kandarin/handlers/RasoloNPC.java | 84 --- .../ArchaeologicalExpertDialogue.kt | 60 ++ .../canifis/dialogue/MalakDialogue.java | 57 -- .../src/main/core/game/activity/Cutscene.kt | 9 + .../game/global/action/SpecialLadders.java | 3 + .../command/sets/AnimationCommandSet.kt | 19 + .../system/command/sets/MiscCommandSet.kt | 14 + .../system/command/sets/TeleportCommandSet.kt | 24 + 41 files changed, 5080 insertions(+), 458 deletions(-) create mode 100644 Server/src/main/content/region/desert/bandits/handlers/BanditDialogue.kt delete mode 100644 Server/src/main/content/region/desert/handlers/KhardianDesertPlugin.java create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/AzzanadraDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/BartenderDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DamisBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasureListeners.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DessousBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfBloodListeners.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfIceListeners.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfShadowListeners.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfSmokeListeners.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/EblisDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/EblisMirrorsDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/FareedBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/IceTrollBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/IceTrollDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/KamilBehavior.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/MalakDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/RasoloDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/RuantunDialogue.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/TranslationBook.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/TrollChildDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/handlers/RasoloNPC.java delete mode 100644 Server/src/main/content/region/morytania/canifis/dialogue/MalakDialogue.java diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 7dbd04fbf..83abfeadb 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -42749,7 +42749,7 @@ "equipment_slot": "12" }, { - "examine": "Frank's shiny silver coated pot.", + "examine": "A silver pot made by Ruantun.", "durability": null, "name": "Silver pot", "tradeable": "false", @@ -42766,7 +42766,7 @@ "id": "4659" }, { - "examine": "Frank's shiny silver coated pot.", + "examine": "A silver pot made by Ruantun filled with your blood.", "durability": null, "name": "Silver pot", "tradeable": "false", @@ -42775,7 +42775,7 @@ "id": "4660" }, { - "examine": "A silver pot made by Ruantun and blessed on Entrana.", + "examine": "A blessed silver pot made by Ruantun filled with your blood.", "durability": null, "name": "Blessed pot", "weight": "2", @@ -42783,7 +42783,7 @@ "id": "4661" }, { - "examine": "Frank's shiny silver coated pot.", + "examine": "A silver pot made by Ruantun filled with blood and garlic.", "durability": null, "name": "Silver pot", "tradeable": "false", @@ -42792,7 +42792,7 @@ "id": "4662" }, { - "examine": "A silver pot made by Ruantun and blessed on Entrana.", + "examine": "A blessed silver pot filled with blood and garlic.", "durability": null, "name": "Blessed pot", "weight": "2", @@ -42800,7 +42800,7 @@ "id": "4663" }, { - "examine": "Frank's shiny silver coated pot.", + "examine": "A silver pot made by Ruantun filled with blood and spices.", "durability": null, "name": "Silver pot", "tradeable": "false", @@ -42809,7 +42809,7 @@ "id": "4664" }, { - "examine": "A silver pot made by Ruantun and blessed on Entrana.", + "examine": "A blessed silver pot filled with blood and spices.", "durability": null, "name": "Blessed pot", "weight": "2", @@ -42817,7 +42817,7 @@ "id": "4665" }, { - "examine": "Frank's shiny silver coated pot.", + "examine": "A silver pot made by Ruantun filled with blood, garlic and spices.", "durability": null, "name": "Silver pot", "tradeable": "false", @@ -42826,7 +42826,7 @@ "id": "4666" }, { - "examine": "A silver pot made by Ruantun and blessed on Entrana.", + "examine": "A blessed silver pot filled with blood, garlic and spices.", "durability": null, "name": "Blessed pot", "weight": "2", diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index ca5e4ad0a..9faf44635 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -12887,7 +12887,7 @@ }, { "examine": "It looks very hungry!", - "melee_animation": "7183", + "melee_animation": "1264", "slayer_exp": "50", "death_animation": "7185", "name": "Vampire", @@ -12901,6 +12901,8 @@ "attack_level": "52" }, { + "examine": "It looks very hungry!", + "melee_animation": "1264", "slayer_exp": "40", "name": "Vampire", "defence_level": "1", @@ -12913,6 +12915,7 @@ "attack_level": "1" }, { + "examine": "It looks very hungry!", "name": "Vampire", "defence_level": "1", "safespot": null, @@ -19944,49 +19947,70 @@ "attack_level": "1" }, { - "examine": "A tough-looking criminal.", - "melee_animation": "412", - "range_animation": "412", + "examine": "Ice warrior.", + "melee_animation": "440", + "range_animation": "440", "attack_speed": "5", "defence_animation": "404", "magic_animation": "412", "death_animation": "9055", "name": "Kamil", - "defence_level": "20", + "defence_level": "135", "safespot": null, - "lifepoints": "50", - "strength_level": "55", + "lifepoints": "130", + "strength_level": "80", "id": "1913", + "bonuses": "0,60,0,0,0,35,60,35,0,0,0,100,0,0,0", "range_level": "1", - "attack_level": "20" + "attack_level": "190" }, { - "melee_animation": "422", + "examine": "A vampyre warrior of Zamorak.", + "melee_animation": "1264", "respawn_delay": "60", "defence_animation": "425", "death_animation": "836", "name": "Dessous", - "defence_level": "1", + "defence_level": "99", "safespot": null, "lifepoints": "200", - "strength_level": "1", + "strength_level": "99", "id": "1914", "aggressive": "true", + "bonuses": "0,0,50,0,0,10,150,150,0,0,0,50,0,0,0", "range_level": "1", - "attack_level": "1" + "attack_level": "99" }, { - "melee_animation": "422", + "examine": "A vampyre warrior of Zamorak.", + "melee_animation": "1264", "respawn_delay": "60", "defence_animation": "425", "death_animation": "836", "name": "Dessous", - "defence_level": "1", + "defence_level": "99", "safespot": null, "lifepoints": "200", - "strength_level": "1", + "strength_level": "99", "id": "1915", "aggressive": "true", + "bonuses": "0,0,50,0,0,10,150,150,0,0,0,50,0,0,0", + "range_level": "1", + "attack_level": "99" + }, + { + "examine": "Luckily, I can't see much of his face.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Ruantun", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1916", "range_level": "1", "attack_level": "1" }, @@ -20040,6 +20064,22 @@ "range_level": "1", "attack_level": "58" }, + { + "examine": "One of Morytania's vampyric nobility.", + "melee_animation": "0", + "range_animation": "0", + "defence_animation": "0", + "magic_animation": "0", + "death_animation": "0", + "name": "Malak", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1920", + "range_level": "1", + "attack_level": "1" + }, { "examine": "Looks like a rough-and-ready type.", "melee_animation": "0", @@ -20238,6 +20278,98 @@ "range_level": "1", "attack_level": "64" }, + { + "examine": "A troll frozen in a block of ice.", + "melee_animation": "0", + "range_animation": "0", + "respawn_delay": "1", + "defence_animation": "0", + "weakness": "9", + "magic_animation": "0", + "death_animation": "0", + "name": "Ice block", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1943", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "A troll frozen in a block of ice.", + "melee_animation": "0", + "range_animation": "0", + "respawn_delay": "1", + "defence_animation": "0", + "weakness": "9", + "magic_animation": "0", + "death_animation": "0", + "name": "Ice block", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1944", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "A troll frozen in a block of ice.", + "melee_animation": "0", + "range_animation": "0", + "respawn_delay": "1", + "defence_animation": "0", + "weakness": "9", + "magic_animation": "0", + "death_animation": "0", + "name": "Ice block", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1945", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "A troll frozen in a block of ice.", + "melee_animation": "0", + "range_animation": "0", + "respawn_delay": "1", + "defence_animation": "0", + "weakness": "9", + "magic_animation": "0", + "death_animation": "0", + "name": "Ice block", + "defence_level": "1", + "safespot": null, + "lifepoints": "10", + "strength_level": "1", + "id": "1946", + "range_level": "1", + "attack_level": "1" + }, + { + "examine": "An ice troll.", + "name": "Troll father", + "id": "1947" + }, + { + "examine": "An ice troll.", + "name": "Troll father", + "id": "1948" + }, + { + "examine": "An ice troll.", + "name": "Troll mother", + "id": "1949" + }, + { + "examine": "An ice troll.", + "name": "Troll mother", + "id": "1950" + }, { "examine": "Not a man's best friend.", "melee_animation": "6579", @@ -20384,17 +20516,17 @@ "magic_animation": "0", "death_animation": "5555", "name": "Mummy", - "defence_level": "55", + "defence_level": "90", "safespot": null, - "lifepoints": "78", - "strength_level": "55", + "lifepoints": "90", + "strength_level": "90", "id": "1961", "aggressive": "true", "range_level": "1", - "attack_level": "55" + "attack_level": "90" }, { - "examine": "Spooky", + "examine": "Spooky, bandaged dead dude.", "melee_animation": "5549", "range_animation": "0", "defence_animation": "0", @@ -20402,14 +20534,15 @@ "magic_animation": "0", "death_animation": "5555", "name": "Mummy", - "defence_level": "55", + "defence_level": "90", "poison_immune": "true", "safespot": null, - "lifepoints": "78", - "strength_level": "55", + "lifepoints": "90", + "strength_level": "90", "id": "1962", + "aggressive": "true", "range_level": "1", - "attack_level": "55" + "attack_level": "90" }, { "examine": "A victim of poor first aid.", @@ -20420,14 +20553,15 @@ "magic_animation": "0", "death_animation": "5555", "name": "Mummy", - "defence_level": "55", + "defence_level": "90", "poison_immune": "true", "safespot": null, - "lifepoints": "78", - "strength_level": "55", + "lifepoints": "90", + "strength_level": "90", "id": "1963", + "aggressive": "true", "range_level": "1", - "attack_level": "55" + "attack_level": "90" }, { "examine": "But who's the daddy?", @@ -20438,13 +20572,14 @@ "magic_animation": "0", "death_animation": "5555", "name": "Mummy", - "defence_level": "55", + "defence_level": "90", "safespot": null, - "lifepoints": "78", - "strength_level": "55", + "lifepoints": "90", + "strength_level": "90", "id": "1964", + "aggressive": "true", "range_level": "1", - "attack_level": "55" + "attack_level": "90" }, { "examine": "A tightly-wrapped monster.", @@ -20484,19 +20619,20 @@ "examine": "I think they're some kind of beetle...", "melee_animation": "1948", "range_animation": "0", + "attack_speed": "3", "poisonous": "true", - "defence_animation": "0", + "defence_animation": "1946", "weakness": "7", "magic_animation": "0", - "death_animation": "1946", + "death_animation": "5464", "name": "Scarabs", - "defence_level": "62", + "defence_level": "10", "safespot": null, - "lifepoints": "88", - "strength_level": "62", + "lifepoints": "25", + "strength_level": "2", "id": "1969", "range_level": "1", - "attack_level": "62" + "attack_level": "255" }, { "examine": "A wandering merchant.", @@ -20526,6 +20662,45 @@ "range_level": "1", "attack_level": "60" }, + { + "examine": "The warrior of darkness.", + "melee_animation": "440", + "range_animation": "0", + "respawn_delay": "60", + "defence_animation": "0", + "weakness": "0", + "magic_animation": "0", + "death_animation": "836", + "name": "Damis", + "defence_level": "90", + "safespot": null, + "lifepoints": "90", + "strength_level": "90", + "id": "1974", + "bonuses": "0,0,0,0,0,60,60,60,60,60,0,80,0,0,0", + "range_level": "1", + "attack_level": "90" + }, + { + "examine": "The warrior of darkness.", + "melee_animation": "440", + "range_animation": "0", + "attack_speed": "3", + "respawn_delay": "60", + "defence_animation": "0", + "weakness": "0", + "magic_animation": "0", + "death_animation": "836", + "name": "Damis", + "defence_level": "160", + "safespot": null, + "lifepoints": "200", + "strength_level": "100", + "id": "1975", + "bonuses": "0,0,0,0,0,100,100,100,80,120,0,100,0,0,0", + "range_level": "1", + "attack_level": "160" + }, { "examine": "Looks hungry!", "melee_animation": "6565", @@ -20545,19 +20720,22 @@ "attack_level": "48" }, { + "examine": "Zamorak's warrior of fire.", "melee_animation": "799", + "magic_level": "100", "respawn_delay": "60", "defence_animation": "434", "death_animation": "836", "name": "Fareed", - "defence_level": "1", + "defence_level": "135", "safespot": null, "lifepoints": "130", - "strength_level": "1", + "strength_level": "120", "id": "1977", "aggressive": "true", - "range_level": "1", - "attack_level": "1" + "bonuses": "0,0,0,0,0,100,100,100,0,0,0,120,0,0,0", + "range_level": "100", + "attack_level": "190" }, { "examine": "A malnourished worker.", diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 074d7ee1f..6a550f27b 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -365,7 +365,7 @@ }, { "npc_id": "110", - "loc_data": "{2564,9887,0,1,4}-{2581,9897,0,1,1}-{2577,9888,0,1,1}-{3234,5497,0,1,1}-{3305,9400,0,1,1}-{3296,9378,0,1,3}-{3050,10337,0,1,4}-{3047,10340,0,1,4}-{3048,10346,0,1,4}-{3048,10346,0,1,3}-" + "loc_data": "{2564,9887,0,1,4}-{2581,9897,0,1,1}-{2577,9888,0,1,1}-{3234,5497,0,1,1}-{3305,9400,0,1,1}-{3244,9356,0,1,1}-{3252,9370,0,1,1}-{3294,9375,0,1,3}-{3050,10337,0,1,4}-{3047,10340,0,1,4}-{3048,10346,0,1,4}-{3048,10346,0,1,3}-" }, { "npc_id": "111", @@ -2393,7 +2393,11 @@ }, { "npc_id": "839", - "loc_data": "{3153,3035,0,1,3}-" + "loc_data": "{3265,3066,0,1,0}-{3267,3066,0,1,0}-{3310,3068,0,1,0}-{3322,3011,0,1,0}-{3322,3052,0,1,0}-{3324,3030,0,1,0}-{3150,3044,0,1,0}-{3172,3009,0,1,0}-{3197,3012,0,1,0}-{3198,3040,0,1,0}-{3217,3092,0,1,0}-{3235,3074,0,1,0}-{3252,3125,0,1,0}-{3258,3078,0,1,0}-{3237,2968,0,1,0}-{3224,3013,0,1,0}-{3225,3034,0,1,0}-{3226,3060,0,1,0}-{3250,3057,0,1,0}-{3283,3108,0,1,0}-{3323,3094,0,1,0}-" + }, + { + "npc_id": "840", + "loc_data": "{3268,3052,0,1,0}-{3281,3056,0,1,0}-{3307,3055,0,1,0}-{3318,3020,0,1,0}-{3318,3040,0,1,0}-{3190,3054,0,1,0}-{3192,3016,0,1,0}-{3217,3111,0,1,0}-{3222,3086,0,1,0}-{3238,3101,0,1,0}-{3244,3080,0,1,0}-{3253,3116,0,1,0}-{3255,3095,0,1,0}-{3237,3000,0,1,0}-{3245,2960,0,1,0}-{3208,3032,0,1,0}-{3217,3064,0,1,0}-{3238,3015,0,1,0}-{3258,3063,0,1,0}-{3267,3077,0,1,0}-{3269,3110,0,1,0}-{3275,3094,0,1,0}-{3291,3078,0,1,0}-{3291,3100,0,1,0}-{3305,3089,0,1,0}-{3318,3078,0,1,0}-{3321,3104,0,1,0}-" }, { "npc_id": "841", @@ -2733,7 +2737,7 @@ }, { "npc_id": "1019", - "loc_data": "{3187,5555,0,1,4}-{3190,5563,0,1,1}-{3193,5555,0,1,3}-{3213,9377,0,1,3}-{3209,9397,0,1,4}-{3245,9401,0,1,6}-{3237,9402,0,1,2}-{3207,9349,0,1,3}-{3220,9347,0,1,6}-{3233,9359,0,1,4}-{3235,9354,0,0,6}-{3259,9370,0,1,1}-{3258,9387,0,1,6}-{2707,9880,0,1,0}-{2711,9876,0,1,0}-{2712,9871,0,1,0}-{2715,9874,0,1,0}-{2720,9871,0,1,0}-{2717,9880,0,1,0}-{2722,9879,0,1,0}-{2723,9875,0,1,0}-{3278,9368,0,1,5}-{3271,9359,0,1,3}-{3287,9359,0,1,5}-{3301,9394,0,1,5}-{3318,9352,0,1,5}-" + "loc_data": "{3187,5555,0,1,4}-{3190,5563,0,1,1}-{3193,5555,0,1,3} -{3213,9377,0,1,3}-{3209,9397,0,1,4}-{3245,9401,0,1,6}- {3237,9402,0,1,2}-{3207,9349,0,1,3}-{3220,9347,0,1,6} -{3233,9359,0,1,4}-{3235,9354,0,0,6}-{3259,9370,0,1,1}- {3258,9387,0,1,6}-{2707,9880,0,1,0}-{2711,9876,0,1,0}- {2712,9871,0,1,0}-{2715,9874,0,1,0}-{2720,9871,0,1,0} -{2717,9880,0,1,0}-{2722,9879,0,1,0}-{2723,9875,0,1,0}- {3278,9368,0,1,5}-{3271,9359,0,1,3}-{3287,9359,0,1,5}- {3301,9394,0,1,5}-{3318,9352,0,1,5}-" }, { "npc_id": "1020", @@ -3861,7 +3865,7 @@ }, { "npc_id": "1585", - "loc_data": "{2575,9892,0,1,6}-{2666,9482,0,0,5}-{2641,9563,2,0,5}-{3257,5523,0,1,1}-{3204,5516,0,1,3}-" + "loc_data": "{2575,9892,0,1,6}-{2666,9482,0,0,5}-{2641,9563,2,0,5}-{3257,5523,0,1,1}-{3204,5516,0,1,3}-{3244,9369,0,1,3}-{3252,9359,0,1,3}-{3306,9400,0,1,3}-" }, { "npc_id": "1586", @@ -4009,7 +4013,7 @@ }, { "npc_id": "1633", - "loc_data": "{1837,3244,0,1,0}-{1836,3250,0,1,0}-{1845,3251,0,1,0}-{1845,3247,0,1,0}-{1849,3241,0,1,0}-{1853,3247,0,1,0}-{1848,3254,0,1,0}-{1858,3251,0,1,0}-{1935,3217,0,1,0}-{1933,3209,0,1,0}-{1930,3208,0,1,0}-{1929,3217,0,1,0}-{1927,3219,0,1,0}-{1924,3211,0,1,0}-{1920,3216,0,1,0}-{1925,3213,0,1,0}-{3263,9399,0,1,3}-{3274,9397,0,1,1}-{3275,9393,0,1,6}-{3271,9384,0,1,0}-{3270,9380,0,1,2}-{3283,9378,0,1,6}-{3285,9386,0,1,5}-{3284,9401,0,1,4}-{3278,9353,0,1,1}-{3299,9380,0,1,1}-{3319,9402,0,1,1}-{3305,9350,0,1,4}-{2761,10007,0,1,0}-{2757,10010,0,1,3}-{2763,10000,0,1,5}-{2760,10011,0,1,0}-{2761,9997,0,1,4}-" + "loc_data": "{1837,3244,0,1,0}-{1836,3250,0,1,0}-{1845,3251,0,1,0}-{1845,3247,0,1,0}-{1849,3241,0,1,0}-{1853,3247,0,1,0}-{1848,3254,0,1,0}-{1858,3251,0,1,0}-{1935,3217,0,1,0}-{1933,3209,0,1,0}-{1930,3208,0,1,0}-{1929,3217,0,1,0}-{1927,3219,0,1,0}-{1924,3211,0,1,0}-{1920,3216,0,1,0}-{1925,3213,0,1,0}-{3263,9399,0,1,3}-{3274,9397,0,1,1}-{3275,9393,0,1,6}-{3271,9384,0,1,0}-{3270,9380,0,1,2}-{3283,9378,0,1,6}-{3285,9386,0,1,5}-{3284,9401,0,1,4}-{3278,9353,0,1,1}-{3299,9380,0,1,1}-{3319,9402,0,1,1}-{3305,9350,0,1,4}-{3248,9374,0,1,3}-{3253,9363,0,1,3}-{3249,9355,0,1,3}-{2761,10007,0,1,0}-{2757,10010,0,1,3}-{2763,10000,0,1,5}-{2760,10011,0,1,0}-{2761,9997,0,1,4}-" }, { "npc_id": "1634", @@ -4491,6 +4495,10 @@ "npc_id": "1873", "loc_data": "{3343,2962,0,1,0}-{3343,2964,0,1,1}-" }, + { + "npc_id": "1874", + "loc_data": "{3371,9301,0,1,0}-{3371,9303,0,1,0}-{3371,9305,0,1,0}-{3371,9307,0,1,0}-{3371,9309,0,1,0}-{3373,9301,0,1,0}-{3373,9303,0,1,0}-{3373,9306,0,1,0}-{3373,9308,0,1,0}-{3375,9301,0,1,0}-{3375,9303,0,1,0}-{3375,9305,0,1,0}-{3375,9307,0,1,0}-{3375,9309,0,1,0}-{3403,2963,0,1,0}-{3429,2976,0,1,0}-{3328,2952,0,1,0}-{3328,2957,0,1,0}-{3331,2955,0,1,0}-{3331,2961,0,1,0}-{3266,2955,0,1,0}-{3271,2967,0,1,0}-{3279,2957,0,1,0}-{3280,2975,0,1,0}-{3284,2959,0,1,0}-{3294,2964,0,1,0}-{3295,2978,0,1,0}-{3305,2966,0,1,0}-{3307,2959,0,1,0}-{3309,2973,0,1,0}-{3396,3029,0,1,0}-{3397,3044,0,1,0}-{3398,3038,0,1,0}-" + }, { "npc_id": "1875", "loc_data": "{3354,2952,0,0,1}-" @@ -4519,6 +4527,10 @@ "npc_id": "1912", "loc_data": "{3376,3429,0,1,6}-" }, + { + "npc_id": "1916", + "loc_data": "{3112,9690,0,0,7}-" + }, { "npc_id": "1917", "loc_data": "{3177,2987,0,1,6}-" @@ -4537,7 +4549,11 @@ }, { "npc_id": "1923", - "loc_data": "{3183,2974,0,0,7}-" + "loc_data": "{3185,2983,0,1,4}-" + }, + { + "npc_id": "1924", + "loc_data": "{3213,2956,0,1,1}-" }, { "npc_id": "1926", @@ -4559,6 +4575,10 @@ "npc_id": "1930", "loc_data": "{3161,2985,0,0,6}-{3161,2983,0,0,6}-{3161,2982,0,0,6}-{3161,2981,0,0,6}-{3161,2984,0,0,6}-" }, + { + "npc_id": "1932", + "loc_data": "{2836,3740,0,0,6}-" + }, { "npc_id": "1935", "loc_data": "{2841,3738,0,0,3}-" @@ -4591,6 +4611,22 @@ "npc_id": "1942", "loc_data": "{2855,3735,0,1,0}-{2858,3730,0,1,0}-{2865,3726,0,1,0}-" }, + { + "npc_id": "1943", + "loc_data": "{2825,3807,2,0,1}-" + }, + { + "npc_id": "1945", + "loc_data": "{2825,3811,2,0,6}-" + }, + { + "npc_id": "1947", + "loc_data": "{2835,3740,0,0,6}-" + }, + { + "npc_id": "1949", + "loc_data": "{2837,3740,0,0,6}-" + }, { "npc_id": "1951", "loc_data": "{2886,3723,0,1,3}-{2887,3720,0,1,4}-{2890,3721,0,1,7}-{2890,3724,0,1,1}-{2909,3736,0,1,5}-{2910,3736,0,1,2}-{2891,3724,0,1,7}-" @@ -4621,23 +4657,35 @@ }, { "npc_id": "1961", - "loc_data": "{3156,5477,0,1,5}-{3162,5479,0,1,4}-{3159,5477,0,1,6}-{3150,5474,0,1,3}-{3147,5480,0,1,1}-{3159,5484,0,1,3}-{3250,9326,0,1,4}-{3258,9327,0,1,6}-{3256,9333,0,1,1}-{3220,9309,0,1,4}-{3252,9333,0,1,3}-{3208,9318,0,1,3}-{3241,9331,0,1,6}-{3204,9328,0,1,3}-{3209,9328,0,1,3}-{3228,9323,0,1,4}-{3210,9282,0,1,7}-{3225,9329,0,1,6}-{3207,9299,0,1,4}-{3215,9295,0,1,3}-{3213,9322,0,1,3}-{3214,9315,0,1,0}-{3221,9291,0,1,0}-{3213,9303,0,1,4}-{3227,9304,0,1,6}-{3247,9301,0,1,1}-{3228,9284,0,1,3}-{3254,9286,0,1,4}-{3262,9291,0,1,6}-{3224,9302,0,1,3}-{3250,9298,0,1,3}-{3252,9293,0,1,6}-{3262,9299,0,1,1}-{3256,9297,0,1,7}-{3262,9285,0,1,1}-{3254,9322,0,1,0}-{3261,9318,0,1,4}-{3242,9316,0,1,6}-{3250,9306,0,1,3}-{3250,9327,0,1,3}-" + "loc_data": "{3156,5477,0,1,5}-{3162,5479,0,1,4}-{3159,5477,0,1,6}-{3150,5474,0,1,3}-{3147,5480,0,1,1}-{3159,5484,0,1,3}-{2764,4944,1,1,0}-{2796,4976,1,1,0}-{2798,4950,1,1,0}-{2806,4939,1,1,0}-{2832,4959,2,1,0}-{3201,9293,0,1,0}-{3205,9303,0,1,0}-{3206,9328,0,1,0}-{3207,9310,0,1,0}-{3211,9284,0,1,0}-{3220,9289,0,1,0}-{3224,9334,0,1,0}-{3249,9286,0,1,0}-{3251,9303,0,1,0}-{3252,9327,0,1,0}-{3252,9332,0,1,0}-{3255,9315,0,1,0}-{3261,9296,0,1,0}-{3261,9306,0,1,0}-" }, { "npc_id": "1962", - "loc_data": "{3168,5458,0,1,2}-{3242,9331,0,1,3}-{3238,9333,0,1,6}-{3261,9330,0,1,1}-{3232,9333,0,1,0}-{3222,9324,0,1,4}-{3205,9303,0,1,3}-" + "loc_data": "{3168,5458,0,1,2}-{2900,4948,3,1,0}-{2762,4962,1,1,0}-{2763,4973,1,1,0}-{2780,4977,1,1,0}-{2787,4967,1,1,0}-{2796,4959,1,1,0}-{2838,4948,2,1,0}-{3205,9329,0,1,0}-{3210,9292,0,1,0}-{3221,9310,0,1,0}-{3225,9323,0,1,0}-{3243,9310,0,1,0}-{3246,9290,0,1,0}-{3255,9301,0,1,0}-{3255,9321,0,1,0}-{3261,9331,0,1,0}-" }, { "npc_id": "1963", - "loc_data": "{3166,5465,0,1,7}-{3168,5462,0,1,0}-{3167,5467,0,1,1}-{3167,5467,0,1,7}-" + "loc_data": "{3166,5465,0,1,7}-{3168,5462,0,1,0}-{3167,5467,0,1,1}-{3167,5467,0,1,7}-{2926,4965,3,1,0}-{2771,4947,1,1,0}-{2775,4963,1,1,0}-{2781,4948,1,1,0}-{2792,4942,1,1,0}-{2798,4954,1,1,0}-{2858,4964,2,1,0}-{3204,9309,0,1,0}-{3214,9333,0,1,0}-{3219,9297,0,1,0}-{3239,9300,0,1,0}-{3240,9286,0,1,0}-{3240,9330,0,1,0}-{3245,9306,0,1,0}-{3250,9316,0,1,0}-{3250,9317,0,1,0}-{3257,9290,0,1,0}-" + }, + { + "npc_id": "1964", + "loc_data": "{2761,4950,1,1,0}-{2765,4938,1,1,0}-{2770,4955,1,1,0}-{2772,4940,1,1,0}-{2777,4943,1,1,0}-{2782,4967,1,1,0}-{2797,4965,1,1,0}-{2799,4937,1,1,0}-{2799,4941,1,1,0}-{2807,4968,1,1,0}-{2808,4975,1,1,0}-{2809,4953,1,1,0}-{2864,4946,2,1,0}-{3202,9283,0,1,0}-{3206,9333,0,1,0}-{3209,9299,0,1,0}-{3219,9301,0,1,0}-{3226,9285,0,1,0}-{3227,9303,0,1,0}-{3228,9293,0,1,0}-{3229,9333,0,1,0}-{3237,9293,0,1,0}-{3246,9321,0,1,0}-{3256,9296,0,1,0}-{3260,9285,0,1,0}-{3262,9317,0,1,0}-" + }, + { + "npc_id": "1970", + "loc_data": "{3233,9317,0,1,1}-" }, { "npc_id": "1972", "loc_data": "{2536,3426,0,1,0}-" }, + { + "npc_id": "1973", + "loc_data": "{2693,5075,0,1,0}-{2695,5089,0,1,0}-{2697,5096,0,1,0}-{2703,5064,0,1,0}-{2710,5105,0,1,0}-{2719,5078,0,1,0}-{2719,5112,0,1,0}-{2720,5096,0,1,0}-{2726,5086,0,1,0}-{2729,5096,0,1,0}-{2735,5061,0,1,0}-{2740,5069,0,1,0}-{2740,5085,0,1,0}-{2746,5092,0,1,0}-{2746,5114,0,1,0}-{2626,5065,0,1,0}-{2637,5099,0,1,0}-{2638,5058,0,1,0}-{2644,5090,0,1,0}-{2658,5082,0,1,0}-{2666,5097,0,1,0}-{2680,5074,0,1,0}-" + }, { "npc_id": "1976", - "loc_data": "{3315,5508,0,1,5}-{3308,5510,0,1,3}-{3304,5507,0,1,4}-{3299,5509,0,1,3}-{3317,5514,0,1,3}-{3319,5518,0,1,4}-{3320,5507,0,1,4}-{3324,5513,0,1,1}-{3283,5510,0,1,5}-{3320,5550,0,1,0}-{3313,5523,0,1,4}-{3310,5541,0,1,4}-{3308,5535,0,1,5}-{3301,5531,0,1,4}-{3315,5530,0,1,1}-{3322,5536,0,1,4}-{3320,5539,0,1,7}-{3311,5519,0,1,3}-{3289,5525,0,1,2}-{3300,5519,0,1,6}-{3289,5515,0,1,7}-{3287,5523,0,1,3}-" + "loc_data": "{2694,5067,0,1,0}-{2717,5081,0,1,0}-{2718,5108,0,1,0}-{2721,5104,0,1,0}-{2726,5091,0,1,0}-{2731,5060,0,1,0}-{2732,5073,0,1,0}-{2740,5083,0,1,0}-{2742,5103,0,1,0}-{2747,5094,0,1,0}-{3315,5508,0,1,5}-{3308,5510,0,1,3}-{3304,5507,0,1,4}-{3299,5509,0,1,3}-{3317,5514,0,1,3}-{3319,5518,0,1,4}-{3320,5507,0,1,4}-{3324,5513,0,1,1}-{3283,5510,0,1,5}-{3320,5550,0,1,0}-{3313,5523,0,1,4}-{3310,5541,0,1,4}-{3308,5535,0,1,5}-{3301,5531,0,1,4}-{3315,5530,0,1,1}-{3322,5536,0,1,4}-{3320,5539,0,1,7}-{3311,5519,0,1,3}-{3289,5525,0,1,2}-{3300,5519,0,1,6}-{3289,5515,0,1,7}-{3287,5523,0,1,3}-" }, { "npc_id": "1990", @@ -4645,11 +4693,43 @@ }, { "npc_id": "1993", - "loc_data": "{3360,2935,0,1,4}-{3359,2924,0,1,6}-{3352,2936,0,1,0}-{3349,2931,0,1,6}-{3341,2924,0,1,4}-" + "loc_data": "{3264,2886,0,1,0}-{3267,2891,0,1,0}-{3268,2881,0,1,0}-{3269,2885,0,1,0}-{3296,2912,0,1,0}-{3297,2919,0,1,0}-{3301,2920,0,1,0}-{3308,2916,0,1,0}-{3258,2868,0,1,0}-{3259,2823,0,1,0}-{3259,2845,0,1,0}-{3260,2830,0,1,0}-{3260,2859,0,1,0}-{3261,2819,0,1,0}-{3261,2851,0,1,0}-{3337,2922,0,1,0}-{3343,2931,0,1,0}-{3349,2922,0,1,0}-{3351,2927,0,1,0}-{3357,2922,0,1,0}-{3359,2927,0,1,0}-{3364,2937,0,1,0}-{3268,2854,0,1,0}-{3269,2827,0,1,0}-{3269,2866,0,1,0}-{3269,2875,0,1,0}-{3270,2818,0,1,0}-{3272,2841,0,1,0}-{3276,2842,0,1,0}-{3282,2839,0,1,0}-{3290,2847,0,1,0}-" }, { "npc_id": "1994", - "loc_data": "{3344,2933,0,1,3}-{3350,2936,0,1,4}-" + "loc_data": "{3265,2931,0,1,0}-{3265,2935,0,1,0}-{3268,2932,0,1,0}-{3268,2935,0,1,0}-{3316,2900,0,1,0}-{3319,2897,0,1,0}-{3320,2901,0,1,0}-{3321,2899,0,1,0}-{3212,2863,0,1,0}-{3213,2866,0,1,0}-{3215,2863,0,1,0}-{3216,2865,0,1,0}-{3216,2868,0,1,0}-{3218,2831,0,1,0}-{3220,2830,0,1,0}-{3220,2833,0,1,0}-{3221,2831,0,1,0}-{3238,2845,0,1,0}-{3240,2845,0,1,0}-{3241,2843,0,1,0}-{3241,2847,0,1,0}-{3400,2997,0,1,0}-{3402,2999,0,1,0}-{3403,2997,0,1,0}-{3445,2993,0,1,0}-{3446,2992,0,1,0}-{3448,2991,0,1,0}-{3448,2994,0,1,0}-{3329,2933,0,1,0}-{3330,2931,0,1,0}-{3331,2933,0,1,0}-{3343,2895,0,1,0}-{3345,2896,0,1,0}-{3346,2894,0,1,0}-{3348,2894,0,1,0}-{3376,2934,0,1,0}-{3378,2933,0,1,0}-{3378,2935,0,1,0}-{3381,2907,0,1,0}-{3383,2905,0,1,0}-{3383,2908,0,1,0}-{3384,2907,0,1,0}-{3306,2817,0,1,0}-{3308,2818,0,1,0}-{3309,2816,0,1,0}-{3312,2817,0,1,0}-{3314,2861,0,1,0}-{3319,2873,0,1,0}-{3321,2871,0,1,0}-{3324,2870,0,1,0}-{3327,2858,0,1,0}-{3406,3014,0,1,0}-{3408,3013,0,1,0}-{3408,3016,0,1,0}-{3410,3015,0,1,0}-" + }, + { + "npc_id": "1995", + "loc_data": "{3309,2806,0,1,0}-{3312,2806,0,1,0}-{3314,2752,0,1,0}-{3314,2806,0,1,0}-{3315,2805,0,1,0}-{3316,2780,0,1,0}-{3316,2795,0,1,0}-{3317,2752,0,1,0}-{3317,2762,0,1,0}-{3317,2763,0,1,0}-{3317,2779,0,1,0}-{3317,2794,0,1,0}-{3318,2761,0,1,0}-{3318,2778,0,1,0}-{3318,2781,0,1,0}-{3318,2794,0,1,0}-{3318,2795,0,1,0}-{3319,2760,0,1,0}-{3319,2763,0,1,0}-" + }, + { + "npc_id": "1997", + "loc_data": "{3272,2802,0,1,0}-{3273,2802,0,1,0}-{3273,2805,0,1,0}-{3274,2798,0,1,0}-{3274,2799,0,1,0}-{3274,2802,0,1,0}-{3274,2804,0,1,0}-{3275,2795,0,1,0}-{3275,2796,0,1,0}-{3275,2798,0,1,0}-{3277,2752,0,1,0}-{3277,2753,0,1,0}-{3277,2756,0,1,0}-{3277,2757,0,1,0}-{3278,2752,0,1,0}-{3278,2753,0,1,0}-{3278,2754,0,1,0}-{3278,2755,0,1,0}-" + }, + { + "npc_id": "1998", + "loc_data": "{3275,2803,0,1,0}-" + }, + { + "npc_id": "1999", + "loc_data": "{3278,2804,0,1,0}-" + }, + { + "npc_id": "2000", + "loc_data": "{3277,2802,0,1,0}-" + }, + { + "npc_id": "2002", + "loc_data": "{3315,2849,0,1,0}-" + }, + { + "npc_id": "2003", + "loc_data": "{3304,9196,0,1,0}-" + }, + { + "npc_id": "2004", + "loc_data": "{3304,9195,0,1,0}-" }, { "npc_id": "2014", @@ -5333,16 +5413,24 @@ }, { "npc_id": "2296", - "loc_data": "{3399,2916,0,0,6}-" + "loc_data": "{3401,2918,0,0,6}-" }, { "npc_id": "2298", "loc_data": "{3287,2813,0,1,1}-" }, + { + "npc_id": "2300", + "loc_data": "{3243,2813,0,0,1}-" + }, { "npc_id": "2301", "loc_data": "{3181,3043,0,1,3}-{3310,3107,0,1,4}-" }, + { + "npc_id": "2302", + "loc_data": "{3243,2812,0,1,1}-" + }, { "npc_id": "2304", "loc_data": "{3039,3292,0,1,6}-" @@ -6153,7 +6241,7 @@ }, { "npc_id": "2803", - "loc_data": "{3391,3066,0,1,6}-{3397,3054,0,1,6}-{3398,3060,0,1,0}-{3412,3059,0,1,3}-" + "loc_data": "{3387,3068,0,1,0}-{3387,3017,0,1,0}-{3404,3062,0,1,0}-{3441,3061,0,1,0}-{3445,3034,0,1,0}-{3338,2804,0,1,0}-{3339,2815,0,1,0}-{3342,2809,0,1,0}-{3344,2800,0,1,0}-{3348,2809,0,1,0}-{3349,2814,0,1,0}-{3357,2813,0,1,0}-{3357,2806,0,1,0}-{3365,2815,0,1,0}-" }, { "npc_id": "2804", @@ -6169,11 +6257,11 @@ }, { "npc_id": "2807", - "loc_data": "{3414,3045,0,1,1}-{3403,3050,0,1,4}-{3407,3058,0,1,3}-{3420,3022,0,0,0}-" + "loc_data": "{3384,3013,0,1,0}-{3387,3014,0,1,0}-{3441,3059,0,1,0}-{3443,3033,0,1,0}-{3443,3059,0,1,0}-" }, { "npc_id": "2808", - "loc_data": "{3384,3072,0,1,2}-{3419,3006,0,1,4}-{3403,3069,0,1,1}-{3402,3061,0,1,1}-{3394,3076,0,1,1}-" + "loc_data": "{3385,3067,0,1,0}-{3389,3065,0,1,0}-{3400,3032,0,1,0}-{3402,3061,0,1,0}-{3404,3060,0,1,0}-{3407,3067,0,1,0}-{3408,3060,0,1,0}-{3411,3065,0,1,0}-{3412,3032,0,1,0}-{3412,3049,0,1,0}-{3414,3029,0,1,0}-{3417,3036,0,1,0}-{3418,3032,0,1,0}-{3419,3034,0,1,0}-{3422,3058,0,1,0}-{3424,3059,0,1,0}-{3435,3057,0,1,0}-{3435,3062,0,1,0}-{3439,3013,0,1,0}-{3439,3065,0,1,0}-{3440,3016,0,1,0}-{3443,3012,0,1,0}-{3443,3017,0,1,0}-{3443,3034,0,1,0}-{3443,3047,0,1,0}-{3446,3014,0,1,0}-" }, { "npc_id": "2809", @@ -6339,6 +6427,10 @@ "npc_id": "3021", "loc_data": "{2572,3105,0,1,0}-{2614,3226,0,1,4}-{3088,3357,0,1,0}-{2856,3435,0,1,0}-{3603,3529,0,1,6}-{2611,3859,0,1,6}-{2589,3863,0,1,0}-{3189,3234,0,1,0}-{2940,3225,0,1,6}-{2663,3374,0,1,4}-{3182,3354,0,1,0}-{2933,3434,0,1,4}-{3449,3471,0,1,6}-{2666,3521,0,1,4}-{2491,3177,0,1,1}-{3007,3371,0,1,2}-{2474,3446,0,1,4}-{2434,3415,0,1,3}-{3232,3459,0,1,3}-{2796,3104,0,1,0}-{2764,3210,0,1,1}-{3315,3205,0,1,6}-{3060,3263,0,1,0}-{3053,3304,0,1,1}-{2812,3333,0,1,4}-{2815,3466,0,1,3}-" }, + { + "npc_id": "3022", + "loc_data": "{3371,9320,0,0,6}-" + }, { "npc_id": "3029", "loc_data": "{3422,2937,0,1,1}-" @@ -7057,7 +7149,7 @@ }, { "npc_id": "3675", - "loc_data": "{3331,2791,0,1,1}-{3333,2803,0,1,2}-{3338,2801,0,1,4}-{3338,2776,0,1,3}-{3321,2857,0,1,3}-{3322,2861,0,0,4}-{3319,2855,0,1,1}-{3319,2853,0,1,6}-" + "loc_data": "{3333,2864,0,1,1}-{3335,2860,0,1,2}-{3338,2864,0,1,4}-{3215,2841,0,1,0}-{3217,2845,0,1,0}-{3220,2841,0,1,0}-{3295,2866,0,1,0}-{3297,2863,0,1,0}-{3301,2864,0,1,0}-{3336,2778,0,1,0}-{3343,2793,0,1,0}-{3367,2791,0,1,0}-" }, { "npc_id": "3677", @@ -8671,6 +8763,10 @@ "npc_id": "5260", "loc_data": "{2665,2651,0,0,1}-{2667,2651,0,0,1}-" }, + { + "npc_id": "5277", + "loc_data": "{3264,2784,0,0,4}-{3264,2785,0,0,4}-" + }, { "npc_id": "5291", "loc_data": "{3300,2792,0,0,6}-{3282,2807,0,0,6}-{3285,2811,0,0,1}-{3283,2772,0,1,5}-{3281,2771,0,1,7}-{3283,2776,0,1,6}-{3278,2770,0,1,6}-" @@ -8823,6 +8919,10 @@ "npc_id": "5358", "loc_data": "{2874,2954,0,0,6}-" }, + { + "npc_id": "5359", + "loc_data": "{2693,5065,0,1,0}-{2693,5089,0,1,0}-{2704,5091,0,1,0}-{2710,5095,0,1,0}-{2712,5076,0,1,0}-{2714,5108,0,1,0}-{2716,5092,0,1,0}-{2719,5071,0,1,0}-{2722,5061,0,1,0}-{2732,5087,0,1,0}-{2739,5078,0,1,0}-{2740,5104,0,1,0}-{2747,5083,0,1,0}-{2627,5093,0,1,0}-{2629,5061,0,1,0}-{2638,5090,0,1,0}-{2651,5105,0,1,0}-{2654,5079,0,1,0}-{2663,5116,0,1,0}-{2683,5059,0,1,0}-{2685,5111,0,1,0}-" + }, { "npc_id": "5361", "loc_data": "{3176,5543,0,1,3}-{3191,5542,0,1,4}-{3175,5543,0,1,2}-{3178,5541,0,1,2}-{3187,5542,0,1,3}-{3192,5545,0,1,2}-{3192,5542,0,1,3}-{3179,5549,0,1,6}-{1757,5358,0,1,5}-{1760,5357,0,1,5}-{1755,5352,0,1,5}-{1751,5342,0,1,3}-{1745,5342,0,1,6}-{1739,5342,0,1,3}-{1737,5344,0,1,7}-{1739,5347,0,1,6}-{1740,5350,0,1,5}-{1739,5355,0,1,3}-{1747,5363,0,1,4}-{1749,5363,0,1,4}-{1743,5360,0,1,3}-{1739,5356,0,1,0}-" @@ -10105,11 +10205,11 @@ }, { "npc_id": "6050", - "loc_data": "{3252,3069,0,1,1}-{3242,3059,0,1,7}-{3235,3051,0,1,5}-{3248,3051,0,1,4}-{3257,3055,0,1,3}-{3263,3063,0,1,3}-{3253,3040,0,1,6}-{3243,3039,0,1,6}-{3254,3031,0,1,1}-{3243,3035,0,1,5}-{3232,3039,0,1,2}-{3230,3046,0,1,6}-{3219,3033,0,1,3}-{3219,3022,0,1,1}-{3227,3017,0,1,5}-{3235,3012,0,1,4}-{3243,3019,0,1,2}-{3251,3028,0,1,3}-{3259,3080,0,1,2}-{3246,3080,0,1,3}-{3244,3082,0,1,1}-{3235,3072,0,1,4}-{3267,3048,0,1,0}-{3291,3081,0,1,7}-{3298,3075,0,1,1}-{3284,3076,0,1,3}-{3266,3072,0,1,1}-" + "loc_data": "{3264,3008,0,1,0}-{3266,3008,0,1,0}-{3285,3066,0,1,0}-{3322,3032,0,1,0}-{3323,3055,0,1,0}-{3325,3010,0,1,0}-{3174,3010,0,1,0}-{3198,3061,0,1,0}-{3199,3016,0,1,0}-{3219,3125,0,1,0}-{3233,3075,0,1,0}-{3250,3126,0,1,0}-{3223,3011,0,1,0}-{3228,3060,0,1,0}-{3251,3059,0,1,0}-{3310,3076,0,1,0}-" }, { "npc_id": "6051", - "loc_data": "{3292,3069,0,1,1}-{3285,3071,0,1,1}-{3273,3065,0,1,3}-{3288,3066,0,1,6}-{3281,3057,0,1,5}-{3294,3056,0,1,5}-{3305,3064,0,1,3}-{3279,3078,0,1,4}-{3312,3075,0,1,6}-{3306,3086,0,1,4}-{3272,3082,0,1,4}-" + "loc_data": "{3266,3010,0,1,0}-{3267,3068,0,1,0}-{3287,3065,0,1,0}-{3287,3067,0,1,0}-{3310,3070,0,1,0}-{3312,3068,0,1,0}-{3320,3054,0,1,0}-{3324,3013,0,1,0}-{3325,3033,0,1,0}-{3153,3047,0,1,0}-{3196,3063,0,1,0}-{3199,3036,0,1,0}-{3215,3092,0,1,0}-{3217,3124,0,1,0}-{3260,3077,0,1,0}-{3223,3035,0,1,0}-{3225,3011,0,1,0}-{3283,3084,0,1,0}-" }, { "npc_id": "6052", @@ -11041,7 +11141,7 @@ }, { "npc_id": "6779", - "loc_data": "{3392,2759,0,1,2}-{3408,2763,0,1,7}-{3410,2786,0,1,2}-{3420,2778,0,1,6}-{3427,2792,0,1,6}-{3429,2802,0,1,4}-" + "loc_data": "{3337,2762,0,1,0}-{3340,2767,0,1,0}-{3345,2763,0,1,0}-{3350,2766,0,1,0}-{3352,2761,0,1,0}-{3356,2769,0,1,0}-{3358,2758,0,1,0}-{3359,2763,0,1,0}-{3365,2769,0,1,0}-{3368,2764,0,1,0}-{3375,2762,0,1,0}-{3392,2759,0,1,2}-{3408,2763,0,1,7}-{3410,2786,0,1,2}-{3420,2778,0,1,6}-{3427,2792,0,1,6}-{3429,2802,0,1,4}-" }, { "npc_id": "6780", diff --git a/Server/src/main/content/global/handlers/scenery/SignpostListener.kt b/Server/src/main/content/global/handlers/scenery/SignpostListener.kt index 19622a201..583aa259d 100644 --- a/Server/src/main/content/global/handlers/scenery/SignpostListener.kt +++ b/Server/src/main/content/global/handlers/scenery/SignpostListener.kt @@ -96,24 +96,24 @@ class SignpostListener : InteractionListener { setInterfaceText(player, "Follow the path west to Ardougne.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else if (node.asScenery().location.equals(Location(2604, 3240))) { - setInterfaceText(player, "North to Ardougne Zoo.", 135, 3) // North - setInterfaceText(player, "South to the Monastery.", 135, 9) // South - setInterfaceText(player, "East to the Tower of Life.", 135, 8) // East - setInterfaceText(player, "West to the Clocktower.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else if (node.asScenery().location.equals(Location(2605, 3298))) { - setInterfaceText(player, "North to the Fishing Guild and Baxtorian Falls.", 135, 3) // North - setInterfaceText(player, "South to Ardougne Zoo and Port Khazard.", 135, 9) // South - setInterfaceText(player, "East to Ardougne Market and Witchaven.", 135, 8) // East - setInterfaceText(player, "West to Ardougne Castle and Ardougne West.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else if (node.asScenery().location.equals(Location(2646, 3404))) { - setInterfaceText(player, "North to the Ranging Guild and Seer's Village.", 135, 3) // North - setInterfaceText(player, "South to the Ardougne City.", 135, 9) // South - setInterfaceText(player, "East to the Sorcerer's Tower.", 135, 8) // East - setInterfaceText(player, "West to the Fishing Guild.", 135, 12) // West - openInterface(player, Components.AIDE_COMPASS_135) - } else { + setInterfaceText(player, "North to the Ardougne City Zoo.", 135, 3) // North + setInterfaceText(player, "South to the Monastery.", 135, 9) // South + setInterfaceText(player, "East to the Tower of Life.", 135, 8) // East + setInterfaceText(player, "West to the Clocktower.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else if (node.asScenery().location.equals(Location(2605, 3298))) { + setInterfaceText(player, "North to the Fishing Guild and Hemenster.", 135, 3) // North + setInterfaceText(player, "South to the Ardougne City Zoo.", 135, 9) // South + setInterfaceText(player, "East to Ardougne Market.", 135, 8) // East + setInterfaceText(player, "West to Ardougne Castle and West Ardougne.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else if (node.asScenery().location.equals(Location(2646, 3404))) { + setInterfaceText(player, "North to the Ranging Guild and Seer's Village.", 135, 3) // North + setInterfaceText(player, "South to the Ardougne City.", 135, 9) // South + setInterfaceText(player, "East to the Sorcerer's Tower.", 135, 8) // East + setInterfaceText(player, "West to the Fishing Guild.", 135, 12) // West + openInterface(player, Components.AIDE_COMPASS_135) + } else { setInterfaceText(player, "North to unknown.", 135, 3) // North setInterfaceText(player, "South to unknown.", 135, 9) // South setInterfaceText(player, "East to unknown.", 135, 8) // East @@ -133,7 +133,7 @@ class SignpostListener : InteractionListener { setInterfaceText(player, "North to Edgeville.", 135, 3) // North setInterfaceText(player, "South to Draynor Manor.", 135, 9) // South setInterfaceText(player, "East to Varrock west gate.", 135, 8) // East - setInterfaceText(player, "West to Barbarian Village and Falador.", 135, 12) // West + setInterfaceText(player, "West to Barbarian Village.", 135, 12) // West openInterface(player, Components.AIDE_COMPASS_135) } else { setInterfaceText(player, "North to unknown.", 135, 3) // North @@ -204,17 +204,17 @@ class SignpostListener : InteractionListener { * SceneryDefinition.forId(4133).getHandlers().put("option:read", this); * SceneryDefinition.forId(4134).getHandlers().put("option:read", this); * SceneryDefinition.forId(4135).getHandlers().put("option:read", this); - * - * SceneryDefinition.forId(5164).getHandlers().put("option:read", this); No - * SceneryDefinition.forId(10090).getHandlers().put("option:read", this); No - * - * SceneryDefinition.forId(13873).getHandlers().put("option:read", this); No - * - * SceneryDefinition.forId(15522).getHandlers().put("option:read", this); No - * SceneryDefinition.forId(25397).getHandlers().put("option:read", this); No - * - * SceneryDefinition.forId(30039).getHandlers().put("option:read", this); // ???? - * SceneryDefinition.forId(30040).getHandlers().put("option:read", this); // ?????? + * SceneryDefinition.forId(5164).getHandlers().put("option:read", this); + * SceneryDefinition.forId(10090).getHandlers().put("option:read", this); + * SceneryDefinition.forId(13873).getHandlers().put("option:read", this); + * SceneryDefinition.forId(15522).getHandlers().put("option:read", this); + * SceneryDefinition.forId(25397).getHandlers().put("option:read", this); + * SceneryDefinition.forId(30039).getHandlers().put("option:read", this); + * SceneryDefinition.forId(30040).getHandlers().put("option:read", this); + * SceneryDefinition.forId(31296).getHandlers().put("option:read", this); + * SceneryDefinition.forId(31298).getHandlers().put("option:read", this); + * SceneryDefinition.forId(31299).getHandlers().put("option:read", this); + * SceneryDefinition.forId(31300).getHandlers().put("option:read", this); * // ObjectDefinition.forId(31301).getConfigurations().put("option:read", this);//goblin village * return this; * } diff --git a/Server/src/main/content/global/skill/slayer/dungeon/SmokeDungeon.java b/Server/src/main/content/global/skill/slayer/dungeon/SmokeDungeon.java index edce0a909..3dec3dd92 100644 --- a/Server/src/main/content/global/skill/slayer/dungeon/SmokeDungeon.java +++ b/Server/src/main/content/global/skill/slayer/dungeon/SmokeDungeon.java @@ -132,7 +132,7 @@ public final class SmokeDungeon extends MapZone implements Plugin { * @param player the player. */ private static void effect(Player player) { - int hit = 2; + int hit = 10; setDelay(player); if (RandomFunction.random(2) == 1) { player.sendChat(CHATS[RandomFunction.random(CHATS.length)]); diff --git a/Server/src/main/content/region/desert/bandits/handlers/BanditDialogue.kt b/Server/src/main/content/region/desert/bandits/handlers/BanditDialogue.kt new file mode 100644 index 000000000..2b6d8f8ac --- /dev/null +++ b/Server/src/main/content/region/desert/bandits/handlers/BanditDialogue.kt @@ -0,0 +1,63 @@ +package content.region.desert.bandits.handlers + +import content.region.desert.quest.deserttreasure.DesertTreasure +import core.api.getAttribute +import core.api.inInventory +import core.api.openDialogue +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class BanditDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun newInstance(player: Player): DialoguePlugin { + return BanditDialogue(player) + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, BanditDialogueFile(), npc) + return false + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.BANDIT_1926) + } +} +class BanditDialogueFile : DialogueBuilderFile() { + + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 100) + .npcl("So you're the one who freed Azzanadra from his prison? Thank you, kind @g[sir,lady]!") + .end() + + b.onQuestStages(DesertTreasure.questName, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) + .npcl("What do you want @g[lad,lass]?") + .playerl("I'm here on an archaeological expedition for the Museum of Varrock. I believe there may be some interesting artefacts in the area.") + .branch { player -> + return@branch (0..4).random() + }.let { branch -> + branch.onValue(0) + .npcl("You are a crazy @g[man,woman]. The only thing you will find out here in the desert is your death.") + .end() + branch.onValue(1) + .npcl("I have no interest in the world that betrayed my people. Search where you will, you will find nothing.") + .end() + branch.onValue(2) + .npcl("The gods forsake us, and drove us to this place. Anything of worth has been long gone.") + .end() + branch.onValue(3) + .npcl("I'm sure there are many secrets buried beneath the sands here. The thing about this being a desert, is that they're likely to stay that way.") + .end() + branch.onValue(4) + .npcl("Do I look like I care who you are or where you came from?") + .end() + } + + b.onPredicate { _ -> true } + .npcl("Get out of this village. You are not welcome here.") + .end() + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/handlers/KhardianDesertPlugin.java b/Server/src/main/content/region/desert/handlers/KhardianDesertPlugin.java deleted file mode 100644 index ed0ba3d8c..000000000 --- a/Server/src/main/content/region/desert/handlers/KhardianDesertPlugin.java +++ /dev/null @@ -1,47 +0,0 @@ -package content.region.desert.handlers; - -import core.cache.def.impl.SceneryDefinition; -import core.game.global.action.DoorActionHandler; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Handles interactions in the khardian desert. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class KhardianDesertPlugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(6481).getHandlers().put("option:enter", this); - SceneryDefinition.forId(6545).getHandlers().put("option:open", this); - SceneryDefinition.forId(6547).getHandlers().put("option:open", this); - SceneryDefinition.forId(6551).getHandlers().put("option:use", this); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - switch (node.getId()) { - case 6481: - player.teleport(new Location(3233, 9313, 0)); - break; - case 6545: - case 6547: - // player.getPacketDispatch().sendMessage("A mystical power has sealed this door..."); - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()); - break; - case 6551: - player.teleport(new Location(3233, 2887, 0)); - break; - } - return true; - } - -} diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt index 0ec1e3d33..397cd052f 100644 --- a/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt +++ b/Server/src/main/content/region/desert/quest/deserttreasure/ArchaeologistDialogue.kt @@ -1,103 +1,211 @@ -package rs09.game.content.dialogue.region.lletya +package content.region.desert.quest.deserttreasure -import core.api.setQuestStage +import content.global.handlers.iface.BookInterface +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player -import core.game.node.entity.skill.Skills import core.plugin.Initializable +import org.rs09.consts.Items import org.rs09.consts.NPCs -import content.data.Quests - -/** - * @author qmqz - */ @Initializable +/** Known in RS3 as Asgarnia Smith */ class ArchaeologistDialogue(player: Player? = null) : DialoguePlugin(player){ - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - if (!player.questRepository.hasStarted(Quests.DESERT_TREASURE)) { - if (player.questRepository.isComplete(Quests.THE_DIG_SITE) && - player.questRepository.isComplete(Quests.THE_TOURIST_TRAP) && - player.questRepository.isComplete(Quests.TEMPLE_OF_IKOV) && - player.questRepository.isComplete(Quests.PRIEST_IN_PERIL) && - player.questRepository.isComplete(Quests.WATERFALL_QUEST) && - player.questRepository.isComplete(Quests.TROLL_STRONGHOLD) && - player.skills.getStaticLevel(Skills.SLAYER) >= 10 && - player.skills.getStaticLevel(Skills.FIREMAKING) >= 50 && - player.skills.getStaticLevel(Skills.MAGIC) >= 50 && - player.skills.getStaticLevel(Skills.THIEVING) >= 53 ) { - player(FacialExpression.FRIENDLY,"Hello there.").also { stage = 0 } - } else { - player(FacialExpression.FRIENDLY,"Hello there.").also { stage = 999 } - } - - } else { - - } - - return true - } - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when(stage){ - - 999 -> sendDialogue("He seems to be lost in his own thoughts...").also { stage = 99 } - - 0 -> npc(FacialExpression.FRIENDLY, "Howdy stranger. What brings you out to these parts?").also { stage++ } - 1 -> options("What are you doing here?", "Do you have any quests?", "Who are you?", "Nothing really.").also { stage++ } - 2 -> when (buttonId) { - //1 -> todo - 2 -> player(FacialExpression.FRIENDLY, "Do you have any quests?", "Call it a hunch, but you look like the type of man who", "might...").also { stage = 20 } - //3 -> todo - //4 -> todo - } - - 20 -> npc(FacialExpression.HALF_THINKING, "Well, it's funny you should say that.", - "I'm not sure if I would really call it a quest as such,", - "but I found this ancient stone tablet in one of my", - "excavations, and it would really help me out if you").also { stage++ } - 21 -> npc(FacialExpression.FRIENDLY, "could go and take it back to the digsite for me and get", - "it examined.").also { stage++ } - 22 -> npc(FacialExpression.NEUTRAL, "It's very old, and I don't recognise and of the", - "inscriptions on it.").also { stage++ } - 23 -> options("Yes, I'll help you.", "No thanks, I don't want to help.").also { stage++ } - 24 -> when(buttonId) { - 1 -> player(FacialExpression.FRIENDLY, "Sure, I was heading that way anyways.", - "Any particular person at the digsite you want me to", - "talk to?").also { stage = 30 } - // 2 -> todo - } - - 30 -> npc(FacialExpression.NEUTRAL, "His name's Terry Balando. Give it to nobody but him.", - "I'm sorry, I can't entrust you with the actual tablet I", - "found, but it is far too valuable to give away, but I took", - "these etchings - they should be enough for him to make").also { stage++ } - 31 -> npc(FacialExpression.NEUTRAL, "a preliminary translation on.", - "Come back and let me know what he says, I would hate", - "to waste my time excavating anything that isn't worth", - "my time as a world famous archaeologist!").also { - player.questRepository.getQuest(Quests.DESERT_TREASURE).start(player) - setQuestStage(player, Quests.DESERT_TREASURE, 1) - stage = 99 - } - - - - - 99 -> end() - } - return true + openDialogue(player!!, ArchaeologistDialogueFile(), npc) + return false } - override fun newInstance(player: Player?): DialoguePlugin { return ArchaeologistDialogue(player) } - override fun getIds(): IntArray { return intArrayOf(NPCs.ARCHAEOLOGIST_1918) } } + +class ArchaeologistDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 0) + .player(FacialExpression.FRIENDLY,"Hello there.") + .branch { player -> + return@branch if (DesertTreasure.hasRequirements(player)) { 1 } else { 0 } + }.let{ branch -> + // Failure branch + branch.onValue(0) + .line("He seems to be lost in his own thoughts...") + .end() + return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch. + }.onValue(1) // Success branch + .npc(FacialExpression.FRIENDLY, "Howdy stranger. What brings you out to these parts?") + .let { path -> + val originalPath = b.placeholder() + path.goto(originalPath) + originalPath.builder().options().let { optionBuilder -> + optionBuilder.option("What are you doing here?") + .player("Nothing much - What are you doing here?", "It doesn't seem like there's much to do out here in the", "desert!") + .npc("Well, that's where you'd be wrong.", "I work for the Archaeological Society of Varrock, and", "have been excavating around here recently.") + .npcl("Was there something you specifically wanted?") + .goto(originalPath) + optionBuilder.option("Do you have any quests?") + .player(FacialExpression.FRIENDLY, "Do you have any quests?", "Call it a hunch, but you look like the type of man who", "might...") + .npc(FacialExpression.HALF_THINKING, "Well, it's funny you should say that.", "I'm not sure if I would really call it a quest as such,", "but I found this ancient stone tablet in one of my", "excavations, and it would really help me out if you") + .npc(FacialExpression.FRIENDLY, "could go and take it back to the digsite for me and get", "it examined.") + .npc(FacialExpression.NEUTRAL, "It's very old, and I don't recognise and of the", "inscriptions on it.") + .options().let { optionBuilder2 -> + optionBuilder2.option("Yes, I'll help you.") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.ETCHINGS_4654) + } + .player("Sure, I was heading that way anyway.", "Any particular person at the digsite you want me to", "talk to?") + .npc(FacialExpression.NEUTRAL, "His name's Terry Balando. Give it to nobody but him.", "I'm sorry, I can't entrust you with the actual tablet I", "found, but it is far too valuable to give away, but I took", "these etchings - they should be enough for him to make") + .npc(FacialExpression.NEUTRAL, "a preliminary translation on.", "Come back and let me know what he says, I would hate", "to waste my time excavating anything that isn't worth", "my time as a world famous archaeologist!") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 0) { + setQuestStage(player, DesertTreasure.questName, 1) + } + } + optionBuilder2.option("No thanks, I don't want to help.") + .playerl("No thanks. Playing delivery boy doesn't really sound like much fun to me. ") + .npcl(" Well, okay. Can't say as I blame you for thinking that. I'll go take it there myself later I guess.") + .end() + } + optionBuilder.option("Who are you?") + .playerl(FacialExpression.THINKING, "Who are you, anyway?") + .npc(FacialExpression.EXTREMELY_SHOCKED, "You don't recognize me???", "I am the world famous Asgarnia Smith, Archaeologist", "extraordinaire!") + .npc(FacialExpression.HALF_THINKING, "I am the one who discovered the long forgotten", "Temple of Ikov!", "The one who unearthed the strange trap filled arena", "in Brimhaven!") + .npc(FacialExpression.HALF_THINKING, "I'm the leading archaeological expert of our time!", "I was voted archaeologist of the year four years", "running by the Varrock Herald! Are you REALLY", "sure you've never heard of me?") + .playerl(FacialExpression.THINKING, "No, I really haven't.") + .npc(FacialExpression.EXTREMELY_SHOCKED, "Well then, I'm confused.", "Why did you come over and speak to me if you don't", "know who I am? What do you want?") + .goto(originalPath) + optionBuilder.option("Nothing really.") + .playerl("Nothing really. I'm just wandering around for no good reason.") + .npcl("Uh-huh. Well, if you'll excuse me, I have a lot more work to do before I can bed down for the night.") + .end() + } + } + + + b.onQuestStages(DesertTreasure.questName, 1,2) + .npcl("So what did Terry Balando say about those etchings? Did he give you a translation for me?") + .playerl("Um...yeah...about that... I kind of didn't go and speak to him yet...") + .npcl("Well what are you waiting for? A written invitation? All I want you to do is take those etchings up to the digsite for me!") + .playerl("Okay, I'll do that then.") + .end() + + b.onQuestStages(DesertTreasure.questName, 3) + .playerl("Hello there.") + .npcl("So what did Terry Balando say about those etchings? Did he give you a translation for me?") + .branch { player -> + return@branch if (inInventory(player, Items.TRANSLATION_4655)) { 1 } else { 0 } + }.let{ branch -> + // Failure branch + branch.onValue(0) + .playerl("Yeah, he did. But I don't have it with me.") + .npcl("...") + .npcl("I see.") + .npcl("Well could you go and get me that translation? It could be vital!") + .end() + return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch. + }.onValue(1) // Success branch + .playerl("Yeah, he did. I have it here in this book.") + .npcl("Did you take a read of this? It will do you good to understand how this profession works. Here, have a read.") + .options().let { optionBuilder -> + optionBuilder.option("Read book") + .endWith { _, player -> + BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, TranslationBook.Companion::display) + } + return@let optionBuilder + } + .option("Don't read book") + .playerl("Yeah, I did. Kind of boring really.") + .npcl("Excellent. Just give me a moment to read this, and talk to me again in a second.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 3) { + removeItem(player, Items.TRANSLATION_4655) // remove if exists + setQuestStage(player, DesertTreasure.questName, 4) + } + } + + b.onQuestStages(DesertTreasure.questName, 4) + .playerl("Hello there.") + .npcl("Hmmm. Interesting. It seems to me like there's some kind of treasure hidden out in the desert.") + .npcl("So what do you say? Fancy being a treasure hunter like me?") + .playerl("Uh... don't you mean archaeologist?") + .npcl("Yeeees... An archaeologist...") + .npcl("It's all this hot sun getting to me I think.") + .npcl("Well anyway, let's just assume there is a treasure hidden in the desert somewhere, and let's just say for the sake of argument that maybe if I found a big stash of gold and treasure I wouldn't necessarily just hand it") + .npcl("all over to the Museum of Varrock.") + .npcl("Let's also say, purely hypothetically, that if there were such a big stash of treasure and someone were to help me find it, then that hypothetical personal might be entitled to, oh, let's say a purely for the sake of") + .npcl("argument thirty percent split...") + .playerl("Fifty percent.") + .npcl("That's right!") + .npcl("A purely for the sake of argument fifty-fifty split on this hypothetical treasure, should it exist...") + .npcl("Do you see where I'm going with this?") + .playerl("You want me to help you find some treasure for a fifty percent share, as long as I don't tell anybody, and your reputation as an esteemed archaeologist with the Museum of Varrock remains intact, and nobody") + .playerl("discovers you're actually just a treasure hunter?") + .npcl("Uh... yes, but the way you said it makes it sound like I'm doing something wrong...") + .npcl("So what do you say? Partners?") + .options() + .let { optionBuilder -> + optionBuilder.option("Help him") + .playerl("Well... I guess nobody is really going to lose out on anything, and we don't even know if there is any treasure...") + .playerl("Aw, go on then. Count me in.") + .npcl("Good @g[lad,lass]! Well, if we split up we'll be able to find treasure quicker.") + .npcl("I'll continue searching around here in this Bedabin Camp, you head due South to the Bandit Village. If either of us find anything, we'll come find each other and say what, okay?") + .npcl("You head due South, see what you can find out about this tablet.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 4) { + setQuestStage(player, DesertTreasure.questName, 5) + } + } + optionBuilder.option("Don't help him") + .playerl("This all sounds very immoral, and I don't want any part of your seedy little schemes.") + .npcl("Aw, c'mon, cut me a break here man! Look, nobody is really getting hurt, right? This treasure is either going to lie around in some underground ruin, or lie around in some museum for") + .npcl("people to look at!") + .npcl("It makes sense for the people to go to all the risk to get a little payback for it, right? Besides, anything of real historical value we can hand over to the museum - we'll just keep the cash for") + .npcl("ourselves!") + .npcl("C'mon... what do you say? Partners?") + .options() + .let { optionBuilder -> + optionBuilder.option("Help him") + .playerl("Well... I guess nobody is really going to lose out on anything, and we don't even know if there is any treasure...") + .playerl("Aw, go on then. Count me in.") + .npcl("Good @g[lad,lass]! Well, if we split up we'll be able to find treasure quicker.") + .npcl("I'll continue searching around here in this Bedabin Camp, you head due South to the Bandit Village. If either of us find anything, we'll come find each other and say what, okay?") + .npcl("You head due South, see what you can find out about this tablet.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 4) { + setQuestStage(player, DesertTreasure.questName, 5) + } + } + optionBuilder.option("Don't help him") + .playerl("I don't trust anything about your little scheme, including you! I want nothing to do with this!") + .npcl("Eh, you'll come running back when you realize just how much money we could be talking here.") + .npcl("I'll see you again when you come crawling back, begging to be cut in on the deal.") + .end() + } + } + + b.onQuestStages(DesertTreasure.questName, 5) + .playerl("Hello there.") + .npcl("Hello again. You find any signs of that treasure yet?") + .playerl("Not yet...") + .npcl("Well, head south to that bandit camp. I bet if there's anything out here, they'll know about it. Don't let on it might be valuable though! Those thieves will steal it as soon as look at you!") + + b.onQuestStages(DesertTreasure.questName, 6,7,8) + .playerl("Hello there.") + .npcl("Hello again. You find any signs of that treasure yet?") + .playerl("Not as such... Although I think I'm onto something of a promising lead...") + .playerl("Did you ever hear of something called the Diamonds of Azzanadra?") + .npcl("Diamonds of Azzanadra? That sounds very promising indeed!") + .playerl("So you have heard of them?") + .npcl("Nope, never heard of them before, but you said diamonds! Diamonds are always promising!") + + + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/AzzanadraDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/AzzanadraDialogue.kt new file mode 100644 index 000000000..c8401ac87 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/AzzanadraDialogue.kt @@ -0,0 +1,59 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.SpellBookManager +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class AzzanadraDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, AzzanadraDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return AzzanadraDialogue(player) + } + override fun getIds(): IntArray { + /* This is wrong SCARABS_1970 should be AZZANADRA_1970 */ + return intArrayOf(NPCs.SCARABS_1970, NPCs.AZZANADRA_1971) + } +} + +class AzzanadraDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 10) + .npcl(FacialExpression.OLD_DEFAULT, "I knew they could not trap me here for long!") + .npcl(FacialExpression.OLD_DEFAULT, "Well done, soldier, tell me, how goes the battle?") + .playerl(FacialExpression.THINKING, "Battle?") + .npcl(FacialExpression.OLD_DEFAULT, "You do not know of the battle?") + .npcl(FacialExpression.OLD_DEFAULT, "More time must have passed than I had thought...") + .npcl(FacialExpression.OLD_DEFAULT, "Tell me, what news of great Paddewwa? Do the shining spires of Lassar still stand? And what of glorious Annakarl? The fortress is still intact?") + .player("Uh...", "Sorry, I've never heard of them...") + .npcl(FacialExpression.OLD_SAD, "No!") + .npcl(FacialExpression.OLD_SAD, "My lord... What has become of you? I cannot hear your voice in my mind anymore!") + .npcl(FacialExpression.OLD_DEFAULT, "My thanks to you brave warrior for your help in freeing me from this accursed tomb, but it seems I have much to do to make amends.") + .npcl(FacialExpression.OLD_DEFAULT, "If the shining cities no longer stand, then it means that we must have failed my lord...") + .npcl(FacialExpression.OLD_DEFAULT, "How long have I been trapped here? Master... Have you truly been dispatched from this world?") + .npcl(FacialExpression.OLD_DEFAULT, "Warrior, for your efforts in freeing me, I offer you the gift of knowledge.") + .npcl(FacialExpression.OLD_DEFAULT, "I bestow upon you the ancient magicks, taught me by my Lord before his disappearance, may you use them well in battle for our people!") + .npcl(FacialExpression.OLD_DEFAULT, "They will replace the knowledge you previously had, but you may switch between them by praying at the altar in this room at any time.") + .npcl(FacialExpression.OLD_DEFAULT, "I trust that we shall meet again adventurer, I offer you the blessings of myself and my master in all of your endeavours!") + .npcl(FacialExpression.OLD_DEFAULT, "Now, I must leave you, for there must be some trace of my master's power left somewhere. Feel free to use the portal I shall create to return here easily in the future!") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 10) { + sendMessage(player,"A strange wisdom has filled your mind...") + finishQuest(player, DesertTreasure.questName) + player.spellBookManager.setSpellBook(SpellBookManager.SpellBook.ANCIENT) + player.spellBookManager.update(player) + } + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/BartenderDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/BartenderDialogue.kt new file mode 100644 index 000000000..2e3e78954 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/BartenderDialogue.kt @@ -0,0 +1,155 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class BartenderDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, BartenderDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return BartenderDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.BARTENDER_1921) + } +} +class BartenderDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4) + .npcl(FacialExpression.ANNOYED, "Get out of here. I have nothing to say to the likes of you.") + .end() + + b.onQuestStages(DesertTreasure.questName, 5) + .branch { player -> + return@branch if (getAttribute(player, DesertTreasure.attributeBoughtBeer, false)) { 1 } else { 0 } + }.let{ branch -> + branch.onValue(1) + .npcl("You've had your drink, now get out of here. I have nothing to say to the-") + .playerl("No, Wait! Look, I'm here on an archaeological expedition for the Museum of Varrock.") + .playerl("I am only here looking for artefacts...") + .npcl("Oh really? Our inheritance is only sand and death. What do you expect to find out here in this desert forsaken by the gods?") + .options() + .let { optionBuilder -> + optionBuilder.option("I heard about treasure...") + .playerl("As I understand it there's some kind of hidden treasure in these parts...") + .npcl("Look around @g[pal,lady]. Does it looks like there's any treasure near here?") + .npcl("If I were you I'd get lost before someone takes a dislike to your face and removes it for you.") + .end() + + optionBuilder.option("I heard about four diamonds...") + .playerl("I heard a rumour about four diamonds or crystals...") + .npcl("The four diamonds of Azzanadra??? How came you to know of this?") + .playerl("You've heard of them then?") + .npcl("It's just a fairy tale for children. Maybe one of the village elders might know more, but it's not really something I care about.") + .npcl("Now get out of here, your sort isn't welcome in my bar.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 5) { + setQuestStage(player, DesertTreasure.questName, 6) + } + } + + optionBuilder.option("I heard about a fortress...") + .playerl("Certain things have led me to believe there may be some kind of ruined fortress around here...") + .npcl("Doubt it. What in the world would someone need to guard against in the middle of this desert?") + .npcl("A bad attack of sand? I think you're on the wrong track, mister so-called archaeologist.") + .end() + } + + branch.onValue(0) + .npcl("If you're not buying anything, I have nothing to say to you.") + .options() + .let { optionBuilder -> + optionBuilder.option("Ask about Desert Treasure") + .playerl("As I understand it there's some kind of hidden treasure in these parts...") + .npcl("Look around @g[pal,lady]. Does it looks like there's any treasure near here?") + .npcl("If I were you I'd get lost before someone takes a dislike to your face and removes it for you.") + .end() + optionBuilder.option("Buy a drink") + .branch { player -> + return@branch if (inInventory(player, Items.COINS_995, 650)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("What's that? You wanna buy a beer? It'll cost ya 650 coins.") + .options() + .let { optionBuilder -> + optionBuilder.option("Buy a beer") + .betweenStage { _, player, _, _ -> + if (removeItem(player, Item(Items.COINS_995, 650))) { + addItemOrDrop(player, Items.BANDITS_BREW_4627) + setAttribute(player, DesertTreasure.attributeBoughtBeer, true) + } + } + .npcl("There you go. Now get out, we don't like your sort around here.") + .end() + optionBuilder.option("Don't buy anything") + .npcl("Get out of my bar then! We don't like your sort round here!") + .end() + } + + branch.onValue(0) + .npcl("You ain't got the 650 coins it costs to buy it, and I'm glad 'cos I didn't want to serve you anyway.") + .end() + } + + } + } + + + b.onQuestStages(DesertTreasure.questName, 6,7,8,9,10,11) + .branch { player -> + return@branch if (getAttribute(player, DesertTreasure.attributeBoughtBeer, false)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("You've had your drink, now get out of here. I have nothing to say to the-") + .playerl("No, Wait! Look, I'm here on an archaeological expedition for the Museum of Varrock.") + .playerl("I am only here looking for artefacts...") + .npcl("Oh really? Our inheritance is only sand and death. What do you expect to find out here in this desert forsaken by the gods?") + .options() + .let { optionBuilder -> + optionBuilder.option("I heard about treasure...") + .playerl("As I understand it there's some kind of hidden treasure in these parts...") + .npcl("Look around @g[pal,lady]. Does it looks like there's any treasure near here?") + .npcl("If I were you I'd get lost before someone takes a dislike to your face and removes it for you.") + .end() + + optionBuilder.option("I heard about four diamonds...") + .playerl("I heard a rumour about four diamonds or crystals...") + .npcl("The four diamonds of Azzanadra??? How came you to know of this?") + .playerl("You've heard of them then?") + .npcl("It's just a fairy tale for children. Maybe one of the village elders might know more, but it's not really something I care about.") + .npcl("Now get out of here, your sort isn't welcome in my bar.") + .end() + + optionBuilder.option("I heard about a fortress...") + .playerl("Certain things have led me to believe there may be some kind of ruined fortress around here...") + .npcl("Doubt it. What in the world would someone need to guard against in the middle of this desert?") + .npcl("A bad attack of sand? I think you're on the wrong track, mister so-called archaeologist.") + .end() + + optionBuilder.option("I heard of the Diamonds of Azzanadra.") + .playerl("Tell me all you know about the Diamonds of Azzanadra.") + .npcl("Not that I think it's any of your business, but when I was a child I remember hearing the legend.") + .npcl("I don't recall it particularly well, other than they are said to contain an incredible power.") + .npcl("If you really want to hear more about it you'd be best off finding someone who cares about the past, and the history of this area, and stop bothering me.") + .end() + } + } + + b.onQuestStages(DesertTreasure.questName, 100) + .npcl("So you're the @g[fella,lass] that freed Azzanadra, huh? Fair play to ya. What will you have?") + .end() + + } +} diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DamisBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DamisBehavior.kt new file mode 100644 index 000000000..c8b9af6d9 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DamisBehavior.kt @@ -0,0 +1,81 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.item.GroundItemManager +import core.game.node.item.Item +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class DamisBehavior : NPCBehavior(NPCs.DAMIS_1974, NPCs.DAMIS_1975) { + + var clearTime = 0 + + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + if (attacker is Player) { + if (attacker == getAttribute(self, "target", null)) { + return true + } + sendMessage(attacker, "It's not after you...") + } + return false + } + + override fun tick(self: NPC): Boolean { + val player: Player? = getAttribute(self, "target", null) + if (clearTime++ > 800) { + clearTime = 0 + if (player != null) { + sendMessage(player, "Damis has vanished once more into the shadows...") + removeAttribute(player, DesertTreasure.attributeDamisInstance) + } + poofClear(self) + } + return true + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + if (state.estimatedHit + Integer.max(state.secondaryHit, 0) >= self.skills.lifepoints && self.id == NPCs.DAMIS_1974) { + state.estimatedHit = self.skills.lifepoints + 1 + state.secondaryHit = -1 + + transformNpc(self, NPCs.DAMIS_1975, 500) + self.skills.lifepoints = self.skills.maximumLifepoints + sendChat(self, "Armour... is for restraint, not... protection...") + queueScript(self, 2, QueueStrength.NORMAL) { stage: Int -> + sendChat(self, "Now I show... you... my true power!") + self.properties.attackSpeed = 3 + return@queueScript stopExecuting(self) + } + } + } + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + // In second form, drain prayer by 5. + if (self.id == NPCs.DAMIS_1975) { + victim.skills.decrementPrayerPoints(5.0) + } + } + + + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + if (self.id == NPCs.DAMIS_1975) { + if (DesertTreasure.getSubStage(killer, DesertTreasure.attributeShadowStage) == 3) { + GroundItemManager.create(Item(Items.SHADOW_DIAMOND_4673), self.location, killer) + DesertTreasure.setSubStage(killer, DesertTreasure.attributeShadowStage, 100) + removeAttribute(killer, DesertTreasure.attributeFareedInstance) + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasure.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasure.kt index f42498ac6..f23f6e024 100644 --- a/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasure.kt +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasure.kt @@ -1,103 +1,544 @@ -//package rs09.game.content.quest.members.deserttreasure +package content.region.desert.quest.deserttreasure -//import core.game.node.entity.player.Player -//import core.game.node.entity.player.link.quest.Quest -//import core.game.node.entity.skill.Skills -//import core.plugin.Initializable +import content.data.Quests +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items /** - * @author qmqz + * Desert Treasure Quest + * + * https://www.youtube.com/watch?v=INaSdOAHdT8: Jesus fucking devil best shit on planet fuckall 31:57 + * https://www.youtube.com/watch?v=LAoOISdsX4w: This guy did the best initial quest journal and then ignored the rest. + * https://www.youtube.com/watch?v=3cyU36qNBpI: one impt quest log part in the front. + * https://www.youtube.com/watch?v=pY-Czja2lE4: Good shit part 2 6:24 + * https://www.youtube.com/watch?v=NB1-m_hoTPk: Blur ass quest log. + * https://www.youtube.com/watch?v=bcy54b6NnJs: Blur ass quest log. + * https://www.youtube.com/watch?v=J_dfMXFz3WQ: Blur ass quest log. + * https://www.youtube.com/watch?v=7n0OcHUNFHc: Blur ass quest log 1:07. + * https://www.youtube.com/@Gunz4Range/videos + * https://www.youtube.com/watch?v=baQ6oJOk7Gc + * https://www.youtube.com/watch?v=u0C2zW6mrcc: Blur ass ending quest log 3:23 + * https://www.youtube.com/watch?v=SUzM0WKY6jk: 1:03 + * https://www.youtube.com/watch?v=3AA5fkkBW-I: 2:05 + * + * https://www.youtube.com/watch?v=ofRV2-h3Dug: 17:21 27:45 + * + * if (VARPBIT[358] == 15) return 2; if (VARPBIT[358] == 0) return 0; return 1; }; if (arg0 == 13) */ +@Initializable +class DesertTreasure : Quest(Quests.DESERT_TREASURE,45, 44, 3, 440, 358, 0, 1, 15){ -//@Initializable -//class DesertTreasure : Quest("Desert Treasure",15, 44, 3, 440, 0, 1, 15){ + companion object { + val questName = Quests.DESERT_TREASURE + /** This is an important varbit as it is literally controlling the Quest varbit (440 Varp 0-14 bits -> 358 Varbit )*/ + const val varbitDesertTreasure = 358 // 10-15-Eblis 1924 shows up other values Eblis disappears. This is tied to the quest. - //override fun drawJournal(player: Player?, stage: Int) { - // super.drawJournal(player, stage) - // var line = 12 + // Desert Treasure Start + const val attributeBoughtBeer = "/save:quest:deserttreasure-boughtbeer" + const val attributeCountMagicLogs = "/save:quest:deserttreasure-countmagiclogs" + const val attributeCountSteelBars = "/save:quest:deserttreasure-countsteelbars" + const val attributeCountMoltenGlass = "/save:quest:deserttreasure-countmoltenglass" + const val attributeCountBones = "/save:quest:deserttreasure-countbones" + const val attributeCountAshes = "/save:quest:deserttreasure-countashes" + const val attributeCountCharcoal = "/save:quest:deserttreasure-countcharocal" + const val attributeCountBloodRune = "/save:quest:deserttreasure-countbloodrune" + const val varbitMirrors = 392 // Set to 1 to show mirrors, they are cactuses before desert treasure. - //val stage = player?.questRepository?.getStage("Desert Treasure")!! + // Blood Diamond + const val attributeBloodStage = "/save:quest:deserttreasure-bloodstage" + const val attributeDessousInstance = "quest:deserttreasure-dessousinstance" - //when (stage) { - // 0 -> { - // line(player,"I can start this quest by speaking to !!The Archaeologist??", line++) - // line(player,"who is exploring the !!Bedabin Camp?? South West of the", line++) - // line(player,"!!Shantay Pass.??", line++) - // line(player,"To complete this quest I will need:", line++) - // if (player.skills.getStaticLevel(Skills.SLAYER) < 10) { - // line(player,"Level 10 Slayer", line++) - // } else { - // line(player,"---Level 10 Slayer/--", line++) - // } - // if (player.skills.getStaticLevel(Skills.SLAYER) < 10) { - // line(player,"Level 50 Firemaking", line++) - // } - // if (player.skills.getStaticLevel(Skills.SLAYER) < 10) { - // line(player,"Level 50 Magic", line++) - // } - // if (player.skills.getStaticLevel(Skills.SLAYER) < 10) { - // line(player,"Level 53 Thieving", line++) - // } - // line(player,"I must have completed the following quests:", line++) + // Smoke Diamond + const val attributeSmokeStage = "/save:quest:deserttreasure-smokestage" + const val attributeUnlockedGate = "/save:quest:deserttreasure-unlockedgate" + const val attributeFareedInstance = "quest:deserttreasure-fareedinstance" + const val varbitStandingTorchNorthEast = 360 // North East standing torch 6406 + const val varbitStandingTorchSouthEast = 361 // South East standing torch 6408 + const val varbitStandingTorchSouthWest = 362 // South West standing torch 6410 + const val varbitStandingTorchNorthWest = 363 // North West standing torch 6412 - // if (player.questRepository.isComplete("The Digsite Quest")) { - // line(player,"---!!The digsite Quest??/--", line++) - // } else { - // line(player,"!!The digsite Quest??", line++) - // } + // Ice Diamond + const val attributeIceStage = "/save:quest:deserttreasure-icestage" + const val attributeTrollKillCount = "/save:quest:deserttreasure-iciclecount" + const val attributeKamilInstance = "quest:deserttreasure-kamilinstance" + const val varbitFrozenFather = 380 // 0-frozen 1-defrosted | Base: 1943 Iced: 1944 Broke: 1948 Reunion: 1947 + const val varbitFrozenMother = 381 // 0-frozen 1-defrosted | Base: 1945 Iced: 1946 Broke: 1950 Reunion: 1949 + const val varbitChildReunite = 382 // 0-frozen 4-reunited 5-reunited 6-varbitfails/ends (This varbit seems to manage ice stages...) + // 0 - start, 1 - feed the crying child, 2 - fought kamil, 3 - unfreeze dad/mum, 4 - reunite, 5 - all chat complete. + const val varbitCaveEntrance = 378 // 6446 0 - 6 6441 - // if (player.questRepository.isComplete("The Tourist Trap")) { - // line(player,"---!!The Tourist Trap??/--", line++) - // } else { - // line(player,"!!The Tourist Trap??", line++) - // } + // Shadow Diamond + const val attributeShadowStage = "/save:quest:deserttreasure-shadowstage" + const val attributeDamisWarning = "quest:deserttreasure-damiswarning" + const val attributeDamisInstance = "quest:deserttreasure-damisinstance" + const val varbitRingOfVisibility = 393 // Set to 1 to show ladder and other cool stuff when wearing ring of visibility. - // if (player.questRepository.isComplete("The Temple of Ikov")) { - // line(player,"---!!The Temple of Ikov??/--", line++) - // } else { - // line(player,"!!The Temple of Ikov??", line++) - // } + // Desert Treasure End + const val attributeBloodDiamondInserted = "/save:quest:deserttreasure-blooddiamondinserted" + const val attributeSmokeDiamondInserted = "/save:quest:deserttreasure-smokediamondinserted" + const val attributeIceDiamondInserted = "/save:quest:deserttreasure-icediamondinserted" + const val attributeShadowDiamondInserted = "/save:quest:deserttreasure-shadowdiamondinserted" + const val varbitBloodObelisk = 390 + const val varbitSmokeObelisk = 387 + const val varbitIceObelisk = 389 + const val varbitShadowObelisk = 388 - // if (player.questRepository.isComplete("Priest In Peril")) { - // line(player,"---!!Priest In Peril??/--", line++) - // } else { - // line(player,"!!Priest In Peril??", line++) - // } + fun completedAllSubstages(player: Player): Boolean { + return getSubStage(player, attributeBloodStage) == 100 && + getSubStage(player, attributeSmokeStage) == 100 && + getSubStage(player, attributeIceStage) == 100 && + getSubStage(player, attributeShadowStage) == 100 + } - // if (player.questRepository.isComplete("Waterfall Quest")) { - // line(player,"---!!Waterfall Quest??/--", line++) - // } else { - // line(player,"!!Waterfall Quest??", line++) - // } + fun getSubStage(player: Player, attributeName: String): Int { + return getAttribute(player, attributeName, 0) + } - // if (player.questRepository.isComplete("Troll Stronghold")) { - // line(player,"---!!Troll Stronghold??/--", line++) - // } else { - // line(player,"!!Troll Stronghold??", line++) - // } + fun setSubStage(player: Player, attributeName: String, value: Int) { + return setAttribute(player, attributeName, value) + } + + fun hasRequirements(player: Player): Boolean { + return arrayOf( + hasLevelStat(player, Skills.SLAYER, 10), + hasLevelStat(player, Skills.FIREMAKING, 50), + hasLevelStat(player, Skills.MAGIC, 50), + hasLevelStat(player, Skills.THIEVING, 53), + isQuestComplete(player, Quests.THE_DIG_SITE), + isQuestComplete(player, Quests.THE_TOURIST_TRAP), + isQuestComplete(player, Quests.TEMPLE_OF_IKOV), + isQuestComplete(player, Quests.PRIEST_IN_PERIL), + isQuestComplete(player, Quests.WATERFALL_QUEST), + isQuestComplete(player, Quests.TROLL_STRONGHOLD), + ).all { it } + } + } + + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player, questName) > 0 + + if(!started){ + line(player,"I can start this quest by speaking to !!The Archaeologist??", line++) + line(player,"who is exploring the !!Bedabin Camp?? South West of the", line++) + line(player,"!!Shantay Pass??.", line++) + line(player,"To complete this quest I will need:", line++) + line(player, "Level 10 Slayer", line++, hasLevelStat(player, Skills.SLAYER, 10)) + line(player, "Level 50 Firemaking", line++, hasLevelStat(player, Skills.FIREMAKING, 50)) + line(player, "Level 50 Magic", line++, hasLevelStat(player, Skills.MAGIC, 50)) + line(player, "Level 53 Thieving", line++, hasLevelStat(player, Skills.THIEVING, 53)) + line(player,"I must have completed the following quests:", line++) // After - I have completed all of the required quests: + line(player, "The Digsite Quest", line++, isQuestComplete(player, Quests.THE_DIG_SITE)) + line(player, "The Tourist Trap", line++, isQuestComplete(player, Quests.THE_TOURIST_TRAP)) + line(player, "The Temple of Ikov", line++, isQuestComplete(player, Quests.TEMPLE_OF_IKOV)) + line(player, "Priest In Peril", line++, isQuestComplete(player, Quests.PRIEST_IN_PERIL)) + line(player, "Waterfall Quest", line++, isQuestComplete(player, Quests.WATERFALL_QUEST)) + line(player, "Troll Stronghold", line++, isQuestComplete(player, Quests.TROLL_STRONGHOLD)) + } else { + + if (stage >= 2) { + line(player, "I took some etchings of a stone tablet discovered by the", line++, true) + line(player, "archaeologist in the desert to Terry Balando at the", line++, true) + line(player, "Varrock digsite.", line++, true) + } else if (stage >= 1) { + line(player, "The !!archaeologist?? has given me some !!etchings from a??", line++, false) + line(player, "!!stone tablet?? that he discovered in the desert somewhere,", line++, false) + line(player, "and asked me to take it to an archaeological expert called", line++, false) + line(player, "!!Terry Balando?? at the Varrock !!digsite??.", line++, false) + } + + if (stage >= 4) { + line(player, "He made a rough translation, which I returned to the", line++, true) + line(player, "archaeologist.", line++, true) + } else if (stage == 3) { + line(player, "Terry Balando made some quick !!translation notes?? of the", line++, false) + line(player, "tablet and asked me to return them to the !!archaeologist?? in", line++, false) + line(player, "the !!Bedabin Camp??.", line++, false) + } else if (stage == 2) { + line(player, "I should get the !!translation notes?? from !!Terry Balando??", line++, false) + } + + if(stage >= 5) { + line(player, "The archaeologist I met in the desert seemed to think that", line++, true) + line(player, "there was some hidden treasure in the desert somewhere,", line++, true) + line(player, "I agreed to help him find it in return for a fifty percent", line++, true) + line(player, "share of whatever we found.", line++, true) + } else if (stage == 4) { + line(player, "I should find out what the !!archaeologist?? has to say about", line++, false) + line(player, "the !!translation notes??.", line++, false) + } + + if (stage >= 6) { + line(player, "I headed South and found a Bandit Camp.", line++, true) + } else if (stage >= 5) { + line(player, "I should head South to the !!Bandit Camp?? and try to find out", line++, false) + line(player, "more about this !!treasure??.", line++, false) + } + + if (stage >= 7) { + line(player, "I asked around the Bandit Camp and discovered someone", line++, true) + line(player, "who was willing to help me find the diamonds, by using a", line++, true) + line(player, "magic spell and some scrying glasses.", line++, true) + } else if (stage >= 6) { + line(player, "After some searching, the barman let slip some", line++, true) + line(player, "information about the 'Four Diamonds of Azzanadra'.", line++, true) + line(player, "I should ask around the !!Bandit Camp?? and see if anyone", line++, false) + line(player, "else has any information about the !!Four Diamonds of??", line++, false) + line(player, "!!Azzanadra??", line++, false) + } + + if (stage >= 10 || (stage >= 9 && completedAllSubstages(player))) { + // This disappears after you find all the diamonds. + } else if (stage >= 8) { + line(player, "I brought Eblis the ingredients so that he could cast the", line++, true) + line(player, "spell to see the places touched by the magic of the", line++, true) + line(player, "diamonds.", line++, true) + } else if (stage >= 7) { + // Crosses out gradually as you SUBMIT them. + line(player, "To make the scrying glasses I need to bring the following", line++, false) + // Crosses out with "I have brought him all xxx(6 Steel bars)" + line(player, "items to Eblis:", line++, false) + line(player, "!!12 Magic logs??", line++, false) + line(player, "!!6 Steel bars??", line++, false) + line(player, "!!6 Molten glass??", line++, false) + line(player, "To cast the spell I will need to bring Eblis:", line++, false) + // Crosses out with "I have brought him xxx(some bones)" + line(player, "!!Some bones??", line++, false) + line(player, "!!Some ash??", line++, false) + line(player, "!!Some charcoal??", line++, false) + line(player, "!!A blood rune??", line++, false) + } + + if (stage >= 10 || (stage >= 9 && completedAllSubstages(player))) { + // This disappears after you find all the diamonds. + } else if (stage >= 9 && !completedAllSubstages(player)) { + // This was supposed to disappear... youtu.be/J4cQMY66MI4 is old but disagrees + line(player, "I headed East into the desert and used the scrying", line++, true) + line(player, "glasses set up for me there by Eblis to try and find the", line++, true) + line(player, "Four Diamonds of Azzanadra.", line++, true) + line++ + } else if (stage >= 8) { + line(player, "I should head !!East into the desert?? and meet Eblis where he", line++, false) + line(player, "has set up the scrying glasses, and use them to try and", line++, false) + line(player, "track down the !!Four Diamonds of Azzanadra??.", line++, false) + line++ + } - // line(player,"", line++) - //} - // } - //} + // The huge one with sub quests. + if (stage >= 9 && completedAllSubstages(player)) { + line(player, "I found all four diamonds using this spell.", line++, true) + } else if (stage == 9) { + line++ + // DIAMOND OF BLOOD (DESSOUS) + // Dessous returns to his grave, bored of toying with you. // https://youtu.be/7CvfS7pypso + if (getSubStage(player, attributeBloodStage) == 100) { + line(player, "I defeated a vampire named Dessous to claim the Diamond", line++, true) + line(player, "of Blood.", line++, true) + } else if (getSubStage(player, attributeBloodStage) >= 1) { + // ZSOCwWEwimM 4:25 helped the first line. + line(player, "I discovered that the location of the Diamond of Blood was", line++, true) + line(player, "somewhere in Morytania, and in the possession of a", line++, true) + line(player, "vampire warrior named Dessous.", line++, true) - // override fun finish(player: Player) { - // var ln = 10 - // super.finish(player) - // player.packetDispatch.sendString("You have completed Desert Treasure!", 277, 4) - // player.packetDispatch.sendItemZoomOnInterface(1891, 240, 277, 5) -// - // drawReward(player,"3 Quest Points", ln++) - // drawReward(player,"20,000 Magic XP", ln++) - // drawReward(player,"Ability to use", ln++) - // drawReward(player,"Ancient Magicks", ln) + if (getSubStage(player, attributeBloodStage) >= 3) { + line(player, "I don't fully trust Malek, but he has agreed to help me kill", line++, true) + line(player, "Dessous.", line++, true) - // player.skills.addExperience(Skills.MAGIC, 20000.0) + line(player, "I made a special blessed pot, filled with blood, garlic and", line++, true) + line(player, "spices, which I used to lure Dessous from his tomb.", line++, true) + line(player, "I managed to defeat the vampire warrior Dessous, but", line++, true) + line(player, "there was no sign of the Diamond of Blood anywhere.", line++, true) + line(player, "I should find out what game !!Malek?? has been playing with", line++, false) + line(player, "me, and where I can actually find the !!Diamond of Blood??.", line++, false) + } else if (getSubStage(player, attributeBloodStage) >= 2) { + line(player, "I don't fully trust Malek, but he has agreed to help me kill", line++, true) + line(player, "Dessous.", line++, true) - // } + // None of these lines cross out when you do it. So it remains like this. + line(player, "Apparently I can find an old !!assistant of Count Draynor?? in", line++, false) + line(player, "the !!sewers of Draynor Village??, who will be able to help me", line++, false) + line(player, "make a !!sacrificial pot??", line++, false) + line(player, "I then need to take that !!sacrificial pot?? to !!Entrana?? and get", line++, false) + line(player, "it blessed by the !!head priest??", line++, false) + line(player, "When I have done that, I should return to !!Malak??, and he will", line++, false) + line(player, "provide me with some !!fresh blood??", line++, false) + line(player, "I then need to add !!garlic?? and !!spices?? to the pot in order to", line++, false) + line(player, "lure Dessous from his tomb.", line++, false) + line(player, "When I have done all of this, I must !!kill Dessous!??", line++, false) + } else if (getSubStage(player, attributeBloodStage) >= 1) { + line(player, "I should speak to !!Malek?? again and find out how exactly I", line++, false) + line(player, "can kill !!Dessous??.", line++, false) // This doesn't stay + } + } else if (getSubStage(player, attributeBloodStage) == 0) { + line(player, "I can use the !!scrying glasses?? to help find the", line++, false) + line(player, "!!Diamond of Blood??.", line++, false) + } - // override fun newInstance(`object`: Any?): Quest { - // return this - // } -//} \ No newline at end of file + line++ + // DIAMOND OF SMOKE (FAREED) + // Fareed has lost interest in you, and returned to his flames. + if (getSubStage(player, attributeSmokeStage) == 100) { + line(player, "I defeated a fire warrior, and now have the Diamond of", line++, true) + line(player, "Smoke.", line++, true) + } else if (getSubStage(player, attributeSmokeStage) >= 1) { + line(player, "I entered a smokey well and lit up the path. I found a", line++, true) // Derived. + line(player, "key in a chest.", line++, true) // Derived. + line(player, "I should find out what the !!key?? unlocks.", line++, false) // Derived. + } else if (getSubStage(player, attributeSmokeStage) == 0) { + // This doesn't change to stage 1 even when you are lighting the fires... + line(player, "I can use the !!scrying glasses?? to help find the", line++, false) + line(player, "!!Diamond of Smoke??.", line++, false) + } + + line++ + // DIAMOND OF ICE (KAMIL) + // Kamil vanishes on an icy wind... + if (getSubStage(player, attributeIceStage) == 100) { + line(player, "I defeated a warrior named Kamil, and now have the", line++, true) + line(player, "Diamond of Ice.", line++, true) + } else if (getSubStage(player, attributeIceStage) >= 1) { + // https://www.youtube.com/watch?v=F5F6Ds-T1P8 28:52 + line(player, "I met a crying ice troll child to the North of Trollheim.", line++, true) + if (getSubStage(player, attributeIceStage) >= 3) { + line(player, "I managed to cheer him up slightly with a sweet treat.", line++, true) + line(player, "After speaking with him, I discovered that his parents had", line++, true) + line(player, "been hurt by a 'bad man' who had the Diamond of Ice, and I", line++, true) + line(player, "agreed to help him rescue them.", line++, true) + line(player, "While heading through the icy area, I was attacked by an", line++, true) + line(player, "ice warrior named Kamil, and managed to defeat him.", line++, true) + line(player, "Was this the 'bad man' the troll child has spoken of?", line++, true) + line(player, "I should head further into the icy area to try and find", line++, false) + line(player, "them.", line++, false) + } else if (getSubStage(player, attributeIceStage) >= 2) { + line(player, "I managed to cheer him up slightly with a sweet treat.", line++, true) + line(player, "After speaking with him, I discovered that his parents had", line++, true) + line(player, "been hurt by a 'bad man' who had the Diamond of Ice, and I", line++, true) + line(player, "agreed to help him rescue them.", line++, true) + line(player, "I should head further into the icy area to try and find", line++, false) + line(player, "them.", line++, false) + } else if (getSubStage(player, attributeIceStage) >= 1) { + line(player, "I should cheer him up with something sweet.", line++, false) // Derived + } + } else if (getSubStage(player, attributeIceStage) == 0) { + line(player, "I can use the !!scrying glasses?? to help find the", line++, false) + line(player, "!!Diamond of Ice??.", line++, false) + } + + line++ + // DIAMOND OF SHADOW (DAMIS) + // Damis has vanished once more into the shadows... + if (getSubStage(player, attributeShadowStage) == 100) { + line(player, "I defeated a warrior named Damis, and now have the", line++, true) + line(player, "Diamond of Shadow.", line++, true) + } else if (getSubStage(player, attributeShadowStage) >= 1) { + line(player, "A travelling merchant named Rasolo had some information", line++, true) + line(player, "about the Diamond of Shadow.", line++, true) + line(player, "Apparently it was owned by an invisible warrior, who I", line++, true) + line(player, "needed a special ring to see.", line++, true) + line(player, "Rasolo owned such a ring, but would only trade it in return", line++, true) + line(player, "for a gilded cross stolen from him by a bandit named.", line++, true) + line(player, "Laheeb.", line++, true) + if (getSubStage(player, attributeShadowStage) >= 3) { + line(player, "I found Laheeb's treasure chest, and managed to bypass", line++, true) + line(player, "the traps on it to take the gilded cross, which I returned to", line++, true) + line(player, "Rasolo.", line++, true) + line(player, "In return, he gave me the Ring of Visibility.", line++, true) + line(player, "I should put the !!Ring of Visibility?? on and try and find the", line++, false) + line(player, "hidden home of !!Damis?? - Rasolo suggested it was very", line++, false) + line(player, "close by to where he is...", line++, false) + } else if (getSubStage(player, attributeShadowStage) >= 2) { + line(player, "I found Laheeb's treasure chest, and managed to bypass", line++, true) + line(player, "the traps on it to take the gilded cross.", line++, true) + line(player, "I need to return the !!gilded cross?? to !!Rasolo??.", line++, false) // Derived + } else if (getSubStage(player, attributeShadowStage) >= 1) { + line(player, "I need to find !!Laheeb's loot?? and retrieve the stolen !!gilded??", line++, false) + line(player, "!!cross??.", line++, false) + } + } else if (getSubStage(player, attributeShadowStage) == 0) { + line(player, "I can use the !!scrying glasses?? to help find the", line++, false) + line(player, "!!Diamond of Shadow??.", line++, false) + } + } + + // If you hold a diamond too long a stranger will try to kill you. + // https://oldschool.runescape.wiki/w/Transcript:Stranger + // After defeating the stranger + // player(THINKING, "I wonder what that was all about?") + + // After all 4 diamonds + // Player dialogue("I should make sure I have all four diamonds with me", "before speaking to Eblis again.") + + if (stage >= 10) { + // This disappears after you place all the diamonds. + } else if (stage >= 9 && completedAllSubstages(player)) { + line(player, "Now that I have recovered all of the !!Diamonds of??", line++, false) + line(player, "!!Azzanadra?? I should take them all to !!Eblis?? and find out what.", line++, false) + line(player, "is so special about them.", line++, false) + // This is the current message even AFTER you speak to Eblis... baQ6oJOk7Gc + } + + if (stage >= 11) { + // This disappears at the end of this quest. + } else if (stage >= 10) { + line(player, "I should explore the !!pyramid?? and see what !!treasure?? awaits", line++, false) + line(player, "me!", line++, false) + } + + if (stage >= 100) { + line(player, "At the heart of the pyramid I found a strange being, who", line++, true) + line(player, "gave me some powerful new magic spells.", line++, true) + line(player, "I can switch between my old spells and my new spells any", line++, true) + line(player, "time by using the altar there, and can avoid the traps by", line++, true) + line(player, "using the secret passage.", line++, true) + line++ + line++ + line(player,"QUEST COMPLETE!", line) + } + } + } + + override fun reset(player: Player) { + setVarbit(player, varbitChildReunite, 0, true) + + removeAttribute(player, attributeBoughtBeer) + removeAttribute(player, attributeCountMagicLogs) + removeAttribute(player, attributeCountSteelBars) + removeAttribute(player, attributeCountMoltenGlass) + removeAttribute(player, attributeCountBones) + removeAttribute(player, attributeCountAshes) + removeAttribute(player, attributeCountCharcoal) + removeAttribute(player, attributeCountBloodRune) + setVarbit(player, varbitMirrors, 0, true) + + removeAttribute(player, attributeBloodStage) + removeAttribute(player, attributeDessousInstance) + + removeAttribute(player, attributeSmokeStage) + removeAttribute(player, attributeFareedInstance) + removeAttribute(player, attributeUnlockedGate) + setVarbit(player, varbitStandingTorchNorthEast, 0, true) + setVarbit(player, varbitStandingTorchSouthEast, 0, true) + setVarbit(player, varbitStandingTorchSouthWest, 0, true) + setVarbit(player, varbitStandingTorchNorthWest, 0, true) + + removeAttribute(player, attributeIceStage) + removeAttribute(player, attributeKamilInstance) + removeAttribute(player, attributeTrollKillCount) + setVarbit(player, varbitFrozenFather, 0, true) // 0-frozen 1-defrosted + setVarbit(player, varbitFrozenMother, 0, true) // 0-frozen 1-defrosted + setVarbit(player, varbitChildReunite, 0, true) // 0-frozen 4-reunited 5-reunited 6-varbitfails/ends (This varbit seems to manage ice stages...) + setVarbit(player, varbitCaveEntrance, 0, true) // 6446 0 - 6 6441 + + removeAttribute(player, attributeShadowStage) + removeAttribute(player, attributeDamisInstance) + removeAttribute(player, attributeDamisWarning) + setVarbit(player, varbitRingOfVisibility, 0, true) // Set to 1 to show ladder when wearing ring of visibility. + + removeAttribute(player, attributeBloodDiamondInserted) + removeAttribute(player, attributeSmokeDiamondInserted) + removeAttribute(player, attributeIceDiamondInserted) + removeAttribute(player, attributeShadowDiamondInserted) + setVarbit(player, varbitBloodObelisk, 0, true) + setVarbit(player, varbitSmokeObelisk, 0, true) + setVarbit(player, varbitIceObelisk, 0, true) + setVarbit(player, varbitShadowObelisk, 0, true) + } + + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed the Desert Treasure Quest!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.ANCIENT_STAFF_4675, 240, 277, 5) + + drawReward(player,"3 Quest Points", ln++) + drawReward(player,"20,000 Magic XP", ln++) + drawReward(player,"Ancient Magicks", ln) + + player.skills.addExperience(Skills.MAGIC, 20000.0) + } + + override fun setStage(player: Player, stage: Int) { + super.setStage(player, stage) + this.updateVarps(player) + } + + override fun updateVarps(player: Player) { + + // Ice: Cave Entrance Varbit + setVarbit(player, varbitCaveEntrance, getAttribute(player,attributeTrollKillCount, 0)) + + // Shadow: Ring of Visibility Ladder Varbit + if (inEquipment(player, Items.RING_OF_VISIBILITY_4657)) { + setVarbit(player, varbitRingOfVisibility, 1) + } else { + setVarbit(player, varbitRingOfVisibility, 0) + } + + // Obelisks Varbits + if (getAttribute(player, attributeBloodDiamondInserted, 0) == 1) { + setVarbit(player, varbitBloodObelisk, 1) + } else { + setVarbit(player, varbitBloodObelisk, 0) + } + + if (getAttribute(player, attributeSmokeDiamondInserted, 0) == 1) { + setVarbit(player, varbitSmokeObelisk, 1) + } else { + setVarbit(player, varbitSmokeObelisk, 0) + } + + if (getAttribute(player, attributeIceDiamondInserted, 0) == 1) { + setVarbit(player, varbitIceObelisk, 1) + } else { + setVarbit(player, varbitIceObelisk, 0) + } + + if (getAttribute(player, attributeShadowDiamondInserted, 0) == 1) { + setVarbit(player, varbitShadowObelisk, 1) + } else { + setVarbit(player, varbitShadowObelisk, 0) + } + + // Special Varbit for Ice Stage + if (getAttribute(player, attributeIceStage, 0) > 5) { + setVarbit(player, varbitChildReunite, 5) + } else { + setVarbit(player, varbitChildReunite, 0) + } + + // Stage Varbits + if(getQuestStage(player, questName) == 0) { + setVarbit(player, varbitDesertTreasure, 0, true) + setVarbit(player, varbitMirrors, 0, true) + } + if(getQuestStage(player, questName) in 1..7) { + setVarbit(player, varbitDesertTreasure, 1, true) + setVarbit(player, varbitMirrors, 0, true) + } + if(getQuestStage(player, questName) in 8..9) { + setVarbit(player, varbitDesertTreasure, 10, true) + setVarbit(player, varbitMirrors, 1, true) + } + if(getQuestStage(player, questName) == 10) { + setVarbit(player, varbitDesertTreasure, 13, true) + setVarbit(player, varbitMirrors, 1, true) + } + if(getQuestStage(player, questName) >= 100) { + setVarbit(player, varbitDesertTreasure, 15, true) + setVarbit(player, varbitMirrors, 1, true) + } + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasureListeners.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasureListeners.kt new file mode 100644 index 000000000..3115efd3f --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DesertTreasureListeners.kt @@ -0,0 +1,464 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.activity.Cutscene +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import org.rs09.consts.Items +import org.rs09.consts.Scenery + +class DesertTreasureListeners : InteractionListener { + + companion object { + fun allDiamondsInserted(player: Player): Boolean{ + return getAttribute(player, DesertTreasure.attributeBloodDiamondInserted, 0) == 1 && + getAttribute(player, DesertTreasure.attributeSmokeDiamondInserted, 0) == 1 && + getAttribute(player, DesertTreasure.attributeIceDiamondInserted, 0) == 1 && + getAttribute(player, DesertTreasure.attributeShadowDiamondInserted, 0) == 1 + } + } + var temp = 6517 + + override fun defineListeners() { + + // THE MIRRORS + on(Scenery.MYSTICAL_MIRROR_6423, SCENERY, "look-into") { player, node -> + SouthMirrorLookCutscene(player).start() + return@on true + } + on(Scenery.MYSTICAL_MIRROR_6425, SCENERY, "look-into") { player, node -> + SouthWestMirrorLookCutscene(player).start() + return@on true + } + on(Scenery.MYSTICAL_MIRROR_6427, SCENERY, "look-into") { player, node -> + NorthWestMirrorLookCutscene(player).start() + return@on true + } + on(Scenery.MYSTICAL_MIRROR_6429, SCENERY, "look-into") { player, node -> + NorthMirrorLookCutscene(player).start() + return@on true + } + on(Scenery.MYSTICAL_MIRROR_6431, SCENERY, "look-into") { player, node -> + NorthEastMirrorLookCutscene(player).start() + return@on true + } + on(Scenery.MYSTICAL_MIRROR_6433, SCENERY, "look-into") { player, node -> + SouthEastMirrorLookCutscene(player).start() + return@on true + } + + + // THE OBELISKS + onUseWith(IntType.SCENERY, intArrayOf(Items.ICE_DIAMOND_4671, Items.SMOKE_DIAMOND_4672, Items.SHADOW_DIAMOND_4673), Scenery.OBELISK_6483) { player, used, with -> + sendMessage(player, "That doesn't appear to be the correct diamond...") + return@onUseWith true + } + onUseWith(IntType.SCENERY, Items.BLOOD_DIAMOND_4670, Scenery.OBELISK_6483) { player, used, with -> + if (getDynLevel(player, Skills.MAGIC) > 50) { + if (removeItem(player, used)) { + sendMessage(player, "The diamond is absorbed into the pillar.") + setVarbit(player, DesertTreasure.varbitBloodObelisk, 1) + setAttribute(player, DesertTreasure.attributeBloodDiamondInserted, 1) + if (allDiamondsInserted(player)) { + sendMessage(player, "The force preventing access to the Pyramid has now vanished.") + if (getQuestStage(player, DesertTreasure.questName) == 9) { + setQuestStage(player, DesertTreasure.questName, 10) + } + } + } + } else { + sendMessage(player, "You are not a powerful enough mage to breach the protective aura.") + sendMessage(player, "You need a magic level of at least 50 to enter the Pyramid.") + } + return@onUseWith true + } + onUseWith(IntType.SCENERY, intArrayOf(Items.BLOOD_DIAMOND_4670, Items.ICE_DIAMOND_4671, Items.SHADOW_DIAMOND_4673), Scenery.OBELISK_6486) { player, used, with -> + sendMessage(player, "That doesn't appear to be the correct diamond...") + return@onUseWith true + } + onUseWith(IntType.SCENERY, Items.SMOKE_DIAMOND_4672, Scenery.OBELISK_6486) { player, used, with -> + if (getDynLevel(player, Skills.MAGIC) > 50) { + if (removeItem(player, used)) { + sendMessage(player, "The diamond is absorbed into the pillar.") + setVarbit(player, DesertTreasure.varbitSmokeObelisk, 1) + setAttribute(player, DesertTreasure.attributeSmokeDiamondInserted, 1) + if (allDiamondsInserted(player)) { + sendMessage(player, "The force preventing access to the Pyramid has now vanished.") + if (getQuestStage(player, DesertTreasure.questName) == 9) { + setQuestStage(player, DesertTreasure.questName, 10) + } + } + } + } else { + sendMessage(player, "You are not a powerful enough mage to breach the protective aura.") + sendMessage(player, "You need a magic level of at least 50 to enter the Pyramid.") + } + return@onUseWith true + } + onUseWith(IntType.SCENERY, intArrayOf(Items.BLOOD_DIAMOND_4670, Items.SMOKE_DIAMOND_4672, Items.SHADOW_DIAMOND_4673), Scenery.OBELISK_6489) { player, used, with -> + sendMessage(player, "That doesn't appear to be the correct diamond...") + return@onUseWith true + } + onUseWith(IntType.SCENERY, Items.ICE_DIAMOND_4671, Scenery.OBELISK_6489) { player, used, with -> + if (getDynLevel(player, Skills.MAGIC) > 50) { + if (removeItem(player, used)) { + sendMessage(player, "The diamond is absorbed into the pillar.") + setVarbit(player, DesertTreasure.varbitIceObelisk, 1) + setAttribute(player, DesertTreasure.attributeIceDiamondInserted, 1) + if (allDiamondsInserted(player)) { + sendMessage(player, "The force preventing access to the Pyramid has now vanished.") + if (getQuestStage(player, DesertTreasure.questName) == 9) { + setQuestStage(player, DesertTreasure.questName, 10) + } + } + } + } else { + sendMessage(player, "You are not a powerful enough mage to breach the protective aura.") + sendMessage(player, "You need a magic level of at least 50 to enter the Pyramid.") + } + return@onUseWith true + } + onUseWith(IntType.SCENERY, intArrayOf(Items.BLOOD_DIAMOND_4670, Items.ICE_DIAMOND_4671, Items.SMOKE_DIAMOND_4672), Scenery.OBELISK_6492) { player, used, with -> + sendMessage(player, "That doesn't appear to be the correct diamond...") + return@onUseWith true + } + onUseWith(IntType.SCENERY, Items.SHADOW_DIAMOND_4673, Scenery.OBELISK_6492) { player, used, with -> + if (getDynLevel(player, Skills.MAGIC) > 50) { + if (removeItem(player, used)) { + sendMessage(player, "The diamond is absorbed into the pillar.") + setVarbit(player, DesertTreasure.varbitShadowObelisk, 1) + setAttribute(player, DesertTreasure.attributeShadowDiamondInserted, 1) + if (allDiamondsInserted(player)) { + sendMessage(player, "The force preventing access to the Pyramid has now vanished.") + if (getQuestStage(player, DesertTreasure.questName) == 9) { + setQuestStage(player, DesertTreasure.questName, 10) + } + } + } + } else { + sendMessage(player, "You are not a powerful enough mage to breach the protective aura.") + sendMessage(player, "You need a magic level of at least 50 to enter the Pyramid.") + } + return@onUseWith true + } + + // THE DOOR + on(intArrayOf(Scenery.PYRAMID_ENTRANCE_6545, Scenery.PYRAMID_ENTRANCE_6547), SCENERY, "open") { player, node -> + if (allDiamondsInserted(player)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendMessage(player, "A mystical power has sealed this door...") + } + return@on true + } + + // THE LADDERS + on(Scenery.LADDER_6497, SCENERY, "climb-down") { player, node -> + teleport(player, Location(2913, 4954, 3)) + return@on true + } + on(Scenery.LADDER_6504, SCENERY, "climb-up") { player, node -> + teleport(player, Location(3233, 2898, 0)) + return@on true + } + + on(Scenery.LADDER_6498, SCENERY, "climb-down") { player, node -> + teleport(player, Location(2846, 4964, 2)) + return@on true + } + on(Scenery.LADDER_6503, SCENERY, "climb-up") { player, node -> + teleport(player, Location(2909, 4963, 3)) + return@on true + } + + on(Scenery.LADDER_6499, SCENERY, "climb-down") { player, node -> + teleport(player, Location(2782, 4972, 1)) + return@on true + } + on(Scenery.LADDER_6502, SCENERY, "climb-up") { player, node -> + teleport(player, Location(2845, 4973, 2)) + return@on true + } + + on(Scenery.LADDER_6500, SCENERY, "climb-down") { player, node -> + teleport(player, Location(3233, 9293, 0)) + return@on true + } + on(Scenery.LADDER_6501, SCENERY, "climb-up") { player, node -> + teleport(player, Location(2783, 4941, 1)) + return@on true + } + + on((6512..6517).toIntArray(), SCENERY, "search") { player, node -> + // Technically there is loot, but I'm lazy as hell. + sendMessage(player, "You don't find anything interesting.") + return@on true + } + + // After Quest + + // Backdoor + on(Scenery.TUNNEL_6481, SCENERY, "enter") { player, node -> + if (isQuestComplete(player, DesertTreasure.questName)){ + teleport(player, Location(3233, 9313, 0)) + } else { + sendMessage(player, "This passage does not seem to lead anywhere...") // https://youtu.be/uNkBucGaqac + } + return@on true + } + + // Portal, which only appears after DT + on(Scenery.PORTAL_6551, SCENERY, "use") { player, node -> + teleport(player, Location(3233, 2887, 0)) + return@on true + } + + } +} + + +// https://www.youtube.com/watch?v=yMwp78OI2y8 + +// Ice Troll +class NorthMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(11322) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 5, 27) + moveCamera(5, 27, 1000) + rotateCamera(6, 27, 1000) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} + +// Canifis +class NorthEastMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(13878) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 47, 31) + moveCamera(47, 31, 1000) + rotateCamera(43, 31, 1000) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} + +// Smoke Dungeon +class SouthEastMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(13102) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 36, 20) + moveCamera(36, 20, 1000) + rotateCamera(44, 20, 1000) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} + +// Pyramid +class SouthMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(12845) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 33, 41) + moveCamera(33, 41, 1000) + rotateCamera(33, 39, 990) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} + +// Bedabin +class SouthWestMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(12590) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 40, 39) + moveCamera(40, 39, 1200) + rotateCamera(10, 39, 1200) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} + +// Rasolo +class NorthWestMirrorLookCutscene(player: Player) : Cutscene(player) { + + override fun setup() { + setExit(player.location.transform(0, 0, 0)) + loadRegion(10037) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + fadeToBlack() + timedUpdate(4) + } + 1 -> { + teleport(player, 56, 40) + moveCamera(56, 40, 1400) + rotateCamera(56, 35, 1000) + timedUpdate(1) + } + 2 -> { + openInterface(player, 155) + closeOverlay() + timedUpdate(6) + } + 3-> { + closeInterface(player) + fadeToBlack() + timedUpdate(4) + } + 4-> { + end(false){ + fadeFromBlack() + // resetCamera() + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DessousBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DessousBehavior.kt new file mode 100644 index 000000000..5c521e6b6 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DessousBehavior.kt @@ -0,0 +1,142 @@ +package content.region.desert.quest.deserttreasure + +import content.region.kandarin.quest.templeofikov.TempleOfIkov +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.combat.* +import core.game.node.entity.combat.equipment.SwitchAttack +import core.game.node.entity.impl.Projectile +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.prayer.PrayerType +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +class DessousMeleeBehavior : NPCBehavior(NPCs.DESSOUS_1914, NPCs.DESSOUS_1915) { + + var clearTime = 0 + + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + if (attacker is Player) { + if (attacker == getAttribute(self, "target", null)) { + return true + } + sendMessage(attacker, "It's not after you...") + } + return false + } + + override fun tick(self: NPC): Boolean{ + // Dessous just continually hisses independently of projectile fires. + if (self.id == NPCs.DESSOUS_1915 && self.properties.combatPulse.isInCombat) { + animate(self, Animation(1914)) + } + // This is probably the prayer flicking nonsense. + val player: Player? = getAttribute(self, "target", null) + if (self.id == NPCs.DESSOUS_1914 && player != null && player.prayer.get(PrayerType.PROTECT_FROM_MELEE)) { + self.transform(NPCs.DESSOUS_1915) + Graphics.send(Graphics(86), self.location) + } else if (self.id == NPCs.DESSOUS_1915 && player != null && (player.prayer.get(PrayerType.PROTECT_FROM_MAGIC) || player.prayer.get(PrayerType.PROTECT_FROM_MISSILES))) { + self.transform(NPCs.DESSOUS_1914) + Graphics.send(Graphics(86), self.location) + } + if (clearTime++ > 800) { + self.transform(NPCs.DESSOUS_1914) + clearTime = 0 + if (player != null) { + removeAttribute(player, DesertTreasure.attributeDessousInstance) + sendMessage(player, "Dessous returns to his grave, bored of toying with you.") + } + poofClear(self) + } + return false + } + + override fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler): CombatSwingHandler { + if (self.id == NPCs.DESSOUS_1915) { + // 2 x 5HP (One Magic, One Ranged) + return CombatHandler() + } else { + // Fast melee attack 3 ticks up to 19HP + return original + } + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + // Teleport nearer, if too far. + if (victim is Player) { + if (victim.location.getDistance(self.location) >= 5) { + Graphics.send(Graphics(86), self.location) + self.properties.teleportLocation = victim.location + Graphics.send(Graphics(86), self.location) + } + } + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + val player = killer + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) == 2) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeBloodStage, 3) + } + removeAttribute(player, DesertTreasure.attributeDessousInstance) + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> player(FacialExpression.ANGRY, "Well that's Dessous dead, but where is the Diamond he", "was supposed to have?").also { stage++ } + 1 -> playerl(FacialExpression.ANGRY, "If Malak lied to me about it, he is going to pay!").also { + stage = END_DIALOGUE + } + } + } + }) + } + } + + /** Handler for ranged. */ + class CombatHandler : MultiSwingHandler( + SwitchAttack(CombatStyle.MAGIC.swingHandler, null), + SwitchAttack(CombatStyle.RANGE.swingHandler, null) + ) { + override fun swing(entity: Entity?, victim: Entity?, state: BattleState?): Int { + if (entity is NPC && victim is Player) { + val projectile = Projectile.create( + victim.location.transform(Location(intArrayOf(3, -3).random(),intArrayOf(3, -3).random())), + victim.location, + 350, + 0, + 0, + 0, + 60, + 0, + 255 + ) + // 2 x 5HP (One Magic, One Ranged) + state!!.estimatedHit = 5 + state.secondaryHit = 5 // I have no idea what I'm doing + queueScript(entity, 0, QueueStrength.STRONG) { stage: Int -> + when (stage) { + 0 -> { + sendChat(entity, "Hssssssssssss") + projectile.send() + return@queueScript delayScript(entity, entity.location.getDistance(victim.location).toInt()) + } + 1 -> { + return@queueScript stopExecuting(entity) + } + else -> return@queueScript stopExecuting(entity) + } + } + + } + return super.swing(entity, victim, state) + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfBloodListeners.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfBloodListeners.kt new file mode 100644 index 000000000..8105aebf7 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfBloodListeners.kt @@ -0,0 +1,134 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.world.map.Direction +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class DiamondOfBloodListeners : InteractionListener { + override fun defineListeners() { + + // Silver pot conversions + onUseWith(ITEM, Items.SILVER_POT_4660, Items.SPICE_2007) { player, used, with -> + sendMessage(player, "You add some spices to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.SILVER_POT_4664) + } + return@onUseWith true + } + onUseWith(ITEM, Items.SILVER_POT_4660, Items.GARLIC_POWDER_4668) { player, used, with -> + sendMessage(player, "You add some crushed garlic to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.SILVER_POT_4662) + } + return@onUseWith true + } + onUseWith(ITEM, Items.SILVER_POT_4662, Items.SPICE_2007) { player, used, with -> + sendMessage(player, "You add some spices to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.SILVER_POT_4666) + } + return@onUseWith true + } + onUseWith(ITEM, Items.SILVER_POT_4664, Items.GARLIC_POWDER_4668) { player, used, with -> + sendMessage(player, "You add some crushed garlic to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.SILVER_POT_4666) + } + return@onUseWith true + } + // Blessed pot conversions + onUseWith(ITEM, Items.BLESSED_POT_4661, Items.SPICE_2007) { player, used, with -> + sendMessage(player, "You add some spices to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.BLESSED_POT_4665) + } + return@onUseWith true + } + onUseWith(ITEM, Items.BLESSED_POT_4661, Items.GARLIC_POWDER_4668) { player, used, with -> + sendMessage(player, "You add some crushed garlic to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.BLESSED_POT_4663) + } + return@onUseWith true + } + onUseWith(ITEM, Items.BLESSED_POT_4663, Items.SPICE_2007) { player, used, with -> + sendMessage(player, "You add some spices to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.BLESSED_POT_4667) + } + return@onUseWith true + } + onUseWith(ITEM, Items.BLESSED_POT_4665, Items.GARLIC_POWDER_4668) { player, used, with -> + sendMessage(player, "You add some crushed garlic to the pot.") + if(removeItem(player, used) && removeItem(player, with)) { + addItemOrDrop(player, Items.BLESSED_POT_4667) + } + return@onUseWith true + } + + // You need to crush the garlic. + onUseWith(ITEM, intArrayOf(Items.SILVER_POT_4660, Items.BLESSED_POT_4661, Items.SILVER_POT_4662, Items.BLESSED_POT_4663, Items.SILVER_POT_4664, Items.BLESSED_POT_4665, Items.SILVER_POT_4666, Items.BLESSED_POT_4667 ), Items.GARLIC_1550) { player, used, with -> + sendMessage(player, "You need to crush the garlic before adding it to the pot.") + return@onUseWith true + } + + // Dessous jumps out. + onUseWith(SCENERY, Items.BLESSED_POT_4667, Scenery.VAMPIRE_TOMB_6437) { player, used, with -> + val prevNpc = getAttribute(player, DesertTreasure.attributeDessousInstance, null) + if (prevNpc != null) { + prevNpc.clear() + } + sendMessage(player, "You pour the blood from the pot onto the tomb.") + removeItem(player, used) + val scenery = with.asScenery() + // Swap to a splittable vampire tomb scenery. + replaceScenery(scenery, Scenery.VAMPIRE_TOMB_6438, Animation(1915).duration) + // Vampire Tomb breaks open. + animateScenery(player, scenery, 1915) + // 8 Bat projectiles + spawnProjectile(Location(3570, 3402), Location(3570, 3404), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3570, 3400), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3568, 3402), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3572, 3402), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3568, 3404), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3572, 3404), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3568, 3400), 350, 0, 0, 0, 60, 0) + spawnProjectile(Location(3570, 3402), Location(3572, 3400), 350, 0, 0, 0, 60, 0) + val npc = NPC(NPCs.DESSOUS_1914) + queueScript(player, 1, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + // Projectile gfx for Dessous to jump out. + spawnProjectile(Location(3570, 3402), Location(3570, 3405), 351, 0, 0, 0, 40, 0) + return@queueScript delayScript(player, 1) + } + 1 -> { + npc.isRespawn = false + npc.isWalks = false + npc.location = Location(3570, 3405, 0) + npc.direction = Direction.NORTH + setAttribute(player, DesertTreasure.attributeDessousInstance, npc) + setAttribute(npc, "target", player) + + npc.init() + npc.attack(player) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + + //sendGraphics(350, Location(3570, 3402)) + //sendGraphics(351, Location(3570, 3402)) + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfIceListeners.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfIceListeners.kt new file mode 100644 index 000000000..9ee2c5ba9 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfIceListeners.kt @@ -0,0 +1,168 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class DiamondOfIceListeners : InteractionListener { + override fun defineListeners() { + onUseWith(IntType.NPC, Items.CHOCOLATE_CAKE_1897, NPCs.BANDIT_1932 /* should be NPCs.TROLL_CHILD_1932 */) { player, used, with -> + if (removeItem(player, used)) { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 0) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeIceStage, 1) + } + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> player("Hey there little troll...", "Take this and dry those tears...").also { stage++ } + 1 -> npc(FacialExpression.OLD_NEARLY_CRYING, "(sniff)").also { + stage = END_DIALOGUE + } + } + } + }, with as NPC) + } + return@onUseWith true + } + + on(intArrayOf(Scenery.ICE_GATE_5043, Scenery.ICE_GATE_5044), SCENERY, "go-through") { player, node -> + + if ((getQuestStage(player, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) > 1) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + sendMessage(player, "You squeeze through the large icy bars of the gate.") + // Anim 3272 to squeeze through? + if(player.location.x > 2838) { + teleport(player, Location(2837, 3739, 0)) + } else { + teleport(player, Location(2839, 3739, 0)) + } + } else { + // j_SdwOX1JWg + sendDialogueLines(player, "The bars are frozen tightly shut and a sturdy layer of ice prevents", "you from slipping through.") + } + return@on true + } + + on(Scenery.CAVE_ENTRANCE_6441, SCENERY, "enter") { player, node -> + lock(player, 3) + animate(player, 2796) // Crawling + queueScript(player, 3, QueueStrength.SOFT) { + teleport(player, Location(2874, 3720, 0)) + return@queueScript stopExecuting(player) + } + return@on true + } + + on(Scenery.CAVE_ENTRANCE_6446, SCENERY, "enter") { player, node -> + sendMessage(player, "The entrance to the cave is covered in too much ice to get through.") + return@on true + } + + on(Scenery.CAVE_EXIT_6447, SCENERY, "enter") { player, node -> + lock(player, 3) + animate(player, 2796) // Crawling + queueScript(player, 3, QueueStrength.SOFT) { + teleport(player, Location(2867, 3719, 0)) + return@queueScript stopExecuting(player) + } + return@on true + } + + on(Scenery.ICE_LEDGE_6455, SCENERY, "use") { player, node -> + + if ((getQuestStage(player, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) >= 3) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + if (inEquipment(player, Items.SPIKED_BOOTS_3107)) { + teleport(player, Location(2838, 3803, 1)) + } else { + sendPlayerDialogue(player, "I don't think I'll make much headway along that icy slope without some spiked boots...") + } + } else { + sendMessage(player, "You have not defeated Kamil yet.") + } + return@on true + } + + on(intArrayOf(Scenery.ICE_GATE_6461, Scenery.ICE_GATE_6462), SCENERY, "go-through") { player, node -> + + teleport(player, Location(2852, 3810, 2)) + return@on true + } + + // This is 1943 as base + on(NPCs.ICE_BLOCK_1944, NPC, "talk-to") { player, node -> + sendDialogueLines(player, "There is a thick layer of ice covering this troll.", "You will have to find some way of shattering it.") + return@on true + } + on(NPCs.ICE_BLOCK_1944, NPC, "smash-ice") { player, node -> + player.attack(node) + return@on true + } + + // This is 1945 as base + on(NPCs.ICE_BLOCK_1946, NPC, "talk-to") { player, node -> + sendDialogueLines(player, "There is a thick layer of ice covering this troll.", "You will have to find some way of shattering it.") + return@on true + } + on(NPCs.ICE_BLOCK_1946, NPC, "smash-ice") { player, node -> + player.attack(node) + return@on true + } + } +} + +/** This is while you are walking up the ice path. **/ +class ComicalTrippingIceArea : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf( + ZoneBorders(2815, 3775, 2880, 3839, 1), + ZoneBorders(2815, 3775, 2880, 3839, 2) + ) + } + + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + if ((1..10).random() == 1) { + lock(entity, 2) + stopWalk(entity) + animate(entity, 767) + } + } + } +} + +class IceAreaAttack : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders(2850, 3750, 2880, 3770)) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player && + getQuestStage(entity, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(entity, DesertTreasure.attributeIceStage) == 2 && + getAttribute(entity, DesertTreasure.attributeKamilInstance, null) == null + ) { + sendMessage(entity, "You can feel an evil presence nearby...") + val npc = NPC.create(NPCs.KAMIL_1913, Location(2857, 3754, 0)) + setAttribute(entity, DesertTreasure.attributeKamilInstance, npc) + setAttribute(npc, "target", entity) + npc.isRespawn = false + npc.init() + npc.attack(entity) + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfShadowListeners.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfShadowListeners.kt new file mode 100644 index 000000000..615a9b22c --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfShadowListeners.kt @@ -0,0 +1,265 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.item.GroundItemManager +import core.game.node.item.Item +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.tools.END_DIALOGUE +import core.tools.RandomFunction +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class DiamondOfShadowListeners : InteractionListener { + + companion object { + + fun roll(player: Player): Boolean { + + val chance = RandomFunction.randomDouble(1.0, 100.0) + val successChance = RandomFunction.getSkillSuccessChance(52.0, 128.0, getDynLevel(player, Skills.THIEVING)) + + return chance < successChance + } + + fun pickAttempt(player: Player, picklockItem: Item?) { + queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + sendMessage(player, "You attempt to pick the first lock...") + return@queueScript delayScript(player, 1) + } + + 1 -> { + if (roll(player)) { + sendMessage(player, "...You successfully picked the first lock!") + return@queueScript delayScript(player, 1) + } else { + if(picklockItem != null) { + removeItem(player, picklockItem) + } else { + removeItem(player, Items.LOCKPICK_1523) + } + sendMessage(player, "...and fail. The locking mechanism has reset itself.") + sendMessage(player, "Your lock pick snapped while attempting to pick the lock.") + impact(player, 3) + applyPoison(player, player, 6) + return@queueScript stopExecuting(player) + } + } + + 2 -> { + sendMessage(player, "You attempt to pick the second lock...") + return@queueScript delayScript(player, 1) + } + + 3 -> { + if (roll(player)) { + sendMessage(player, "...You successfully picked the second lock!") + return@queueScript delayScript(player, 1) + } else { + if(picklockItem != null) { + removeItem(player, picklockItem) + } else { + removeItem(player, Items.LOCKPICK_1523) + } + sendMessage(player, "...and fail. The locking mechanism has reset itself.") + sendMessage(player, "Your lock pick snapped while attempting to pick the lock.") + impact(player, 3) + applyPoison(player, player, 6) + return@queueScript stopExecuting(player) + } + } + + 4 -> { + sendMessage(player, "You attempt to pick the final lock...") + return@queueScript delayScript(player, 1) + } + + 5 -> { + if (roll(player)) { + sendMessage(player, "You managed to pick the final lock.") + return@queueScript delayScript(player, 1) + } else { + if(picklockItem != null) { + removeItem(player, picklockItem) + } else { + removeItem(player, Items.LOCKPICK_1523) + } + sendMessage(player, "...and fail. The locking mechanism has reset itself.") + sendMessage(player, "Your lock pick snapped while attempting to pick the lock.") + impact(player, 3) + applyPoison(player, player, 6) + return@queueScript stopExecuting(player) + } + } + + 6 -> { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 1) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeShadowStage, 2) + } + return@queueScript stopExecuting(player) + } + + else -> return@queueScript stopExecuting(player) + } + } + } + } + + override fun defineListeners() { + + // Hidden entrance to the shadow dungeon. + on(Scenery.LADDER_6561, SCENERY, "climb-down") { player, node -> + teleport(player, Location(2630, 5072)) + return@on true + } + + /** This will open up a lot of other places. Maybe have this in a general file? */ + onEquip(Items.RING_OF_VISIBILITY_4657) { player, _ -> + + if((DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) >= 3 && + getQuestStage(player, DesertTreasure.questName) >= 9) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + + setVarbit(player, DesertTreasure.varbitRingOfVisibility, 1) + return@onEquip true + } + sendMessage(player, "You need to complete part of Desert Treasure to equip this.") + return@onEquip false + } + + onUnequip(Items.RING_OF_VISIBILITY_4657) { player, _ -> + setVarbit(player, DesertTreasure.varbitRingOfVisibility, 0) + return@onUnequip true + } + + + + on(Scenery.SECURE_CHEST_6448, SCENERY, "open") { player, node -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 1) { + if (inInventory(player, Items.LOCKPICK_1523)) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + START_DIALOGUE -> dialogue("Your skill as a thief allows you to see some kind of elaborate booby", "trapped locking mechanism on this chest.").also { stage++ } + 1 -> showTopics( + Topic(FacialExpression.NEUTRAL, "Yes", 2, true), + Topic(FacialExpression.NEUTRAL, "No", END_DIALOGUE, true), + title = "Try to open the chest?" + ) + 2 -> end().also { + if (inInventory(player, Items.LOCKPICK_1523)) { + pickAttempt(player, null) + } else { + sendMessage(player, "You need a lockpick in order to attempt this.") + } + } + } + } + }) + } else { + sendMessage(player, "You need a lockpick in order to attempt this.") + } + } else if ((DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) >= 2 && + getQuestStage(player, DesertTreasure.questName) >= 9) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + if (inInventory(player, Items.GILDED_CROSS_4674)) { + sendMessage(player, "The chest is empty.") + } else { + replaceScenery(node as core.game.node.scenery.Scenery, 6449, 2) + sendMessage(player, "Inside the chest, hidden under some rags, you find a Gilded Cross.") + addItemOrDrop(player, Items.GILDED_CROSS_4674) + } + } else { + sendPlayerDialogue(player, "These bandits are hostile enough without me trying to rob them!") + } + return@on true + } + + onUseWith(SCENERY, Items.LOCKPICK_1523, Scenery.SECURE_CHEST_6448) { player, used, with -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 1) { + pickAttempt(player, used as Item) + } else if((DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) >= 2 && + getQuestStage(player, DesertTreasure.questName) >= 9) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + sendMessage(player, "The chest is unlocked.") + } else { + sendPlayerDialogue(player, "These bandits are hostile enough without me trying to rob them!") + } + return@onUseWith true + } + + } +} + +class ShadowDungeonWarning : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders(2726, 5072, 2728, 5072)) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + if ( + getQuestStage(entity, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(entity, DesertTreasure.attributeShadowStage) == 3 && + getAttribute(entity, DesertTreasure.attributeDamisWarning, false) + ) { + sendMessage(entity, "A voice seems to come from the walls around you;") + sendMessage(entity, "'You... do not be... long in this... place") + sendMessage(entity, "Turn... back now, or... prepare... to meet your... doom'") + getAttribute(entity, DesertTreasure.attributeDamisWarning, true) + } else if ( + getQuestStage(entity, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(entity, DesertTreasure.attributeShadowStage) == 100 + ) { + if (!inInventory(entity, Items.SHADOW_DIAMOND_4673) && !inBank(entity, Items.SHADOW_DIAMOND_4673)) { + sendMessage(entity, "The Diamond of Shadow seems to have mystically found its way back here...") + GroundItemManager.create(Item(Items.SHADOW_DIAMOND_4673), Location(2739, 5088, 0), entity) + } + } + } + } +} + +class ShadowDungeonAttack : MapArea { + override fun defineAreaBorders(): Array { + return arrayOf(ZoneBorders(2731, 5085, 2748, 5097)) + } + + override fun areaEnter(entity: Entity) { + if (entity is Player) { + if (getQuestStage(entity, DesertTreasure.questName) == 9) { + if (DesertTreasure.getSubStage(entity, DesertTreasure.attributeShadowStage) == 3 && + getAttribute(entity, DesertTreasure.attributeDamisInstance, null) == null + ) { + val npc = NPC.create(NPCs.DAMIS_1974, Location(2739, 5088, 0)) + setAttribute(entity, DesertTreasure.attributeDamisInstance, npc) + setAttribute(npc, "target", entity) + npc.isRespawn = false + npc.walkRadius = 30 + npc.init() + npc.attack(entity) + sendChat(npc, "You should have listened to me!") + } + } else if (DesertTreasure.getSubStage(entity, DesertTreasure.attributeShadowStage) >= 100) { + if (!inInventory(entity, Items.SHADOW_DIAMOND_4673) && !inBank(entity, Items.SHADOW_DIAMOND_4673)) { + sendMessage(entity, "The Diamond of Shadow seems to have mystically found its way back here...") + GroundItemManager.create(Item(Items.SHADOW_DIAMOND_4673), Location(2739, 5088, 0), entity) + } + } + } + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfSmokeListeners.kt b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfSmokeListeners.kt new file mode 100644 index 000000000..279b6d17d --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/DiamondOfSmokeListeners.kt @@ -0,0 +1,180 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.item.GroundItemManager +import core.game.node.item.Item +import core.game.system.timer.RSTimer +import core.game.world.map.Location +import core.tools.secondsToTicks +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class DiamondOfSmokeListeners : InteractionListener { + companion object { + const val timerIdentifierTorchNE = "deserttreasureNEtorch" + const val timerIdentifierTorchSE = "deserttreasureSEtorch" + const val timerIdentifierTorchSW = "deserttreasureSWtorch" + const val timerIdentifierTorchNW = "deserttreasureNWtorch" + + fun checkAllTorchesLit(player: Player) : Boolean { + return getVarbit(player, DesertTreasure.varbitStandingTorchNorthEast) == 1 && + getVarbit(player, DesertTreasure.varbitStandingTorchSouthEast) == 1 && + getVarbit(player, DesertTreasure.varbitStandingTorchSouthWest) == 1 && + getVarbit(player, DesertTreasure.varbitStandingTorchNorthWest) == 1 + } + } + + override fun defineListeners() { + on(Scenery.BURNT_CHEST_6420, SCENERY, "open") { player, node -> + if (checkAllTorchesLit(player)) { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeSmokeStage) == 0) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeSmokeStage, 1) + } + } + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeSmokeStage) >= 1) { + replaceScenery(node as core.game.node.scenery.Scenery, 6421, 2) + addItemOrDrop(player, Items.WARM_KEY_4656) + sendMessage(player, "You open the chest and take a key.") + } else { + sendDialogueLines(player, "There seems to be no way to open this chest. Engraved where the", "keyhole should be is a message:", "'Light the path, and find the key...'") + } + return@on true + } + + on(intArrayOf(Scenery.GATE_6451, Scenery.GATE_6452), SCENERY, "open") { player, node -> + if (getQuestStage(player, DesertTreasure.questName) == 9) { + // Set attributeUnlockedGate to true if warm key and first time unlocking the gate. + if (!getAttribute(player, DesertTreasure.attributeUnlockedGate, false) && inInventory(player, Items.WARM_KEY_4656)) { + if(removeItem(player, Items.WARM_KEY_4656)) { + sendMessage(player, "You unlock the gate and enter the room.") + setAttribute(player, DesertTreasure.attributeUnlockedGate, true) + } + } + // Fight if unlocked gate, drop recovery diamond if done. + if (getAttribute(player, DesertTreasure.attributeUnlockedGate, false)) { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeSmokeStage) == 1 && + getAttribute(player, DesertTreasure.attributeFareedInstance, null) == null) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + val npc = core.game.node.entity.npc.NPC.create(NPCs.FAREED_1977, Location(3315, 9376, 0)) + setAttribute(player, DesertTreasure.attributeFareedInstance, npc) + setAttribute(npc, "target", player) + npc.isRespawn = false + npc.init() + npc.attack(player) + sendChat(npc, "You dare trespass in my realm?") + } else if (DesertTreasure.getSubStage(player, DesertTreasure.attributeSmokeStage) >= 100) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + if (!inInventory(player, Items.SMOKE_DIAMOND_4672) && !inBank(player, Items.SMOKE_DIAMOND_4672)) { + sendMessage(player, "The Diamond of Smoke seems to have mystically found its way back here...") + GroundItemManager.create(Item(Items.SMOKE_DIAMOND_4672), Location(3315, 9376, 0), player) + } + } + } else { + sendMessage(player, "The gate is locked.") + } + + } else if (getQuestStage(player, DesertTreasure.questName) in 9..100) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendMessage(player, "The gate is locked.") + } + return@on true + } + + + on(Scenery.A_DARK_HOLE_31367, SCENERY, "enter") { player, node -> + // You have to come from the Pollnivneach Slayer Dungeon, then this will tele you back. + sendDialogueLines(player, "This hole leads to a maze of other passages. Without knowing where", "you are headed, there's no chance of reaching anywhere interesting.") + return@on true + } + + // NE Standing Torch + onUseWith(IntType.SCENERY, Items.TINDERBOX_590, Scenery.STANDING_TORCH_6406, Scenery.STANDING_TORCH_6413) { player, used, with -> + if (getDynLevel(player, Skills.FIREMAKING) < 50) { + sendMessage(player, "You need a firemaking level of 50 to light this torch.") + return@onUseWith true + } + setVarbit(player, DesertTreasure.varbitStandingTorchNorthEast, 1) + sendMessage(player, "You light the torch.") + if (checkAllTorchesLit(player)) { + sendMessage(player, "The path is lit, now claim the key...") + } + removeTimer(player, timerIdentifierTorchNE) + registerTimer(player, StandingTorchTimer(timerIdentifierTorchNE, DesertTreasure.varbitStandingTorchNorthEast)) + return@onUseWith true + } + + // SE Standing Torch + onUseWith(IntType.SCENERY, Items.TINDERBOX_590, Scenery.STANDING_TORCH_6408, Scenery.STANDING_TORCH_6414) { player, used, with -> + if (getDynLevel(player, Skills.FIREMAKING) < 50) { + sendMessage(player, "You need a firemaking level of 50 to light this torch.") + return@onUseWith true + } + setVarbit(player, DesertTreasure.varbitStandingTorchSouthEast, 1) + sendMessage(player, "You light the torch.") + if (checkAllTorchesLit(player)) { + sendMessage(player, "The path is lit, now claim the key...") + } + removeTimer(player, timerIdentifierTorchSE) + registerTimer(player, StandingTorchTimer(timerIdentifierTorchSE, DesertTreasure.varbitStandingTorchSouthEast)) + return@onUseWith true + } + + // SW Standing Torch + onUseWith(IntType.SCENERY, Items.TINDERBOX_590, Scenery.STANDING_TORCH_6410, Scenery.STANDING_TORCH_6415) { player, used, with -> + if (getDynLevel(player, Skills.FIREMAKING) < 50) { + sendMessage(player, "You need a firemaking level of 50 to light this torch.") + return@onUseWith true + } + setVarbit(player, DesertTreasure.varbitStandingTorchSouthWest, 1) + sendMessage(player, "You light the torch.") + if (checkAllTorchesLit(player)) { + sendMessage(player, "The path is lit, now claim the key...") + } + removeTimer(player, timerIdentifierTorchSW) + registerTimer(player, StandingTorchTimer(timerIdentifierTorchSW, DesertTreasure.varbitStandingTorchSouthWest)) + return@onUseWith true + } + + // NW Standing Torch + onUseWith(IntType.SCENERY, Items.TINDERBOX_590, Scenery.STANDING_TORCH_6412, Scenery.STANDING_TORCH_6416) { player, used, with -> + if (getDynLevel(player, Skills.FIREMAKING) < 50) { + sendMessage(player, "You need a firemaking level of 50 to light this torch.") + return@onUseWith true + } + setVarbit(player, DesertTreasure.varbitStandingTorchNorthWest, 1) + sendMessage(player, "You light the torch.") + if (checkAllTorchesLit(player)) { + sendMessage(player, "The path is lit, now claim the key...") + } + removeTimer(player, timerIdentifierTorchNW) + registerTimer(player, StandingTorchTimer(timerIdentifierTorchNW, DesertTreasure.varbitStandingTorchNorthWest)) + return@onUseWith true + } + } +} + +class StandingTorchTimer(private val timerIdentifier: String = "deserttreasureunknowntimer", private val torchVarbit: Int = 0) : RSTimer(secondsToTicks(150), timerIdentifier) { + override fun run(entity: Entity): Boolean { + if (entity is Player) { + when(timerIdentifier) { + DiamondOfSmokeListeners.timerIdentifierTorchNE -> sendMessage(entity, "The North-east torch burns out...") + DiamondOfSmokeListeners.timerIdentifierTorchSE -> sendMessage(entity, "The South-east torch burns out...") + DiamondOfSmokeListeners.timerIdentifierTorchSW -> sendMessage(entity, "The South-west torch burns out...") + DiamondOfSmokeListeners.timerIdentifierTorchNW -> sendMessage(entity, "The North-west torch burns out...") + else -> sendMessage(entity, "The torch burns out...") + } + setVarbit(entity, torchVarbit, 0) + } + entity.timers.removeTimer(this) + return true + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/EblisDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/EblisDialogue.kt new file mode 100644 index 000000000..11608e56c --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/EblisDialogue.kt @@ -0,0 +1,328 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class EblisDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, EblisDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return EblisDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.EBLIS_1923) + } + +} +class EblisDialogueFile : DialogueBuilderFile() { + + companion object { + fun checkAllGiven(player: Player): Boolean { + return (getAttribute(player, DesertTreasure.attributeCountMagicLogs, 0) >= 12 && + getAttribute(player, DesertTreasure.attributeCountSteelBars, 0) >= 6 && + getAttribute(player, DesertTreasure.attributeCountMoltenGlass, 0) >= 6 && + getAttribute(player, DesertTreasure.attributeCountBones, 0) >= 1 && + getAttribute(player, DesertTreasure.attributeCountAshes, 0) >= 1 && + getAttribute(player, DesertTreasure.attributeCountCharcoal, 0) >= 1 && + getAttribute(player, DesertTreasure.attributeCountBloodRune, 0) >= 1) + } + } + + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4) + .npcl("Leave us to our fate. We care nothing for the world that betrayed us, or those that come from it.") + .end() + + b.onQuestStages(DesertTreasure.questName, 5,6) + .playerl("Hello. I represent the Museum of Varrock, and I have reason to believe there may be some kinds of artefacts of historical significance in the nearby area...") + .npcl("Ah yes. The only time people care about our existence is when they think they have something to gain from us.") + .npcl("I have nothing to say to you. You and your kind are not welcome here.") + .playerl("Please, if I can just have a few minutes of your time to ask some questions...?") + .npcl("(sigh) I suppose I can spare you that. What do you wish to know about?") + .options() + .let { optionBuilder -> + optionBuilder.option("Why is this village so hostile?") + .playerl("Why are all of the people here so hostile? You would think I was asking you for money instead of just for answers to a few questions...") + .npcl("It is a long story, and I doubt you have much interest in hearing it. Your sort never are, you just take what you can of ours, and then abandon us once more to the desert.") + .options() + .let { optionBuilder2 -> + optionBuilder2.option("No, I want to hear this story.") + .playerl("Actually, I'd be quite interested to hear what it is you have to say to excuse the attitude everybody in this village seems to have.") + .npcl("Ah, it all begun many generations ago, when our ancestors were the proud rulers of these lands...") + .npcl("My ancestors lived far to the North of here, and our lands stretched from the sea in the East to the river Lum, and the mountain of ice. From coast to coast, North to South, our domain was absolute.") + .npcl("Our god was kind to us, and blessed us with prosperity and happiness, and in return we were merciless to his enemies wherever we found them.") + .npcl("Then came the betrayal.") + .npcl("Our god was banished, leaving us helpless to our fates.") + .npcl("Without his protection, we were forced to fend for ourselves once more, against the enemies that sought to destroy us through their petty jealousies.") + .npcl("But we did not succumb without fighting! The spiteful Saradomin and pathetic Zamorak warred with each other, but the hatred they had for each other was as nothing to the hatred they held towards us!") + .npcl("With each battle they waged, we lost more and more land, unable to fight on all fronts, and were pushed further and further South into this gods-forsaken desert.") + .npcl("Our greatest hero, Azzanadra, was finally trapped in a strange stone structure to the South of here, and bound within by terrible powers...") + .npcl("And with that our lands, our homes, our very lives were stolen from us! Too weak to reclaim what was rightfully ours, we made our homes here, knowing that someday Azzanadra will") + .npcl("return with his magnificent power, and bring us back to our former glory...") + .playerl("So you're upset because of something that happened hundreds of years ago?") + .playerl("Seems to me like maybe you should find some closure, and let the past go...") + .npcl("The insults heaped upon my race will never be forgotten, will never be forgiven and will never again be overlooked.") + .npcl("Someday, a harsh wind will blow upon this land, uncovering the wrongs of the past, and we will get back what is rightfully ours. Until such a day we will bide our time here, and will") + .npcl("always be ready with our blades for our righteous vengeance.") + .end() + + optionBuilder2.option("I don't care about your story.") + .playerl("I don't really care what your story is to be honest, there is no excuse for such rudeness or hostility.") + .playerl("I have done nothing wrong to you, but everybody here treats me like I have committed some great crime against the village.") + .npcl("That is because, from our point of view, you have.") + .playerl("What? Just because I entered your village?") + .npcl("You have no right to be here! You have no right to the life you have, for it was taken at our expense!") + .playerl("Whatever... No wonder all you loonies live out here in the desert by yourselves.") + .end() + } + + optionBuilder.option("Do you know anything about treasure near here?") + .playerl("I was wondering if you knew anything about some treasure somewhere around here?") + .playerl("I have some evidence that there might be some kind of treasure hidden very close to this village...") + .npcl("If I knew of any treasure I would not choose to spend my life in this gods-forsaken desert.") + .end() + + optionBuilder.option("Do you know anything about a fortress near here?") + .playerl("Do you know anything about some kind of fortress nearby? I have reason to believe there is, or at least used to be, some kind of fortress very close to here...") + .npcl("Nobody would build anything in this wasteland unless they were forced to, to survive.") + .npcl("I know of no fortress, I know of no reason why anyone would ever bother doing anything out here in the desert.") + .end() + + + // This will only show up after you've talked to the bartender. + optionBuilder.optionIf("Tell me of the four diamonds of Azzanadra.") { player -> + return@optionIf getQuestStage(player, DesertTreasure.questName) == 6 + } + .playerl("So tell me... Did you ever hear of something called the Diamonds of Azzanadra?") + .npcl("This is the treasure which you seek???") + .npcl("Please accept my apologies noble @g[sir,madam]! I thought you were but some opportunistic thief, looking to steal what heritage we have left! Now I see that you are in fact a brave adventurer,") + .npcl("looking to restore our glories back upon us!") + .playerl("Uh... yeah... So anyway, you have heard of them?") + .npcl("Heard of them? Of course I have heard of them! They are the legacy of the great Mahjarrat hero, Azzanadra!") + .playerl("So... do you have any idea where they might be? I have a feeling they will be very valuable.") + .playerl("Uh, valuable as historical artefacts I mean, obviously.") + .npcl("They were stolen by warriors of the false god Zamorak generations ago. When you find the warriors, you will find the diamonds.") + .npcl("I suspect they will not willingly part with such objects of power however.") + .npc("Beware too, for these warriors are very powerful;", "they have taken the powers of the diamonds into themselves!") + .playerl("How do you mean?") + .npcl("Each diamond has an elemental quality...") + .npcl("There is the Diamond of Blood, the Diamond of Ice, the Diamond of Smoke and the Diamond of Shadow.") + .npcl("You should expect the warriors to have taken some aspect of these diamonds as their own...") + .playerl("Do you have any idea how I could track down these warriors somehow, then?") + .npcl("There is an ancient spell I know of that may spy upon such power... But it will require a few ingredients for it to work.") + .npcl("Should you be willing to get these ingredients for me, I will be able to locate the rough area where each of these warriors has taken refuge. The spell is imprecise, but it should help you get on the") + .npcl("right track in your search.") + .npcl("Is your desire for our freedom strong enough? Will you gather the ingredients for this spell for me?") + .options() + .let { optionBuilder2 -> + + optionBuilder2.option("Yes") + // The quest should jump to the next stage here, but I didn't want to write some weird if else here. + .playerl("Sure, what do you need?") + .npcl("For this spell, I will need to make some scrying glasses. I will need enough so that we can view the realm in its entirety.") + .npcl("When enchanted, the scrying glass will be able to let us view any area that has been influenced by the presence of the Diamonds of Azzanadra.") + .playerl("Okay, but what exactly do you need for this spell?") + .npcl("Well, six scrying glasses should be sufficient. For each scrying glass, I will need two magic logs, a steel bar and some molten glass. This makes a total of 12 magic logs, 6 pieces of molten") + .npcl("glass, and 6 steel bars.") + .npcl("In addition, for the actual spell to enchant the glasses, I will require one set of normal bones, some ash, some charcoal and a single blood rune.") + .npcl("Do you understand me, adventurer?") + .playerl("Quick question; what kind of bones do you need?") + .npcl("Standard bones. Other types of bones are of no use to me in this spell.") + .options() + .let { optionBuilder3 -> + optionBuilder3.option("Yes, I will go get those for you.") + .playerl("It's a slightly odd collection of ingredients, but I shouldn't have too much trouble getting those for you.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 6) { + setQuestStage(player, DesertTreasure.questName, 7) + } + } + + optionBuilder3.option("No, please repeat those ingredients.") + .npcl("Before I can complete the spell I will still need the following items;") + .npc("12 magic logs", "6 steel bars", "6 molten glass") + .npc("1 bones,", "1 ashes,", "1 charcoal", "and 1 blood rune.") // This is sic authentic trash dialogue. + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 6) { + setQuestStage(player, DesertTreasure.questName, 7) + } + } + + } + + optionBuilder2.option("No") + .playerl("Actually I don't feel like going on a shopping trip for you right now.") + .npcl("As you wish. I should have known not to get my hopes up that our long cursed life may soon be at an end...") + .end() + } + + optionBuilder.option("Nothing thanks.") + .playerl("Actually, there was nothing I really wanted to ask you about.") + .npcl("Yes, it is exactly like your sort to waste my time in such a way.") + .end() + } + + b.onQuestStages(DesertTreasure.questName, 7) + // Branch to check + + .branch { player -> + return@branch if (checkAllGiven(player)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npcl("Excellent! Those are all the ingredients I need to create the scrying glasses.") + .npcl("I will find a suitable spot in the desert to the East of here, and set them up. When you are ready to begin your search, please come and find me there, I will show you how to utilise the") + .npcl("mirrors to find the diamonds.") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 7) { + setQuestStage(player, DesertTreasure.questName, 8) + } + } + + branch.onValue(0) + .npcl("Before I can complete the spell I will still need the following items;") + .manualStage { df, player, _, _ -> + df.interpreter!!.sendDialogues(npc!!.id, FacialExpression.NEUTRAL, + "" + (12 - getAttribute(player, DesertTreasure.attributeCountMagicLogs, 0)) + " magic logs", + "" + (6 - getAttribute(player, DesertTreasure.attributeCountSteelBars, 0)) + " steel bars", + "" + (6 - getAttribute(player, DesertTreasure.attributeCountMoltenGlass, 0)) + " molten glass") + } + .manualStage { df, player, _, _ -> + df.interpreter!!.sendDialogues(npc!!.id, FacialExpression.NEUTRAL, + "" + (1 - getAttribute(player, DesertTreasure.attributeCountBones, 0)) + " bones,", + "" + (1 - getAttribute(player, DesertTreasure.attributeCountAshes, 0)) + " ashes,", + "" + (1 - getAttribute(player, DesertTreasure.attributeCountCharcoal, 0)) + " charcoal", + "and " + (1 - getAttribute(player, DesertTreasure.attributeCountBloodRune, 0)) + " blood rune.") // This is sic authentic trash dialogue. + } + .end() + } + + b.onQuestStages(DesertTreasure.questName, 8,9,10) + .npcl("Meet me again in the desert East of here, I will use these ingredients to create a scrying glass for you.") + .end() + + b.onQuestStages(DesertTreasure.questName, 100) + .npcl("Meet me again in the desert East of here.") + .end() + + } +} + +class EblisCollectionsListeners : InteractionListener { + override fun defineListeners() { + + onUseWith(IntType.NPC, intArrayOf(Items.MAGIC_LOGS_1513, Items.MAGIC_LOGS_1514), NPCs.EBLIS_1923) { player, used, with -> + for(i in 0..11) { + if (inInventory(player, used.id)) { + if (getAttribute(player, DesertTreasure.attributeCountMagicLogs, 0) < 12) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountMagicLogs, + getAttribute(player, DesertTreasure.attributeCountMagicLogs, 0) + 1) + sendMessage(player, "You hand over a magic log.") + } + } else { + break + } + } else { + break + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.STEEL_BAR_2353, Items.STEEL_BAR_2354), NPCs.EBLIS_1923) { player, used, with -> + for(i in 0..5) { + if (inInventory(player, used.id)) { + if (getAttribute(player, DesertTreasure.attributeCountSteelBars, 0) < 6) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountSteelBars, + getAttribute(player, DesertTreasure.attributeCountSteelBars, 0) + 1) + sendMessage(player, "You hand over a steel bar.") + } + } else { + break + } + } else { + break + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.MOLTEN_GLASS_1775, Items.MOLTEN_GLASS_1776), NPCs.EBLIS_1923) { player, used, with -> + for(i in 0..5) { + if (inInventory(player, used.id)) { + if (getAttribute(player, DesertTreasure.attributeCountMoltenGlass, 0) < 6) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountMoltenGlass, + getAttribute(player, DesertTreasure.attributeCountMoltenGlass, 0) + 1) + sendMessage(player, "You hand over some molten glass.") + } + } else { + break + } + } else { + break + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.BONES_526, Items.BONES_527), NPCs.EBLIS_1923) { player, used, with -> + if (getAttribute(player, DesertTreasure.attributeCountBones, 0) < 1) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountBones, + getAttribute(player, DesertTreasure.attributeCountBones, 0) + 1) + sendNPCDialogue(player, NPCs.EBLIS_1923, "Thank you, those are enough bones for the spell.") + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.ASHES_592, Items.ASHES_593), NPCs.EBLIS_1923) { player, used, with -> + if (getAttribute(player, DesertTreasure.attributeCountAshes, 0) < 1) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountAshes, + getAttribute(player, DesertTreasure.attributeCountAshes, 0) + 1) + sendNPCDialogue(player, NPCs.EBLIS_1923, "Thank you, that is enough ash for the spell.") + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.CHARCOAL_973, Items.CHARCOAL_974), NPCs.EBLIS_1923) { player, used, with -> + if (getAttribute(player, DesertTreasure.attributeCountCharcoal, 0) < 1) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountCharcoal, + getAttribute(player, DesertTreasure.attributeCountCharcoal, 0) + 1) + sendNPCDialogue(player, NPCs.EBLIS_1923, "Thank you, that is enough charcoal for the spell.") + } + } + return@onUseWith true + } + + onUseWith(IntType.NPC, intArrayOf(Items.BLOOD_RUNE_565), NPCs.EBLIS_1923) { player, used, with -> + if (getAttribute(player, DesertTreasure.attributeCountBloodRune, 0) < 1) { + if (removeItem(player, used.id)) { + setAttribute(player, DesertTreasure.attributeCountBloodRune, + getAttribute(player, DesertTreasure.attributeCountBloodRune, 0) + 1) + sendNPCDialogue(player, NPCs.EBLIS_1923, "Thank you, that blood rune should be sufficient for the spell.") + } + } + return@onUseWith true + } + + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/EblisMirrorsDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/EblisMirrorsDialogue.kt new file mode 100644 index 000000000..43bec25f1 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/EblisMirrorsDialogue.kt @@ -0,0 +1,127 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class EblisMirrorsDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, EblisMirrorsDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return EblisMirrorsDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.EBLIS_1924, NPCs.EBLIS_1925) + } +} +class EblisMirrorsDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 8) + .npcl("Ah, so you got here at last.") + .npc("As you may noticed, I have made the mirrors for", "the spell, and cast the enchantment upon them.") + .npc("By simply looking into each mirror, you will be able to", "see the area where the trace magics from the Diamonds", "of Azzanadra are emanating from.") + .npc("Unfortunately, I cannot narrow the search closer with", "this kind of spell, but if you search the areas shown to", "you, you may be able to find some clues leading you to", "the evil warriors of Zamorak who stole the diamonds in") + .npc("the first place.") + .player(FacialExpression.THINKING, "So you can't be anymore specific about where to look", "for these warriors and their diamonds?") + .npc("I'm afraid not, other than the direction that the mirror", "is facing will be approximately the direction you will", "need to head in.") + .npc("Make sure to come and speak to me when you have", "retrieved all four diamonds.") + .endWith { _, player -> + if (getQuestStage(player, DesertTreasure.questName) == 8) { + setQuestStage(player, DesertTreasure.questName, 9) + } + } + + b.onQuestStages(DesertTreasure.questName, 9, 10) + .branch { player -> + return@branch if (DesertTreasure.completedAllSubstages(player)) { + 1 + } else { + 0 + } + }.let { branch -> + branch.onValue(1) + .player(FacialExpression.THINKING, "So I have all four of these Diamonds of Azzanadra, now", "what?") + .npc("Azzanadra was our greatest ever hero.", "He was unkillable, and the cowardly traitors who stole", "our lands did not know what to do with him, for his", "hatred for them was as strong as his magics.") + .npc(FacialExpression.SAD, "In the end, they cast a spell upon him, to trap him in", "the stone structure to the South of here.") + .npc(FacialExpression.ANNOYED, "They stole his very life force, the essence of his power,", "and trapped it within four crystals - the very same", "Four Diamonds which you have now recovered from", "the brigands who stole from us.") + .npc(FacialExpression.ANNOYED, "The four pillars surrounding the structure are keeping", "the containment spell intact.", "By placing a diamond into each, you will breach the", "magical defenses and begin to restore Azzanadra's") + .npcl(FacialExpression.ANNOYED, "power, and be able to enter the structure.") + .npcl("Go, place the diamonds, and free my lord Azzanadra!") + .npc(FacialExpression.FRIENDLY, "The path will be hard, for his prison is full of traps", "and danger to prevent his rescue, but he will reward you", "beyond your wildest dreams when freed!") + .npc("Quickly...", "After all these centuries, Lord Azzanadra is nearly free!", "You must spare no time, place the Diamonds upon the", "pillars and enter the pyramid so that you may free him!") + .end() + + branch.onValue(0) + .playerl("So can you give me any help on where to find these warriors and their diamonds?") + .npcl("No, the magic used in this spell is powerful, but inaccurate. The direction the scrying glass faces is roughly the direction you will find the warrior, but I'm afraid I") + .npcl("can't be any more help than that.") + .playerl("I don't understand why there are six mirrors when there are only four diamonds...") + .npcl("As I say, the enchantment is very inaccurate.") + .npcl("I can only focus upon the aura the diamonds have left behind them, so any place where the Diamonds were present for a significant period of time will still be shown - such as the Bandit Camp where I make my home.") + .npcl("My apologies, but magic is an inaccurate art in many respects.") + .npcl("Don't forget to come back here when you have collected all four diamonds.") + .end() + } + + b.onQuestStages(DesertTreasure.questName, 100) + .branch { player -> + if (inInventory(player, Items.ANCIENT_STAFF_4675)) { + 1 + } else { + 0 + } + }.let { branch -> + branch.onValue(1) + .playerl("Hello again.") + .npcl("Greetings. I await the return of my Lord Azzanadra and of our god. I do not know why, but I feel this spot has some significance...") + .end() + + branch.onValue(0) + .npcl("So have you spoken to my Lord Azzanadra yet?") + .playerl("Yes I have.") + .npcl("And what words did he have for his followers?") + .playerl("Er... He didn't really mention you at all, but he did teach me some cool new magic spells.") + .npcl("It is understandable perhaps... His poor mind must be addled after all of those years of confinement, he would not willingly ignore his followers...") + .npcl("Anyway, if he has taught you our ancient magics, you may be interested in purchasing an ancient heirloom that was passed down to me. My ancestor fought in the ancient battles using the") + .npcl("magic of our god. This heirloom will help you with the speed of your spell-casting.") + .npcl("Normally I could not bear to part with such a priceless relic, but for your help in freeing my Lord Azzanadra, I will be prepared to sell it to you for a mere 80,000 gold.") + .npcl("Are you interested?") + .options() + .let { optionBuilder -> + optionBuilder.option("Yes please") + .branch { player -> + if (inInventory(player, Items.COINS_995, 80000)) { 1 } else { 0 } + } + .let { branch2 -> + branch2.onValue(1) + .npcl("Take care of it, it is the only heirloom from those times I possess, although rumour has it many of our ancient warriors were buried with identical weapons so that they could continue to fight for my Lord in their deaths.") + .endWith { _, player -> + if (removeItem(player, Item(Items.COINS_995, 80000))) { + addItemOrDrop(player, Items.ANCIENT_STAFF_4675) + } + } + + branch2.onValue(0) + .linel("You don't have enough money to buy that.") + .end() + } + + optionBuilder.option("No thanks") + .playerl("No, not really.") + .npcl("As you wish. Bear my offer in mind should you ever change your decision, I will remain here.") + .end() + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/FareedBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/FareedBehavior.kt new file mode 100644 index 000000000..be98d963c --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/FareedBehavior.kt @@ -0,0 +1,76 @@ +package content.region.desert.quest.deserttreasure + +import content.global.skill.magic.modern.WaterSpell +import core.api.* +import core.game.container.impl.EquipmentContainer +import core.game.global.action.EquipHandler +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class FareedBehavior : NPCBehavior(NPCs.FAREED_1977) { + + var clearTime = 0 + + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + if (attacker is Player) { + if (attacker == getAttribute(self, "target", null)) { + return true + } + sendMessage(attacker, "It's not after you...") + } + return false + } + + override fun tick(self: NPC): Boolean { + val player: Player? = getAttribute(self, "target", null) + if (clearTime++ > 800) { + clearTime = 0 + if (player != null) { + sendMessage(player, "Fareed has lost interest in you, and returned to his flames.") + removeAttribute(player, DesertTreasure.attributeFareedInstance) + } + poofClear(self) + } + return true + } + + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (state.style == CombatStyle.MAGIC && state.spell !is WaterSpell) { + state.neutralizeHits() + } + } + + override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) { + if (victim is Player) { + if (!inEquipment(victim, Items.ICE_GLOVES_1580)) { + val weapon = getItemFromEquipment(victim, EquipmentSlot.WEAPON) + if(weapon != null) { + EquipHandler.unequip(victim, EquipmentContainer.SLOT_WEAPON, weapon.id) + } +// val weapon = getItemFromEquipment(victim, EquipmentSlot.WEAPON) +// if(weapon != null && removeItem(victim, weapon.id, Container.EQUIPMENT)) { +// addItemOrDrop(victim, weapon.id) +// } + sendMessage(victim, "The heat from the warrior causes you to drop your weapon.") + } + } + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + addItemOrDrop(killer, Items.SMOKE_DIAMOND_4672) + sendMessage(killer, "You take the Diamond of Smoke from the ashes of the warrior.") + if (DesertTreasure.getSubStage(killer, DesertTreasure.attributeSmokeStage) == 1) { + DesertTreasure.setSubStage(killer, DesertTreasure.attributeSmokeStage, 100) + removeAttribute(killer, DesertTreasure.attributeFareedInstance) + } + } + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollBehavior.kt new file mode 100644 index 000000000..5b4eeed6a --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollBehavior.kt @@ -0,0 +1,75 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.FacialExpression +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.combat.BattleState +import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import org.rs09.consts.NPCs + +class FatherTrollBehavior : NPCBehavior(NPCs.ICE_TROLL_1943 /** WRONG NAME ITS ICE_BLOCK */) { + + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + return attacker is Player + } + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + self.properties.combatPulse.stop() + attacker.properties.combatPulse.stop() + if (state.estimatedHit + Integer.max(state.secondaryHit, 0) >= self.skills.lifepoints) { + state.estimatedHit = self.skills.lifepoints + 1 + state.secondaryHit = -1 + self.skills.lifepoints = self.skills.maximumLifepoints // Reset life of ice block + + setVarbit(attacker, DesertTreasure.varbitFrozenFather, 1) + if (getVarbit(attacker, DesertTreasure.varbitFrozenMother) == 1) { + setVarbit(attacker, DesertTreasure.varbitChildReunite, 4) + queueScript(self, 1, QueueStrength.NORMAL) { stage: Int -> + openDialogue(attacker, ChatFatherAndMotherTrollDialogueFile()) + return@queueScript stopExecuting(self) + } + } else { + queueScript(self, 1, QueueStrength.NORMAL) { stage: Int -> + sendNPCDialogue(attacker, NPCs.TROLL_FATHER_1948, "Oh thank you! It was really cold in there! But please, you must free my wife as well! Our son is depending on us!", FacialExpression.OLD_CALM_TALK2) + return@queueScript stopExecuting(self) + } + } + } + } + } +} + +class MotherTrollBehavior : NPCBehavior(NPCs.ICE_BLOCK_1945) { + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + return attacker is Player + } + override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) { + if (attacker is Player) { + self.properties.combatPulse.stop() + attacker.properties.combatPulse.stop() + if (state.estimatedHit + Integer.max(state.secondaryHit, 0) >= self.skills.lifepoints) { + state.estimatedHit = self.skills.lifepoints + 1 + state.secondaryHit = -1 + self.skills.lifepoints = self.skills.maximumLifepoints // Reset life of ice block + + setVarbit(attacker, DesertTreasure.varbitFrozenMother, 1) + if (getVarbit(attacker, DesertTreasure.varbitFrozenFather) == 1) { + setVarbit(attacker, DesertTreasure.varbitChildReunite, 4) + queueScript(self, 1, QueueStrength.NORMAL) { stage: Int -> + openDialogue(state.attacker!!.asPlayer(), ChatFatherAndMotherTrollDialogueFile()) + return@queueScript stopExecuting(self) + } + } else { + queueScript(self, 1, QueueStrength.NORMAL) { stage: Int -> + sendNPCDialogue(attacker, NPCs.TROLL_MOTHER_1950, "Wow, thanks for breaking me out of that ice! But please, my husband is still trapped in there!", FacialExpression.OLD_CALM_TALK2) + return@queueScript stopExecuting(self) + } + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollDialogue.kt new file mode 100644 index 000000000..a83ededd6 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/FatherAndMotherTrollDialogue.kt @@ -0,0 +1,170 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.* +import core.game.interaction.QueueStrength +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Components +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +// Base: 1943 Iced: 1944 Broke: 1948 Reunion: 1947 +// Base: 1945 Iced: 1946 Broke: 1950 Reunion: 1949 + +@Initializable +class FatherTrollDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 3 && + getVarbit(player, DesertTreasure.varbitFrozenFather) == 1 && + getVarbit(player, DesertTreasure.varbitFrozenMother) == 1) { + openDialogue(player!!, ChatFatherAndMotherTrollDialogueFile(), npc) + } else if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 3) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(FacialExpression.OLD_CALM_TALK2, "Oh thank you! It was really cold in there! But please, you must free my wife as well! Our son is depending on us!").also { stage = END_DIALOGUE } + } + } + }, npc) + } else if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 4) { + openDialogue(player!!, ChatFatherAndMotherTrollAfterDialogueFile(), npc) + } else if ((getQuestStage(player, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) >= 5) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(FacialExpression.OLD_CALM_TALK2, "Thanks again for freeing me from that ice block! I might be a troll, but it was real uncomfortable in there!").also { stage = END_DIALOGUE } + } + } + }, npc) + } + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return FatherTrollDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(1943) + } +} + +@Initializable +class MotherTrollDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + println(getQuestStage(player, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) >= 5) + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 3 && + getVarbit(player, DesertTreasure.varbitFrozenFather) == 1 && + getVarbit(player, DesertTreasure.varbitFrozenMother) == 1) { + openDialogue(player!!, ChatFatherAndMotherTrollDialogueFile(), npc) + } else if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 3) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(FacialExpression.OLD_CALM_TALK2, "Wow, thanks for breaking me out of that ice! But please, my husband is still trapped in there!").also { stage = END_DIALOGUE } + } + } + }, npc) + } else if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 4) { + openDialogue(player!!, ChatFatherAndMotherTrollAfterDialogueFile(), npc) + } else if ((getQuestStage(player, DesertTreasure.questName) == 9 && + DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) >= 5) || + getQuestStage(player, DesertTreasure.questName) >= 10) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(FacialExpression.OLD_CALM_TALK2, "Thanks again for freeing me from that ice block! I don't know what my little snookums would have done without us!").also { stage = END_DIALOGUE } + } + } + }, npc) + } + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return MotherTrollDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.TROLL_MOTHER_1950) + } +} + +class ChatFatherAndMotherTrollDialogueFile : DialogueFile() { + // We gon do like this as the old way allows to easily jump between npcs. + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "Phew! Am I glad to be out of that big ice cube! Are you okay too darling?").also { stage++ } + 1 -> npcl(NPCs.TROLL_MOTHER_1950, FacialExpression.OLD_CALM_TALK2, "Yes, I thought we were done for! Why ever did that nasty Kamil freeze us up there anyway?").also { stage++ } + 2 -> playerl("He must have been trying to protect his Diamond...").also { stage++ } + 3 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "You mean that diamond I found the other day belonged to him? But why didn't he just ask for it back? It's not like I really want it or anything!").also { stage++ } + 4 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "And how did you know we had that diamond anyway, fleshy?").also { stage++ } + 5 -> playerl("Your son told me. That's why I rescued you, it is very important that I have that diamond...").also { stage++ } + 6 -> npcl(NPCs.TROLL_MOTHER_1950, FacialExpression.OLD_CALM_TALK2, "Ooohhhhh, my poor baby! He must have been so worried about us...").also { stage++ } + 7 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "Yes, but he certainly inherited his Dad's smarts!").also { stage++ } + 8 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "If he'd told this fleshy that he had the Diamond and not us, we might never have been rescued!").also { stage++ } + 9 -> playerl("Wait... what? That stupid little troll kid had the diamond all along?").also { stage++ } + 10 -> npcl(NPCs.TROLL_MOTHER_1950, FacialExpression.OLD_CALM_TALK2, "Don't you talk about my baby like that!").also { stage++ } + 11 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "Now, now dear, all's well that ends well. We've been freed and this fleshy has certainly earned himself that diamond.").also { stage++ } + 12 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK2, "Let's get out of this terrible place and see our son!").also { + stage++ + if (DesertTreasure.getSubStage(player!!, DesertTreasure.attributeIceStage) == 3) { + DesertTreasure.setSubStage(player!!, DesertTreasure.attributeIceStage, 4) + } + } + + 13 -> { + queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int -> + when (stage) { + 0 -> { + closeOverlay(player!!) + openOverlay(player!!, Components.FADE_TO_BLACK_120) + return@queueScript delayScript(player!!, 6) + } + 1 -> { + teleport(player!!, Location(2836, 3739, 0)) + return@queueScript delayScript(player!!, 1) + } + 2 -> { + openOverlay(player!!, Components.FADE_FROM_BLACK_170) + return@queueScript delayScript(player!!, 6) + } + 3 -> { + closeOverlay(player!!) + openDialogue(player!!, ChatFatherAndMotherTrollAfterDialogueFile()) + return@queueScript stopExecuting(player!!) + } + else -> return@queueScript stopExecuting(player!!) + } + } + end() + } + } + } +} + +class ChatFatherAndMotherTrollAfterDialogueFile : DialogueFile() { + // We gon do like this as the old way allows to easily jump between npcs. + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + 0 -> npcl(NPCs.TROLL_CHILD_1933, FacialExpression.OLD_CALM_TALK2, "Mommy! Daddy! You're free!").also { stage++ } + 1 -> npc(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK1, "That's right son, and it's all thanks to this brave", "adventurer here.", "Now, make sure you hand over that diamond he was", "looking for.").also { stage++ } + 2 -> npcl(NPCs.TROLL_FATHER_1948, FacialExpression.OLD_CALM_TALK1, "It has been nothing but trouble for us, let's just get back to our cave and have dinner.").also { stage++ } + 3 -> npcl(NPCs.TROLL_MOTHER_1950, FacialExpression.OLD_CALM_TALK2, "That's right son, it's your favorite tonight too! A big plate of raw mackerel!").also { stage++ } + 4 -> npcl(NPCs.TROLL_CHILD_1933, FacialExpression.OLD_CALM_TALK2, "RAW MACKEREL! YUMMY!").also { stage++ } + 5 -> npcl(NPCs.TROLL_CHILD_1933, FacialExpression.OLD_CALM_TALK1, "Here ya go mister! Thanks for getting my mom and dad away from the bad man!").also { + stage++ + if (DesertTreasure.getSubStage(player!!, DesertTreasure.attributeIceStage) in 3 .. 4) { + addItemOrDrop(player!!, Items.ICE_DIAMOND_4671) + DesertTreasure.setSubStage(player!!, DesertTreasure.attributeIceStage, 100) + } + } + 6 -> playerl("Don't worry about it, just as long as I don't have to go back into that blizzard.").also { + stage = END_DIALOGUE + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollBehavior.kt new file mode 100644 index 000000000..1146559a4 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollBehavior.kt @@ -0,0 +1,35 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import org.rs09.consts.NPCs + +class IceTrollBehavior : NPCBehavior(*iceTrollIds) { + companion object { + private val iceTrollIds = intArrayOf( + NPCs.ICE_TROLL_1936, + NPCs.ICE_TROLL_1937, + NPCs.ICE_TROLL_1938, + NPCs.ICE_TROLL_1939, + NPCs.ICE_TROLL_1940, + NPCs.ICE_TROLL_1941, + NPCs.ICE_TROLL_1942, + ) + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + if (getQuestStage(killer, DesertTreasure.questName) >= 9) { + val currentIceTrollKill = getAttribute(killer, DesertTreasure.attributeTrollKillCount, 0) + if (currentIceTrollKill < 5) { + setAttribute(killer, DesertTreasure.attributeTrollKillCount, currentIceTrollKill + 1) + setVarbit(killer, DesertTreasure.varbitCaveEntrance, getAttribute(killer, DesertTreasure.attributeTrollKillCount, 0)) + sendMessage(killer, "A chunk of ice falls away from the cave entrance...") + } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollDialogue.kt new file mode 100644 index 000000000..ac37cb4dd --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/IceTrollDialogue.kt @@ -0,0 +1,35 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.NPCs + +@Initializable +class IceTrollDialogue (player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, IceTrollDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return IceTrollDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.ICE_TROLL_1935) + } + +} +class IceTrollDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onPredicate { _ -> true } + .npc(FacialExpression.OLD_LAUGH1, "Hur hur hur!", "Well look here, a puny fleshy human!") + .npc(FacialExpression.OLD_LAUGH1, "You should beware of the icy wind that runs through", "this valley, it will bring a fleshy like you to a cold end", "indeed!") + .end() + } + +} diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/KamilBehavior.kt b/Server/src/main/content/region/desert/quest/deserttreasure/KamilBehavior.kt new file mode 100644 index 000000000..e5ddbdae1 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/KamilBehavior.kt @@ -0,0 +1,79 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.node.entity.Entity +import core.game.node.entity.combat.* +import core.game.node.entity.combat.equipment.SwitchAttack +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import core.game.node.entity.player.Player +import core.game.world.update.flag.context.Animation +import core.tools.RandomFunction +import org.rs09.consts.NPCs + +// https://www.youtube.com/watch?v=xeu6Ncmt1fY + +class KamilBehavior : NPCBehavior(NPCs.KAMIL_1913) { + + var clearTime = 0 + + override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean { + if (attacker is Player) { + if (attacker == getAttribute(self, "target", null)) { + return true + } + sendMessage(attacker, "It's not after you...") + } + return false + } + + override fun tick(self: NPC): Boolean { + val player: Player? = getAttribute(self, "target", null) + if (clearTime++ > 800) { + clearTime = 0 + if (player != null) { + sendMessage(player, "Kamil vanishes on an icy wind...") + removeAttribute(player, DesertTreasure.attributeKamilInstance) + } + poofClear(self) + } + return true + } + + override fun onDeathFinished(self: NPC, killer: Entity) { + if (killer is Player) { + if (DesertTreasure.getSubStage(killer, DesertTreasure.attributeIceStage) == 2) { + DesertTreasure.setSubStage(killer, DesertTreasure.attributeIceStage, 3) + removeAttribute(killer, DesertTreasure.attributeKamilInstance) + sendPlayerDialogue(killer, "Well, that must have been the 'bad man' that the troll kid was on about... His parents must be up ahead somewhere.") + } + } + } + + override fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler): CombatSwingHandler { + return KamilCombatHandler() + } +} + +// All these combat shit is the most trash level thing to use or decipher. +class KamilCombatHandler: MultiSwingHandler( + SwitchAttack(CombatStyle.MELEE.swingHandler, null), +) { + override fun impact(entity: Entity?, victim: Entity?, state: BattleState?) { + if (victim is Player) { + // This is following RevenantCombatHandler.java, no idea if this is good. + // I can't be bothered to fix fucking frozen. The player can hit through frozen. What the fuck is frozen for then, to glue his fucking legs??? + if (RandomFunction.roll(3) && !hasTimerActive(victim, "frozen") && !hasTimerActive(victim, "frozen:immunity")) { + registerTimer(victim, spawnTimer("frozen", 7, true)) + sendMessage(victim, "You've been frozen!") + sendChat(entity as NPC, "Sallamakar Ro!") // Salad maker roll. + sendGraphics(539, victim.location) + victim.properties.combatPulse.stop() // Force the victim to stop fighting. Whatever. + // Audio? + }else { + animate(entity!!, Animation(440)) + } + } + super.impact(entity, victim, state) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/MalakDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/MalakDialogue.kt new file mode 100644 index 000000000..37ccfdc53 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/MalakDialogue.kt @@ -0,0 +1,262 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.combat.ImpactHandler.HitsplatType +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class MalakDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, MalakDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return MalakDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.MALAK_1920) + } +} + +class MalakDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4,5,6,7,8) + .npc("Away from me, dog.", "I have business to discuss with the barkeeper.") + .end() + + + b.onQuestStages(DesertTreasure.questName, 9) + .branch { player -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) == 1) { + return@branch 0 // Same branch as 0 + } + return@branch DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) + }.let { branch -> + branch.onValue(0) + .npcl("A human, eh? Give me one good reason why I should not just take you to Lord Drakan now.") + // There's a ring of charos dialogue here, but its one line and doesn't change anything... + .npcl("You had better make it a good one too, or you will not survive the night, I'll wager.") + .let { builder -> + val returnJoin = b.placeholder() + builder.goto(returnJoin) + return@let returnJoin.builder() + .options() + .let { optionBuilder -> + val continuePath = b.placeholder() + optionBuilder.option("I am here to worship Zamorak") + .playerl("I am here to worship the almighty Zamorak! Yay! Go Zamorak!") + .npcl("I see. You are a moron. You have probably settled right in with the rest of the idiots in this pathetic excuse for a village.") + .npcl("Unfortunately for you, that is not a good enough reason to explain your presence here.") + .npcl("Now tell me the reason for your coming here, or I will ensure you suffer a horrible fate indeed.") + .goto(returnJoin) + + optionBuilder.option("I am here to praise Lord Drakan") + .playerl("I am here only to serve the mighty Drakan. Yup, Drakan, he's the man.") + .npcl("I see. I would perhaps be more inclined to believe you if I could not smell the death blood of his brother Draynor upon you.") + .npcl("What are you real intentions here?") + // "If the player has not completed Vampyre Slayer" but I'm lazy again + // .npcl("Really? That is interesting, that you would want to give your life by tresspassing in this land for such an unbelievable reason.") + // .npcl("Now speak, what is your purpose in coming here?") + .goto(returnJoin) + + optionBuilder.option("I am here to worship you, oh mighty Malak") + .playerl("I am here only to serve the mighty Drakan.") + .playerl("I came here looking for you, oh mighty Malak, so that I might serve your glory.") + .npcl("Please. Do not think that I am so vain and foolish as to allow you to avoid my question with such obvious sycophancy.") + .npcl("Now tell me the reason behind your being here, or I will ensure that you suffer.") + .goto(returnJoin) + + optionBuilder.option("I am here to kill Lord Drakan") + .playerl("I am here to kill Lord Drakan, and every stinking one of his vampyre brood!") + .npcl("Hah! Most entertaining, human!") + .npcl("Now tell me the reason you are here, or we shall soon see who will be killing whom.") + .goto(returnJoin) + + optionBuilder.option("I am looking for a special Diamond...") + .playerl("I am here looking for a special diamond... I have reason to believe it is somewhere in this vicinity, and it is probably in the possession of a warrior of Zamorak.") + .playerl("I'm fairly sure it will have some kind of magical aura or something too. I don't suppose you've seen it, or know where it might be?") + .npcl("Interesting... Well perhaps we can come to a little... arrangement, human.") + .npcl("I may have information that may assist you, but you in turn will have to do something for me. What do you say? Do you think we could come to some form of") + .npcl("agreement?") + .playerl("Well, what kind of something? No offence, but you're not exactly the trustworthy type...") + .npcl("Ah, you have a healthy sense of paranoia, I see. It is not a particularly unfair request on my part...") + .npcl("All I ask is that you ensure that the current owner of the diamond is killed. For my part, I will let you know his whereabouts, and how exactly to kill him.") + .npcl("When he is dead, you may take the diamond from his corpse and do with it what you will. I have no interest in such baubles.") + .npcl("So what say you? A life for a diamond. As a mark of good faith, I will give you some information free:") + .npcl("The current owner of this diamond is named Dessous.") + .betweenStage { df, player, _, _ -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) == 0) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeBloodStage, 1) + } + } + .options("Agree to this arrangement?") + .let { optionBuilder2 -> + optionBuilder2.option("Yes") + .betweenStage { df, player, _, _ -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) == 1) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeBloodStage, 2) + } + } + .playerl("Well... I can't see any drawback. Okay, I accept your offer. Now tell me what you know.") + .goto(continuePath) + + optionBuilder2.option("No") + .playerl("I don't trust you, or anything you say. I'm afraid I have to decline.") + .npcl("As you wish human. I doubt anybody near here knows of the diamond you seek, however.") + .npcl("If you wish to claim it as your own, you have little choice but to accept my bargain. I will wait here until such time as you change your mind.") + .end() + } + return@let continuePath.builder() + } + } + .npcl("What I know? Hah! After you have been alive for as long as I, the things I know are enough to fill a library.") + .npcl("I'm afraid you will need to be a little more specific.") + .let { builder -> + val returnJoin = b.placeholder() + builder.goto(returnJoin) + returnJoin.builder() + .options() + .let { optionBuilder -> + optionBuilder.option("Why do you want Dessous dead?") + .playerl("I don't see exactly how this bargain benefits you... Why exactly do you want Dessous killed anyway?") + .npcl("That is an impertinent question to demand from myself.") + .npcl("However, if it will help seal our deal, I will let you know some of the details.") + .npcl("As you may or may not know, myself and my blood kin are the rulers of this land, all serving under Lord Drakan. However, we tend not to die of old age or similar") + .npcl("natural causes, which means that to gain another Lords tithe or land, there often need to be...") + .npcl("Unnatural causes of death involved. Let us just say, that Dessous is in control of some land that I myself would like some say in, and that it is not in my interest to be seen to be responsible for the") + .npcl("death of a fellow Lord.") + .npcl("It would however be extremely advantageous to myself should some random human adventurer take it upon themself to remove this rival for me... Do you understand?") + .playerl("Yes... I think so...") + .npcl("Good, we understand each other then. We will both benefit from the death of Dessous.") + .goto(returnJoin) + + optionBuilder.option("Where can I find Dessous?") + .playerl("Where can I find this Dessous?") + .npcl("He currently resides in a graveyard to the South-East of here. You will not be able to move the gravestone which he lies beneath however, you will need to find some way to") + .npcl("lure him out from his tomb.") + .playerl("And how exactly would I go about doing that?") + .npcl("Well, he is a vampyre, so fresh blood would almost certainly entice him out.") + .npcl("However, even though he is a frail and decrepit example of our species, he will be able to kill a weakling human such as yourself extremely easily. Having him in a bloodlust as he does so, will not make") + .npcl("your job any easier.") + .goto(returnJoin) + + optionBuilder.option("How can I kill Dessous?") + .playerl("So what advice can you give me on killing Dessous?") + .npcl("As ancient and weak as Dessous is, he is still more than a match for the likes of you.") + .npcl("That is, assuming you were to fight him fairly.") + .npcl("My proposal would be for you to even the odds up a little bit...") + .playerl("How would I go about doing that?") + .npcl("Well, my plan would be as follows. First, take a silver bar to the man living in the sewers in Draynor. He was an assistant to Count Draynor in some of his...") + .npcl("more interesting experiments many years past. Tell him you need a sacrificial offering pot. He will know what you speak of, it is a unique type of container used in various ancient vampyric ceremonies.") + .npcl("Then take the pot to Entrana and get it blessed by the Head Monk. This will lend the pot some holy power.") + .npcl("If you then bring that silver pot back to me, I will provide you with some fresh blood, to put into it. To that pot of blood, you will add some crushed garlic, and some spice to disguise the smell.") + .npcl("Use that pot of blood upon Dessous' tomb, and he will be unable to resist rising and drinking from it.") + .npcl("The combination of garlic, silver, and blessings from Saradomin will act upon him as a poison, and allow you to kill him.") + .npcl("This is just my suggestion of course, you may ignore it if you wish, although I offer no guarantees of your ability to defeat him otherwise.") + .npcl("Was there anything else you wanted?") + .goto(returnJoin) + + optionBuilder.option("Actually, I don't need to know anything.") + .playerl("Never mind, I will figure out all I need to know by myself.") + .npcl("As you wish. Come and see me when you have managed to kill Dessous.") + .end() + } + } + + branch.onValue(2) + .branch { player -> + return@branch if(inInventory(player, Items.BLESSED_POT_4659) || inInventory(player, Items.SILVER_POT_4658)) { 1 } else { 0} + }.let { branch2 -> + branch2.onValue(1) + .player("I found Ruantun in Draynors sewers.", "He made me this pot, now where can I get some fresh", "blood to fill it with?") + .betweenStage { df, player, _, _ -> + sendMessage(player, "Malak cuts you and pours some of your blood into the pot.") + if (removeItem(player, Items.SILVER_POT_4658)) { + addItemOrDrop(player, Items.SILVER_POT_4660) + } else if (removeItem(player, Items.BLESSED_POT_4659)) { + addItemOrDrop(player, Items.BLESSED_POT_4661) + } + animate(npc!!, 1264) + player.impactHandler.manualHit(player, 5, HitsplatType.NORMAL) + } + .linel("Malak cuts you and pours some of your blood into the pot.") // Supposed to be a sendMessage not a dialogue, but why... + .playerl("Ow!") + .npcl("There you go. As fresh as it gets.") + .playerl("Thanks for nothing.") + .npcl("Come and speak to me again when you have managed to kill Dessous.") + .end() + + branch2.onValue(0) + .npcl("Why are you still here? I notice Dessous still lives.") + .options() + .let { optionBuilder -> + optionBuilder.option("Where can I find Dessous?") + .playerl("Where can I find this Dessous?") + .npcl("He currently resides in a graveyard to the South-East of here. You will not be able to move the gravestone which he lies beneath however, you will need to find some way to") + .npcl("lure him out from his tomb.") + .playerl("And how exactly would I go about doing that?") + .npcl("Come and see my when you have prepared a silver ritual pot in the manner I have told you.") + .npcl("I will ensure that you get some fresh blood that you may taint with garlic and spices, to lure our Dessous.") + .end() + + optionBuilder.option("How do I kill Dessous again?") + .playerl("How am I supposed to kill Dessous again?") + .npcl("Take a silver bar to the man in the Draynor sewers. He will fashion a ritualistic pot for you, which you should then take to Entrana and get blessed.") + .npcl("When you have done that, come back here and speak to me, I will provide you with some fresh blood which you will then crush some garlic into, and then add some spices to hide the garlic.") + .npcl("In this way, you will be able to lure him from his tomb and he should be sufficiently weakened to be vulnerable to your attacks.") + .end() + + optionBuilder.option("Actually, I don't need to know anything.") + .playerl("Never mind, I will figure out all I need to know by myself.") + .npcl("As you wish. Come and see me when you have managed to kill Dessous.") + .end() + } + } + + branch.onValue(3) + .npcl("Ah, the wandering hero returns! I take it you have dispatched poor old Dessous for me?") + .playerl("Quit playing games with me, Malak. I want that diamond, and I want it now!") + .betweenStage { df, player, _, _ -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeBloodStage) == 3) { + addItemOrDrop(player, Items.BLOOD_DIAMOND_4670) + DesertTreasure.setSubStage(player, DesertTreasure.attributeBloodStage, 100) + } + } + .npcl("Do not take that tone of voice with me, meat. You should be thankful I have allowed you your life.") + .npcl("Here, take your precious little bauble.") + .npcl("I will take that silver pot from you as well, humans are not meant to possess such artefacts. Now get out of my sight, our deal is complete, and if I see you here again I will not hesistate to take you to") + .npcl("Lord Drakan.") + .npcl("He will be extremely pleased to meet the murderer of poor Dessous, I suspect.") + .end() + + branch.onValue(100) + .branch { player -> + return@branch if(!inInventory(player, Items.BLOOD_DIAMOND_4670)) { 1 } else { 0 } + }.let { branch2 -> + branch2.onValue(1) + .playerl("Where is the Diamond of Blood? I know you have it!") + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.BLOOD_DIAMOND_4670) + } + .npcl("Do not take that tone of voice with me, meat. Here, take your bauble. I have no use for it.") + .end() + + branch2.onValue(0) + .npcl("Be lucky I have let you live, meat. Our deal is done, I wish no further dealing with you.") + .end() + + } + } + + b.onQuestStages(DesertTreasure.questName, 10,11,12,13,100) + .npcl("Be lucky I have let you live, meat. Our deal is done, I wish no further dealing with you.") + .end() + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt b/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt new file mode 100644 index 000000000..ab45baf12 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt @@ -0,0 +1,314 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Direction +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import core.tools.RandomFunction +import org.rs09.consts.Components +import org.rs09.consts.NPCs + +class PyramidArea { + companion object { + /** All The Sarcophagus Locations */ + val sarcophagusList = arrayOf( + // Level 1 + Location(2901, 4946, 3), + Location(2902, 4969, 3), + Location(2903, 4961, 3), + Location(2909, 4954, 3), + Location(2913, 4950, 3), + Location(2916, 4954, 3), + Location(2917, 4951, 3), + Location(2917, 4959, 3), + Location(2918, 4963, 3), + // Level 2 + Location(2831, 4962, 2), + Location(2837, 4970, 2), + Location(2843, 4964, 2), + Location(2847, 4947, 2), + Location(2858, 4956, 2), + Location(2858, 4973, 2), + Location(2864, 4942, 2), + Location(2868, 4948, 2), + Location(2869, 4968, 2), + // Level 3 + Location(2759, 4962, 1), + Location(2760, 4956, 1), + Location(2763, 4966, 1), + Location(2764, 4941, 1), + Location(2765, 4936, 1), + Location(2765, 4940, 1), + Location(2767, 4945, 1), + Location(2768, 4947, 1), + Location(2771, 4944, 1), + Location(2774, 4947, 1), + Location(2776, 4941, 1), + Location(2786, 4974, 1), + Location(2787, 4964, 1), + Location(2790, 4968, 1), + Location(2791, 4977, 1), + Location(2798, 4947, 1), + Location(2798, 4952, 1), + Location(2800, 4960, 1), + Location(2802, 4940, 1), + Location(2806, 4936, 1), + Location(2806, 4942, 1), + Location(2810, 4968, 1), + Location(2810, 4975, 1), + // Level 4 + Location(3208, 9315, 0), + Location(3211, 9330, 0), + Location(3217, 9295, 0), + Location(3218, 9281, 0), + Location(3221, 9313, 0), + Location(3221, 9320, 0), + Location(3221, 9324, 0), + Location(3222, 9281, 0), + Location(3225, 9308, 0), + Location(3225, 9310, 0), + Location(3226, 9312, 0), + Location(3226, 9318, 0), + Location(3227, 9288, 0), + Location(3229, 9309, 0), + Location(3231, 9297, 0), + Location(3233, 9309, 0), + Location(3234, 9297, 0), + Location(3234, 9330, 0), + Location(3236, 9302, 0), + Location(3237, 9309, 0), + Location(3240, 9312, 0), + Location(3240, 9318, 0), + Location(3241, 9282, 0), + Location(3242, 9302, 0), + Location(3246, 9282, 0), + Location(3246, 9308, 0), + Location(3246, 9324, 0), + Location(3247, 9323, 0), + Location(3249, 9293, 0), + Location(3250, 9324, 0), + Location(3251, 9323, 0), + Location(3251, 9330, 0), + Location(3251, 9337, 0), + Location(3252, 9330, 0), + Location(3252, 9337, 0), + Location(3253, 9301, 0), + Location(3254, 9324, 0), + Location(3255, 9323, 0), + Location(3255, 9330, 0), + Location(3255, 9337, 0), + Location(3256, 9330, 0), + Location(3256, 9337, 0), + Location(3257, 9289, 0), + Location(3259, 9310, 0), + Location(3259, 9313, 0), + ) + + val safeZone = ZoneBorders(3227, 3239, 9310, 9320) + + // Direction.NORTH - LEFT + // rot 0 - LEFT + // rot 1 - NORTH + // rot 2 - RIGHT + // rot 3 - SOUTH + /** Sarcophagus Opening Location (Note, they are all wrongly mapped due to Scenery) */ + fun getNewLocation(direction: Direction): Location { + return when (direction) { + Direction.NORTH -> Location(-1, 0) + Direction.WEST -> Location(0, -1) + Direction.EAST -> Location(0, 1) + Direction.SOUTH -> Location(1, 0) + else -> Location(0, 0) + } + } + + /** Sarcophagus Opening Facing (Note, they are all wrongly mapped due to Scenery) */ + fun getNewFacing(direction: Direction): Direction { + return when (direction) { + Direction.NORTH -> Direction.NORTH + Direction.WEST -> Direction.NORTH_WEST + Direction.SOUTH -> Direction.WEST + Direction.EAST -> Direction.NORTH_EAST + else -> direction + } + } + + fun nearSarcophagus(loc: Location): Location? { + for (sarcoph in sarcophagusList) { + if(loc.withinDistance(sarcoph, 3)) { + return sarcoph + } + } + return null + } + + /** Trapdoor randomly throws you out of the Pyramid. */ + fun trapdoorTrap(player: Player) { + stopWalk(player) + lock(player, 8) + sendMessage(player, "You accidentally trigger a trap...") + // addScenery(6521, location) -> animateScenery(scenery, 1939), but 6522 does it for you. + val pitfallScenery = addScenery(6522, player.location) // Scenery - Trapdoor Scenery + animate(player, 1950) // Anim - Player Falling Animation + queueScript(player, 4, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendGraphics(354, player.location) // Gfx - Puff of Smoke + closeOverlay(player) + openOverlay(player, Components.FADE_TO_BLACK_120) + return@queueScript delayScript(player, 2) + } + 1 -> { + removeScenery(pitfallScenery) + teleport(player, Location(3233, 2887, 0)) + sendMessage(player, "...and tumble unharmed outside the pyramid.") + closeOverlay(player) + openOverlay(player, Components.FADE_FROM_BLACK_170) + // animate(player, ??) // Anim - Player Getting Up https://www.youtube.com/watch?v=95OvIPFYCwg + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + + /** Mummies randomly spawns out of a sarcophagus. */ + fun spawnMummy(player: Player, sarcophagusLocation: Location) { + stopWalk(player) + lock(player, 3) + val sarcophagusScenery = getScenery(sarcophagusLocation) ?: return + val locationInFront = sarcophagusScenery.location.transform(getNewLocation(sarcophagusScenery.direction)) + // There are 6 sarcophagus, 6512 - 6517 with different door designs. + // They map nicely to 6506 - 6511 and act like a door. + // 6505 is the underlying hole scenery after the door opens, but it is done for you. + replaceScenery( + sarcophagusScenery, + sarcophagusScenery.id - 6, + 5, + getNewFacing(sarcophagusScenery.direction), + locationInFront + ) + val mummyNpc = NPC(NPCs.MUMMY_1958) + mummyNpc.isRespawn = false + mummyNpc.isWalks = false + mummyNpc.isAggressive = true + mummyNpc.location = sarcophagusScenery.location + mummyNpc.init() + mummyNpc.walkingQueue.addPath(locationInFront.x, locationInFront.y) + sendChat(mummyNpc, "Rawr!") + stopWalk(player) + queueScript(player, 2, QueueStrength.SOFT) { stage -> + stopWalk(player) + mummyNpc.walkingQueue.addPath(locationInFront.x, locationInFront.y) + mummyNpc.isWalks = true + mummyNpc.isAggressive = true + mummyNpc.attack(player) + return@queueScript stopExecuting(player) + } + + } + + /** Scarabs randomly spawns somewhere near you. */ + fun spawnScarabs(player: Player) { + stopWalk(player) + lock(player, 3) + val scarabsLocation = Location.getRandomLocation(player.location, 3, true) + sendGraphics(356, scarabsLocation) // Gfx - Cracks before scarab appears. + val scarabNpc = NPC(NPCs.SCARABS_1969) + stopWalk(player) + queueScript(player, 2, QueueStrength.STRONG) { stage -> + stopWalk(player) + when (stage) { + 0 -> { + scarabNpc.isRespawn = false + scarabNpc.isWalks = false + scarabNpc.location = scarabsLocation + scarabNpc.init() + animate(scarabNpc, 1949) // Anim - Scarabs appearing from ground. + return@queueScript delayScript(player, 3) + } + 1 -> { + scarabNpc.isWalks = true + scarabNpc.isAggressive = true + scarabNpc.attack(player) + return@queueScript stopExecuting(player) + } + } + return@queueScript stopExecuting(player) + } + } + } +} + +class PyramidAreaFirstThree: MapArea { + + override fun defineAreaBorders(): Array { + return arrayOf( + getRegionBorders(11597), + getRegionBorders(11341), + getRegionBorders(11085), + getRegionBorders(12945), + ) + } + + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + + if (!PyramidArea.safeZone.insideBorder(entity.location)) { // Safezone is talking to Azzanadra. + val averageLevel = ( + getDynLevel(entity, Skills.AGILITY) + + getDynLevel(entity, Skills.THIEVING) + ) / 2 + val randomValue = RandomFunction.randomDouble(99.5) + + if ((1..10).random() == 1) { + // A mummy would jump out if you walk near a sarcophagus of 2 radius. + val sarcoph = PyramidArea.nearSarcophagus(entity.location) + if (sarcoph != null) { + PyramidArea.spawnMummy(entity, sarcoph) + } + } + + if ((1..60).random() == 1) { + PyramidArea.spawnScarabs(entity) + } + if (randomValue > averageLevel) { + PyramidArea.trapdoorTrap(entity) + } + } + } + } +} + +class PyramidAreaFinal: MapArea { + + override fun defineAreaBorders(): Array { + return arrayOf( + getRegionBorders(12945), + ) + } + + override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { + if (entity is Player) { + + if ((1..30).random() == 1) { + PyramidArea.spawnScarabs(entity) + } + + if ((1..15).random() == 1) { + // A mummy would jump out if you walk near a sarcophagus of 2 radius. + val sarcoph = PyramidArea.nearSarcophagus(entity.location) + if (sarcoph != null) { + PyramidArea.spawnMummy(entity, sarcoph) + } + } + + // No Trapdoor For The Final Level + } + } +} diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/RasoloDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/RasoloDialogue.kt new file mode 100644 index 000000000..273dd5d34 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/RasoloDialogue.kt @@ -0,0 +1,217 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +@Initializable +class RasoloDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, RasoloDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return RasoloDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.RASOLO_1972) + } +} + +class RasoloDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4,5,6,7,8) + .npc("Greetings friend.", "I am Rasolo, the famous merchant.", "Would you care to see my wares?") + .options() + .let { optionBuilder -> + optionBuilder.option("Yes") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + optionBuilder.option("No") + .playerl("No, not really.") + .npcl("As you wish. I will travel wherever the business takes me.") + .end() + } + + b.onPredicate { player -> + DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 0 && + getQuestStage(player, DesertTreasure.questName) >= 9 + } + .npc("Greetings friend.", "I am Rasolo, the famous merchant.", "Would you care to see my wares?") + .options() + .let { optionBuilder -> + optionBuilder.option("Yes") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + optionBuilder.option("No") + .playerl("No, not really.") + .npcl("As you wish. I will travel wherever the business takes me.") + .end() + + optionBuilder.option("Ask about the Diamonds of Azzanadra") + .playerl("No, actually I was looking for something specific...") + .npcl("Hmmmm? And what would that be?") + .playerl("I am looking for one of the Diamonds of Azzanadra. I have reason to believe it may be somewhere around here...") + .npcl("Ahhh... The Shadow Diamond...") + .npcl("I know the object of which you speak. It is guarded by a fearsome warrior known as Damis, they say, who lives in the shadows, invisible to prying eyes...") + .playerl("How can I find this 'Damis' then?") + .npcl("Well now... perhaps we can help each other out here.") + .npcl("I have in my possession a small trinket, a ring, that allows its wearer to see the unseen...") + .playerl("How much do you want for it?") + .npcl("Ah, but it is not for sale... As such...") + .npcl("I am offering to trade it for an item that was rightfully mine, but that was stolen by a bandit named Laheeb.") + .npcl("The item is question is a gilded cross, that has some sentimental value to myself. I wish for you to recover this item for me, and I will happily let you have my ring of visibility.") + .playerl("Where can I find this Laheeb?") + .npcl("Well, as a travelling merchant I have roamed these lands for many years...") + .npcl("To the far east of here there is an area that is dry and barren like the desert... it is called...") + .playerl("Al Kharid?") + .npcl("...Yes, Al Kharid. Now to the south of Al Kharid there is a passageway, it is called the...") + .playerl("Shantay Pass.") + .npcl("...Yes. I didn't realise you had travelled there yourself.") + .npcl("Anyway, when you have gone through the Shantay Pass, you will find yourself in a hostile desert... You will need to bring water with you to keep your life. Now, to the south-west of this pass, you will find a small") + .npcl("village...") + .playerl("The Bedabin camp.") + .npcl(FacialExpression.ANNOYED, "If you know where Laheeb lives, why did you ask me?") + .playerl("I don't. Sorry, please continue.") + .npcl("Well, okay then. Anyway, south of this encampment there is an area where few have ever been... It is a village of murderous bandits, and treacherous") + .npcl("thieves... This is where Laheeb makes his home.") + .npcl("He will have hidden his stolen treasure somewhere in that village, I am sure of it. When you find his loot, you will find my gilded cross. Return it to me, and I will reward you with my ring") + .npcl("of visibility, so that you may find Damis. Does this seem fair to you?") + .options() + .let { optionBuilder2 -> + optionBuilder2.option("Yes") + .playerl("Not a problem. I'll be back with your cross before you know it.") + .endWith { _, player -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 0) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeShadowStage, 1) + } + } + optionBuilder2.option("No") + .playerl("Sounds like too much effort to me. I'll find this Damis by myself.") + .npcl("As you wish.") + .end() + } + } + + b.onPredicate { player -> + DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) in 1 .. 2 && + getQuestStage(player, DesertTreasure.questName) >= 9 + } + .npcl("Have you retrieved my gilded cross for me yet?") + .branch { player -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 2 && inInventory(player, Items.GILDED_CROSS_4674)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(0) + .playerl("No, not yet...") + .npcl("Well what seems to be the problem?") + .options() + .let { optionBuilder -> + optionBuilder.option("Where can I find Laheeb?") + .playerl("Where can I find this Laheeb?") + .npcl("Well, as a travelling merchant I have roamed these lands for many years...") + .npcl("To the far east of here there is an area that is dry and barren like the desert... it is called...") + .playerl("Al Kharid?") + .npcl("...Yes, Al Kharid. Now to the south of Al Kharid there is a passageway, it is called the...") + .playerl("Shantay Pass.") + .npcl("...Yes. I didn't realise you had travelled there yourself.") + .npcl("Anyway, when you have gone through the Shantay Pass, you will find yourself in a hostile desert... You will need to bring water with you to keep your life. Now, to the south-west of this pass, you will find a small") + .npcl("village...") + .playerl("The Bedabin camp.") + .npcl("If you know where Laheeb lives, why did you ask me?") + .playerl("I don't. Sorry, please continue.") + .npcl("Well, okay then. Anyway, south of this encampment there is an area where few have ever been... It is a village of murderous bandits, and treacherous") + .npcl("thieves... This is where Laheeb makes his home.") + .end() + optionBuilder.option("Can't I just buy your ring?") + .playerl("Can't I just buy your ring?") + .npcl("No, it is not for sale. Some things are more important than money, and the return of my gilded cross is one of them.") + .end() + optionBuilder.option("Is Damis near here, then?") + .playerl("Is Damis near here, then?") + .npcl("You would be surprised to know just how close he is...") + .end() + } + branch.onValue(1) + .playerl("Yes I have!") + .npcl("Excellent, excellent. Here, take this ring. While you wear it, you will be able to see the things that live in shadows...") + .npcl("And you will be able to find the entrance to Damis' lair.") + .endWith { _, player -> + if (removeItem(player, Items.GILDED_CROSS_4674)) { + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 2) { + addItemOrDrop(player, Items.RING_OF_VISIBILITY_4657) + DesertTreasure.setSubStage(player, DesertTreasure.attributeShadowStage, 3) + } + } + } + } + + b.onPredicate { player -> + DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) == 3 && + getQuestStage(player, DesertTreasure.questName) >= 9 + } + .npcl("So how goes your quest? Did you managed to find the Diamond you were looking for yet?") + .branch { player -> + if (inInventory(player, Items.RING_OF_VISIBILITY_4657)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .playerl("Not yet...") + .npcl("Well, his lair is very close to here. I suggest you look around for it.") + .end() + + branch.onValue(0) + .playerl("I lost that ring you gave me...") + .npcl("Then by all means, take another. Only a foolish merchant would give away his only stock!") + .endWith { _, player -> + addItem(player, Items.RING_OF_VISIBILITY_4657) + } + } + + + b.onPredicate { player -> + DesertTreasure.getSubStage(player, DesertTreasure.attributeShadowStage) > 3 && + getQuestStage(player, DesertTreasure.questName) >= 9 || getQuestStage(player, DesertTreasure.questName) >= 10 + } + .npcl("Many thanks for returning my heirloom to me, adventurer. Would you like to buy something?") + .options() + .let { optionBuilder -> + optionBuilder.option("Yes") + .endWith { _, player -> + openNpcShop(player, npc!!.id) + } + optionBuilder.option("No") + .playerl("No, not really.") + .npcl("As you wish. I will travel wherever the business takes me.") + .end() + + optionBuilder.optionIf("I lost that ring you gave me...") { player -> + return@optionIf !inInventory(player, Items.RING_OF_VISIBILITY_4657) + } + .playerl("I lost that ring you gave me...") + .npcl("Then by all means, take another. Only a foolish merchant would give away his only stock!") + .endWith { _, player -> + addItem(player, Items.RING_OF_VISIBILITY_4657) + } + } + + } +} + +class RasoloTradeListeners : InteractionListener { + override fun defineListeners() { + on(NPCs.RASOLO_1972, NPC, "trade") { player, node -> + openNpcShop(player, node.id) + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/RuantunDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/RuantunDialogue.kt new file mode 100644 index 000000000..89fa635f7 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/RuantunDialogue.kt @@ -0,0 +1,83 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class RuantunDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, RuantunDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return RuantunDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.RUANTUN_1916) + } +} + +class RuantunDialogueFile : DialogueBuilderFile() { + override fun create(b: DialogueBuilder) { + + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4,5,6,7,8) + .playerl("Hello.") + .npcl(FacialExpression.OLD_NORMAL, "You ssshould not be down here...") + .options() + .let { optionBuilder -> + optionBuilder.option("Who are you?") + .playerl("Who are you?") + .npcl(FacialExpression.OLD_NORMAL, "My name isss unimportant... I live only to ssserve my massster.") + .playerl("Um... Okay then.") + .end() + + optionBuilder.option("Why are you down here?") + .playerl("Why are you down here?") + .npcl(FacialExpression.OLD_NORMAL, "Thisss isss where I belong... Beingsss sssuch as myssself cannot abide in the light... It is in the darknesss where we find our homesss...") + .playerl("Uh... Okay then.") + .end() + + optionBuilder.option("Can I use your anvil?") + .playerl("Can I use your anvil?") + .npcl(FacialExpression.OLD_NORMAL, "Of courssse you may... I have very little ussse for it nowadaysss...") + .playerl("Uh... Thanks, I guess.") + .end() + } + + b.onQuestStages(DesertTreasure.questName, 9, 10, 100) + // Technically should happen after talking to Malak, but nah. + .playerl("Hello.") + .npcl(FacialExpression.OLD_NORMAL, "You sshould not be down here...") + .playerl("Are you an assistant to Count Draynor?") + .npc(FacialExpression.OLD_NORMAL, "I usssed to have that honour...", "Why do you ssseek me?") + .branch { player -> + return@branch if (inInventory(player, Items.SILVER_BAR_2355)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .playerl("I have a silver bar with me, I was wondering if you could make it into a 'sacrificial offering pot' for me?") + .betweenStage { df, player, _, _ -> + if (removeItem(player, Items.SILVER_BAR_2355)) { + addItemOrDrop(player, Items.SILVER_POT_4658) + } + } + .npc(FacialExpression.OLD_NORMAL, "Yesss, of courssse...", "There you are, put it to good usssse...") + .end() + + branch.onValue(0) + .playerl("I understand that you can make me a 'sacrificial offering pot' if I bring you a bar of silver?") + .npcl(FacialExpression.OLD_NORMAL, "And where did you hear thisss?") + .playerl("It was from Malak in Canifis.") + .npc(FacialExpression.OLD_NORMAL, "Ah, I sssee...", "Yesss, I know how to make sssuch an item...", "It has been many yearsss sssince I have needed to however...") + .npcl(FacialExpression.OLD_NORMAL, "It is not my wisssh to quessstion your desssire for sssuch an item, I wasss merely sssurprisssed that one sssuch as you would make sssuch a requessst...") + .npcl(FacialExpression.OLD_NORMAL, "I will happily make you thisss pot, but you mussst bring me a bar of sssilver... Alasss, I can no longer collect my own ingredientsss, and mussst remain here...") + .end() + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/TranslationBook.kt b/Server/src/main/content/region/desert/quest/deserttreasure/TranslationBook.kt new file mode 100644 index 000000000..b9ff24e33 --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/TranslationBook.kt @@ -0,0 +1,185 @@ +package content.region.desert.quest.deserttreasure + +import content.global.handlers.iface.BookInterface +import content.global.handlers.iface.BookLine +import content.global.handlers.iface.Page +import content.global.handlers.iface.PageSet +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.player.Player +import org.rs09.consts.Items + +class TranslationBook : InteractionListener { + + companion object { + private val TITLE = "Translation Primer" + private val CONTENTS = arrayOf( + PageSet( + Page( + BookLine("This is a rough", 55), + BookLine("translation of the stone", 56), + BookLine("tablet brought to me by", 57), + BookLine("courier earlier today.", 58), + BookLine("", 59), + BookLine("", 60), + BookLine("The cuneiforms of this", 61), + BookLine("particular tablet are far", 62), + BookLine("different to anything I", 63), + BookLine("have previously seen in", 64), + BookLine("my career as an", 65) + ), + Page( + BookLine("archaeological expert.", 66), + BookLine("", 67), + BookLine("Where possible I have", 68), + BookLine("given as accurate a", 69), + BookLine("translation as possible, but", 70), + BookLine("some of the words I have", 71), + BookLine("attempted to translate", 72), + BookLine("hold different meanings", 73), + BookLine("depending upon their", 74), + BookLine("intonation and context;", 75), + BookLine("Due to my unfamiliarity", 76) + ) + ), + PageSet( + Page( + BookLine("with this language, I have", 55), + BookLine("given possible translations", 56), + BookLine("for these words wherever", 57), + BookLine("I have encountered them.", 58), + BookLine("Wherever I have a word", 59), + BookLine("n brackets, it is a word", 60), + BookLine("which has many meanings", 61), + BookLine("depending on the context,", 62), + BookLine("although the general", 63), + BookLine("meaning should be clear", 64), + BookLine("to even a casual study.", 65) + ), + Page( + BookLine("", 66), + BookLine("", 67), + BookLine("Hopefully this translation", 68), + BookLine("will help you in your", 69), + BookLine("excavations Asgarnia, and", 70), + BookLine("as usual I look forward", 71), + BookLine("to seeing what relics you", 72), + BookLine("bring back to the", 73), + BookLine("Museum of Varrock this", 74), + BookLine("time!", 75), + BookLine("Your friend, as always,", 76) + ), + ), + PageSet( + Page( + BookLine("Terry Balando", 55), + BookLine("", 56), + BookLine("", 57), + BookLine("", 58), + BookLine("", 59), + BookLine("", 60), + BookLine("", 61), + BookLine("", 62), + BookLine("", 63), + BookLine("", 64), + BookLine("", 65) + ), + Page( + BookLine("Translation follows:", 66), + BookLine("", 67), + BookLine("", 68), + BookLine("(There are some missing", 69), + BookLine("sentence fragments here,", 70), + BookLine("presumably from a stone", 71), + BookLine("tablet preceding this one", 72), + BookLine("which you have not yet", 73), + BookLine("discovered)", 74), + BookLine("", 75), + BookLine("...the permanent", 76) + ) + ), + PageSet( + Page( + BookLine("(exile/journey) of the", 55), + BookLine("people ended.", 56), + BookLine("And so it came to pass,", 57), + BookLine("that deep in the", 58), + BookLine("(fiery/uncomfortable)", 59), + BookLine("desert, the gods", 60), + BookLine("(argued/decided) amongst", 61), + BookLine("themselves that the", 62), + BookLine("(fortress/home) would be", 63), + BookLine("the (selected/chosen) place", 64), + BookLine("that would", 65) + ), + Page( + BookLine("(imprison/conceal) the", 66), + BookLine("(wealth/power).", 67), + BookLine("Thus (guarded/protected)", 68), + BookLine("by the (unusually archaic", 69), + BookLine("word here, I believe it", 70), + BookLine("means either the sick or", 71), + BookLine("the dead depending on", 72), + BookLine("context) and", 73), + BookLine("(defended/trapped) by the", 74), + BookLine("(diamonds/crystals) of", 75), + BookLine("(this word is", 76) + ) + ), + PageSet( + Page( + BookLine("untranslatable). So it was", 55), + BookLine("that the gods left the four", 56), + BookLine("(diamonds/crystals) as the", 57), + BookLine("(key/secret).", 58), + BookLine("(Guarded/Protected) by", 59), + BookLine("the (again, this word has", 60), + BookLine("no modern equivalent)", 61), + BookLine("and held by the", 62), + BookLine("(worthy/strong) so that", 63), + BookLine("the (wealth/power) might", 64), + BookLine("forever be", 65) + ), + Page( + BookLine("(imprisoned/concealed).", 66), + BookLine("", 67), + BookLine("", 68), + BookLine("", 69), + BookLine("", 70), + BookLine("", 71), + BookLine("", 72), + BookLine("", 73), + BookLine("", 74), + BookLine("", 75), + BookLine("", 76) + ) + ), + PageSet( + Page( + BookLine("There seems to be some", 55), + BookLine("further missing", 56), + BookLine("information continued", 57), + BookLine("onto a further tablet, but", 58), + BookLine("from this preliminary", 59), + BookLine("translation I think you", 60), + BookLine("may be onto something", 61), + BookLine("very big indeed!", 62), + BookLine("", 63), + BookLine("", 64), + BookLine("", 65) + ), + ), + ) + fun display(player: Player, pageNum: Int, buttonID: Int) : Boolean { + BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS) + return true + } + } + + override fun defineListeners() { + on(Items.TRANSLATION_4655, IntType.ITEM, "read") { player, _ -> + BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display) + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/TrollChildDialogue.kt b/Server/src/main/content/region/desert/quest/deserttreasure/TrollChildDialogue.kt new file mode 100644 index 000000000..24cedf3ef --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/TrollChildDialogue.kt @@ -0,0 +1,142 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.dialogue.DialogueBuilder +import core.game.dialogue.DialogueBuilderFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.node.entity.player.Player +import core.plugin.Initializable +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class TrollChildDialogue(player: Player? = null) : DialoguePlugin(player){ + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player!!, TrollChildDialogueFile(), npc) + return false + } + override fun newInstance(player: Player?): DialoguePlugin { + return TrollChildDialogue(player) + } + override fun getIds(): IntArray { + // NPCs.BANDIT_1932 is wrong, should be NPCs.TROLL_CHILD_1932 + // NPCs.TROLL_CHILD_1933, NPCs.TROLL_CHILD_1934 are varbit controlled 1932 instances. + return intArrayOf(NPCs.BANDIT_1932) + } +} +class TrollChildDialogueFile : DialogueBuilderFile() { + + companion object { + fun dialogueBeforeQuestCrying(builder: DialogueBuilder): DialogueBuilder { + // From https://youtu.be/AJaHuCuxfFg 15:19 + return builder + .playerl("Hello there.") + .line("The troll child is crying to itself.", "It is ignoring you completely.") + } + fun dialogueStillCrying(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Hello there.") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"Waaaaaaa!") + .line("This troll seems very upset about something.", "Maybe some sweet food would take his mind off things?") + } + fun dialogueStoppedCrying(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Hello there.") + .npc(FacialExpression.OLD_SAD,"-sniff-","H-hello there.") + .playerl("Why so sad, little troll?") + .npc(FacialExpression.OLD_NEARLY_CRYING,"It was the bad man!", "He hurt my mommy and daddy!", "He made them all freezey!") + .playerl("Bad man...?") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"He said it was because they stole his diamond! But they never did! They found it, and didn't know who it belonged to!") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"My mommy always told me stealing is wrong, they would never steal from someone!") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"Then he did some wavey hand thing and my mommy and daddy got frozified!") + .playerl("A diamond you say? Listen, I think I might be able to help your parents, but I need that Diamond in return.") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"-sniff- I don't think they really wanted it anyway, they would have given it back to the bad man if he'd asked before freezifying them...") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"I give you my promise mister that if you unfreeze my mommy and daddy, you can have the stupid diamond.") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"Do we have a deal?") + } + fun dialogueYesToHelp(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Absolutely. Don't worry kid, I'll get your parents back to you safe and sound.") + } + fun dialogueNoToHelp(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("Sorry, I can't make any promises about that, and I don't think I have the time to waste trying to defrost some stupid ice trolls.") + .npcl(FacialExpression.OLD_NEARLY_CRYING,"Waaaaaaa!") + } + fun dialogueHaveYouFreedThem(builder: DialogueBuilder): DialogueBuilder { + return builder + .npcl(FacialExpression.OLD_SAD,"You didn't free my mommy and daddy yet?") + .player("Not yet...") + .npc(FacialExpression.OLD_SAD,"Please try harder!", "I love my mommy and daddy!") + } + fun dialogueThankYou(builder: DialogueBuilder): DialogueBuilder { + return builder + .npc(FacialExpression.OLD_CALM_TALK1, "Thanks for all of your help!", "I'm surprised you managed to survive the blizzard,", "being a thin skinned fleshy and all!") + .player("What can I say?", "I'm a lot tougher than I look.") + } + fun dialogueLostDiamond(builder: DialogueBuilder): DialogueBuilder { + return builder + .playerl("I lost that diamond of Ice you gave me...") + .npcl(FacialExpression.OLD_CALM_TALK1, "That's okay, it blew back on an icy wind... It's almost like it wants to stay here! Here, take it back, you've earned it.") + } + } + + override fun create(b: DialogueBuilder) { + // Dialogue Logic + b.onQuestStages(DesertTreasure.questName, 0,1,2,3,4,5,6,7,8) + .let{dialogueBeforeQuestCrying(it)} + .end() + + b.onQuestStages(DesertTreasure.questName, 9) + .branch { player -> + return@branch DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) + }.let { branch -> + // Branch on sub-stages. + branch.onValue(0) + .let{dialogueStillCrying(it)} + .end() + + branch.onValue(1) + .let{dialogueStoppedCrying(it)} + .options().let { optionBuilder -> + optionBuilder.option("Yes") + .let{dialogueYesToHelp(it)} + .endWith { _, player -> + if (DesertTreasure.getSubStage(player, DesertTreasure.attributeIceStage) == 1) { + DesertTreasure.setSubStage(player, DesertTreasure.attributeIceStage, 2) + } + } + optionBuilder.option("No") + .let{dialogueNoToHelp(it)} + .end() + } + + branch.onValue(2) + .let{dialogueHaveYouFreedThem(it)} + .end() + + branch.onValue(3) + .let{dialogueHaveYouFreedThem(it)} + .end() + + branch.onValue(4) + .let{dialogueHaveYouFreedThem(it)} + .end() + + branch.onValue(100) + .branch { player -> + return@branch if (!inInventory(player, Items.ICE_DIAMOND_4671)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .let{dialogueLostDiamond(it)} + .endWith { _, player -> + addItemOrDrop(player, Items.ICE_DIAMOND_4671) + } + branch.onValue(0) + .let{dialogueThankYou(it)} + .end() + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/ullek/handlers/UllekListeners.kt b/Server/src/main/content/region/desert/ullek/handlers/UllekListeners.kt index b654b8b27..f2b790453 100644 --- a/Server/src/main/content/region/desert/ullek/handlers/UllekListeners.kt +++ b/Server/src/main/content/region/desert/ullek/handlers/UllekListeners.kt @@ -1,8 +1,11 @@ package content.region.desert.ullek.handlers +import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener +import core.game.interaction.QueueStrength import core.game.world.map.Location +import core.game.world.update.flag.context.Animation import org.rs09.consts.Scenery class UllekListeners : InteractionListener { @@ -23,5 +26,17 @@ class UllekListeners : InteractionListener { player.properties.teleportLocation = Location.create(3419, 2803, 1) return@on true } + on(Scenery.REEDS_28474, IntType.SCENERY, "push through") { player, node -> + animate(player, 7633) + animateScenery(node as core.game.node.scenery.Scenery, 7634) + queueScript(player, animationDuration(Animation(7633)), QueueStrength.SOFT) { + val newLoc = node.location.transform(Location.getDelta(player.location, node.location)) + player.walkingQueue.reset() + player.walkingQueue.addPath(newLoc.x, newLoc.y) + + return@queueScript stopExecuting(player) + } + return@on true + } } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/handlers/RasoloNPC.java b/Server/src/main/content/region/kandarin/handlers/RasoloNPC.java deleted file mode 100644 index b75407700..000000000 --- a/Server/src/main/content/region/kandarin/handlers/RasoloNPC.java +++ /dev/null @@ -1,84 +0,0 @@ -package content.region.kandarin.handlers; - -import core.cache.def.impl.NPCDefinition; -import core.game.dialogue.DialoguePlugin; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -@Initializable -public class RasoloNPC extends OptionHandler { - @Override - public Plugin newInstance(Object arg) throws Throwable { - new RosaloDialouge().init(); - NPCDefinition.forId(1972).getHandlers().put("option:talk-to",this); - NPCDefinition.forId(1972).getHandlers().put("option:trade",this); - return null; - } - - @Override - public boolean handle(Player player, Node node, String option) { - if(option.equals("trade")){ - new NPC(1972).openShop(player); - } else { - player.getDialogueInterpreter().open(1972); - } - return false; - } - - /** - * Rasolo npc - * @author ceik - */ - - public class RosaloDialouge extends DialoguePlugin{ - public RosaloDialouge(){ - /** - * - */ - } - public RosaloDialouge(Player player){super(player);} - - @Override - public DialoguePlugin newInstance(Player player) { - return new RosaloDialouge(player); - } - - @Override - public boolean open(Object... args){ - npc("Hello, would you like to see my wares?"); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch(stage){ - case 0: - player.getDialogueInterpreter().sendOptions("Select one", "Yes, please", "No, thanks"); - stage++; - break; - case 1: - switch(buttonId){ - case 1: - end(); - new NPC(1972).openShop(player); - break; - case 2: - player("No, thanks"); - stage++; - break; - } - break; - case 2: - end(); - break; - } - return true; - } - @Override - public int[] getIds() {return new int[] {1972};} - } -} diff --git a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertDialogue.kt b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertDialogue.kt index 6672f61aa..3f4ea3d0e 100644 --- a/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/quest/thedigsite/ArchaeologicalExpertDialogue.kt @@ -1,5 +1,6 @@ package content.region.misthalin.digsite.quest.thedigsite +import content.region.desert.quest.deserttreasure.DesertTreasure import core.api.* import core.game.dialogue.DialogueBuilder import core.game.dialogue.DialogueBuilderFile @@ -8,6 +9,7 @@ import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.plugin.Initializable +import org.rs09.consts.Items @Initializable @@ -26,6 +28,64 @@ class ArchaeologicalExpertDialogue (player: Player? = null) : DialoguePlugin(pla class ArchaeologicalExpertDialogueFile : DialogueBuilderFile() { override fun create(b: DialogueBuilder) { + b.onQuestStages(DesertTreasure.questName, 4,5,6,7,8,9,10,11,12,13,14,15,100) + .npc("Hello again.", "Was that translation any use to Asgarnia?") + .playerl("I think it was, thanks!") + .end() + + b.onQuestStages(DesertTreasure.questName, 3) + .branch { player -> + return@branch if (inInventory(player, Items.TRANSLATION_4655)) { 1 } else { 0 } + }.let { branch -> + branch.onValue(1) + .npc("Hello again.", "Was that translation any use to Asgarnia?") + .playerl(FacialExpression.SUSPICIOUS, "I, uh, kind of didn't take it to him yet...") + .npc(FacialExpression.THINKING, "Whyever not?", "You're the strangest delivery @g[boy,girl] I've ever met!") + .end() + branch.onValue(0) + .playerl("I lost that translation you gave me...") + .npcl("Oh, no matter, I mostly remember what it said anyway! Here you go!") + .endWith { _, player -> + addItemOrDrop(player, Items.TRANSLATION_4655) + } + } + b.onQuestStages(DesertTreasure.questName, 2) + .betweenStage { df, player, _, _ -> + addItemOrDrop(player, Items.TRANSLATION_4655) + } + .npcl("There you go, that book contains the sum of my translating ability. If you would be so kind as to take that back to Asgarnia, I think it will reassure him that he is on the") + .npcl("right track for a find of great archaeological importance!") + .playerl("Wow! You write really quickly don't you?") + .npcl("What can I say? It's a skill I picked up through my many years of taking field notes!") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 2) { + setQuestStage(player, DesertTreasure.questName, 3) + } + } + + b.onQuestStages(DesertTreasure.questName, 1) + .playerl("Hello, are you Terry Balando?") + .npcl("That's right, who wants to know...?") + .npcl("Ah yes, I recognise you! You're the fellow who found that strange artefact about Zaros for the museum, aren't you? What can I do for you now?") + .playerl("That's right. I was in the desert down by the Bedabin Camp, and I found an archaeologist who asked me to deliver this to you.") + .npcl("You spoke to the legendary Asgarnia Smith??? Quickly, let me see what he had to give you! He is always at the forefront of archaeological breakthroughs!") + .betweenStage { df, player, _, _ -> + removeItem(player, Items.ETCHINGS_4654) // remove if exists + } + .playerl("So what does the inscription say? Anything interesting?") + .npcl("This... this is fascinating! These cuneiforms seem to predate even the settlement we are excavating here... Yes, yes, this is most interesting indeed!") + .playerl("Can you translate it for me?") + .npc("Well, I am not familiar with this particular language, but", "the similarities inherent in the pictographs seem to show", "a prevalent trend towards a syllabary consistent with", "the phonemes we have discovered in this excavation!") + .playerl("Um... So, can you translate it for me or not?") + .npcl("Well, unfortunately this is the only example of this particular language I have ever seen, but I might be able to make a rough translation, of sorts...") + .npcl("It might be slightly obscure on the finer details, but it should be good enough to understand the rough meaning of what was originally written. Please, just wait a moment, I will write up what I can") + .npcl("translate into a journal for you. Then you can take it back to Asgarnia, I think he will be extremely interested in the translation!") + .endWith { _, player -> + if(getQuestStage(player, DesertTreasure.questName) == 1) { + setQuestStage(player, DesertTreasure.questName, 2) + } + } + // Fallback dialogue. b.onPredicate { player -> true } .playerl(FacialExpression.FRIENDLY, "Hello. Who are you?") diff --git a/Server/src/main/content/region/morytania/canifis/dialogue/MalakDialogue.java b/Server/src/main/content/region/morytania/canifis/dialogue/MalakDialogue.java deleted file mode 100644 index b4e1d290f..000000000 --- a/Server/src/main/content/region/morytania/canifis/dialogue/MalakDialogue.java +++ /dev/null @@ -1,57 +0,0 @@ -package content.region.morytania.canifis.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.dialogue.FacialExpression; -import core.game.node.entity.npc.NPC; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the dialogue used for malak. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public class MalakDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code MalakDialogue} {@code Object}. - */ - public MalakDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code MalakDialogue} {@code Object}. - * @param player the player. - */ - public MalakDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new MalakDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Away from me, dog.", "I have business to discuss with the barkeeper."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - end(); - return true; - } - - @Override - public int[] getIds() { - return new int[] { 1920 }; - } -} diff --git a/Server/src/main/core/game/activity/Cutscene.kt b/Server/src/main/core/game/activity/Cutscene.kt index a8b2c6759..2cf25e068 100644 --- a/Server/src/main/core/game/activity/Cutscene.kt +++ b/Server/src/main/core/game/activity/Cutscene.kt @@ -57,6 +57,15 @@ abstract class Cutscene(val player: Player) { base = region.baseLocation } + /** + * Immediately closes the player's overlay. + */ + fun closeOverlay() + { + logCutscene("Close ${player.username}'s overlay.") + player.interfaceManager.closeOverlay() + } + /** * Fade the player's view to black. This process can be safely assumed to take about 8 ticks to complete. */ diff --git a/Server/src/main/core/game/global/action/SpecialLadders.java b/Server/src/main/core/game/global/action/SpecialLadders.java index 1e96aec6f..532bd896a 100644 --- a/Server/src/main/core/game/global/action/SpecialLadders.java +++ b/Server/src/main/core/game/global/action/SpecialLadders.java @@ -37,6 +37,9 @@ public enum SpecialLadders implements LadderAchievementCheck { ALKHARID_CRAFTING_DOWN(Location.create(3314,3187,1),Location.create(3310,3187,0)), ALKHARID_SOCRCERESS_UP(Location.create(3325,3142,0),Location.create(3325,3139,1)), ALKHARID_SOCRCERESS_DOWN(Location.create(3325,3139,1),Location.create(3325,3143,0)), + KHARIDIAN_DESERT_SUMMONING_UP(Location.create(3299,9318,0),Location.create(3303,2897,0)), + KHARIDIAN_DESERT_SUMMONING_DOWN(Location.create(3304,2897,0),Location.create(3299,9317,0)), + SHADOW_DUNGEON_UP(new Location(2629, 5072,0), new Location(2548, 3421,0)), CLOCKTOWER_HIDDEN_LADDER(Location.create(2572,9631,0),Location.create(2572,3230,0)), diff --git a/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt b/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt index 2ac6a0957..e1de944d1 100644 --- a/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/AnimationCommandSet.kt @@ -27,6 +27,25 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) { player.animate(animation) } + /** + * Force the player to play animation + */ + define("anims", Privilege.ADMIN, "::anim Animation ID", "Plays the animation with the given ID."){ player, args -> + if (args.size < 3) { + reject(player, "Syntax error: ::anim ") + } + val animation = args[1].toInt() + val animationTo = args[2].toInt() + GameWorld.Pulser.submit(object : Pulse(3, player) { + var someId = animation + override fun pulse(): Boolean { + player.animate(Animation.create(someId)) + someId += 1 + return someId >= animationTo + } + }) + } + /** * Force the player to loop animation */ diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 473998a67..1c22818df 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -411,6 +411,20 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ setVarbit(player, index!!, value!!) } + define("setvarbits", Privilege.ADMIN, "::setvarbits FROM VARBIT ID TO VARBIT ID VALUE", ""){ + player,args -> + if(args.size != 4){ + reject(player,"Usage: ::setvarbits fromvarbit tovarbit value") + } + val fromIndex = args[1].toIntOrNull()!! + val toIndex = args[2].toIntOrNull()!! + val value = args[3].toIntOrNull()!! + + for (index in fromIndex..toIndex) { + setVarbit(player, index, value) + } + } + define("getvarbit", Privilege.ADMIN, "::getvarbit VARBIT ID", "") { player, args -> if (args.size != 2) diff --git a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt index 2cbc404e2..30e4107c9 100644 --- a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt @@ -139,6 +139,30 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){ } } + /** + * Finds a list of objects/sceneries in a region + */ + define("findobjs", Privilege.ADMIN, "::findobjs REGION ID SCENERY ID", "Finds all locations of scenery objects of id."){player, args -> + if(args.size < 4) reject(player, "Usage: region_id scenery_id") + val regionId = args[1].toInt() + val sceneryId = args[2].toInt() + val sceneryIdEnd = args[3].toInt() + + val region = RegionManager.forId(regionId) + + GlobalScope.launch { + for (plane in region.planes) { + for (objects in plane.objects.filterNotNull()) { + for (parent in objects.filterNotNull()) { + if (parent.id in sceneryId..sceneryIdEnd) { + println(parent.location) + } + } + } + } + } + } + /** * Teleport to a specific player */ From 053254b504e0173fabc94c6631ad55a3a15e16d4 Mon Sep 17 00:00:00 2001 From: Elbarto 2 <25245812-elbarto2@users.noreply.gitlab.com> Date: Sun, 16 Feb 2025 09:48:21 +0000 Subject: [PATCH 226/306] Corrected restore for various consumables --- .../content/data/consumables/Consumables.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Server/src/main/content/data/consumables/Consumables.java b/Server/src/main/content/data/consumables/Consumables.java index ead89d9d2..82c6650a1 100644 --- a/Server/src/main/content/data/consumables/Consumables.java +++ b/Server/src/main/content/data/consumables/Consumables.java @@ -30,24 +30,24 @@ public enum Consumables { HERRING(new Food(new int[] {347}, new HealingEffect(5))), MACKEREL(new Food(new int[] {355}, new HealingEffect(6))), ROAST_BIRD_MEAT(new Food(new int[] {9980}, new HealingEffect(6))), - THIN_SNAIL(new Food(new int[] {3369}, new HealingEffect(5))), + THIN_SNAIL(new Food(new int[] {3369}, new RandomHealthEffect(5, 7))), TROUT(new Food(new int[] {333}, new HealingEffect(7))), - SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new HealingEffect(7))), + SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new RandomHealthEffect(7, 11))), SPIDER_ON_SHAFT(new Food(new int[] {6299}, new HealingEffect(7))), ROAST_RABBIT(new Food(new int[] {7223}, new HealingEffect(7))), - LEAN_SNAIL(new Food(new int[] {3371}, new HealingEffect(8))), + LEAN_SNAIL(new Food(new int[] {3371}, new RandomHealthEffect(6, 8))), COD(new Food(new int[] {339}, new HealingEffect(7))), PIKE(new Food(new int[] {351}, new HealingEffect(8))), ROAST_BEAST_MEAT(new Food(new int[] {9988}, new HealingEffect(8))), COOKED_CRAB_MEAT(new Food(new int[] {7521, 7523, 7524, 7525, 7526}, new HealingEffect(2))), - FAT_SNAIL(new Food(new int[] {3373}, new HealingEffect(9))), + FAT_SNAIL(new Food(new int[] {3373}, new RandomHealthEffect(7, 9))), SALMON(new Food(new int[] {329}, new HealingEffect(9))), - SLIMY_EEL(new Food(new int[] {3381}, new HealingEffect(6))), + SLIMY_EEL(new Food(new int[] {3381}, new RandomHealthEffect(6, 10))), TUNA(new Food(new int[] {361}, new HealingEffect(10))), COOKED_KARAMBWAN(new Food(new int[] {3144}, new HealingEffect(18)), true), COOKED_CHOMPY(new Food(new int[] {2878}, new HealingEffect(10))), RAINBOW_FISH(new Food(new int[] {10136}, new HealingEffect(11))), - CAVE_EEL(new Food(new int[] {5003}, new HealingEffect(7))), + CAVE_EEL(new Food(new int[] {5003}, new RandomHealthEffect(8, 12))), LOBSTER(new Food(new int[] {379}, new HealingEffect(12))), COOKED_JUBBLY(new Food(new int[] {7568}, new HealingEffect(15))), BASS(new Food(new int[] {365}, new HealingEffect(13))), @@ -59,7 +59,7 @@ public enum Consumables { MANTA_RAY(new Food(new int[] {391}, new HealingEffect(22))), KARAMBWANJI(new Food(new int[] {3151}, new HealingEffect(3))), STUFFED_SNAKE(new Food(new int[] {7579}, new HealingEffect(20), "You eat the stuffed snake-it's quite a meal! It tastes like chicken.")), - CRAYFISH(new Food(new int[] {13433}, new HealingEffect(2))), + CRAYFISH(new Food(new int[] {13433}, new HealingEffect(1))), GIANT_FROG_LEGS(new Food(new int [] {4517}, new HealingEffect(6))), /** Breads */ @@ -111,7 +111,7 @@ public enum Consumables { /** Vegetables */ POTATO(new Food(new int[] {1942}, new HealingEffect(1), "You eat the potato. Yuck!")), - BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(2))), + BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(4))), SPICY_SAUCE(new Food(new int[] {7072, 1923}, new HealingEffect(2))), CHILLI_CON_CARNE(new Food(new int[] {7062, 1923}, new HealingEffect(5))), SCRAMBLED_EGG(new Food(new int[] {7078, 1923}, new HealingEffect(5))), @@ -128,8 +128,8 @@ public enum Consumables { MUSHROOM_POTATO(new Food(new int[] {7058}, new HealingEffect(20))), TUNA_AND_CORN(new Food(new int[] {7068, 1923}, new HealingEffect(13))), TUNA_POTATO(new Food(new int[] {7060}, new HealingEffect(22))), - ONION(new Food(new int[] {1957}, new HealingEffect(2), "It's always sad to see a grown man/woman cry.")), - CABBAGE(new Food(new int[] {1965}, new HealingEffect(2), "You eat the cabbage. Yuck!")), + ONION(new Food(new int[] {1957}, new HealingEffect(1), "It's always sad to see a grown man/woman cry.")), + CABBAGE(new Food(new int[] {1965}, new HealingEffect(1), "You eat the cabbage. Yuck!")), DRAYNOR_CABBAGE(new Food(new int[] {1967}, new DraynorCabbageEffect(), "You eat the cabbage.", "It seems to taste nicer than normal.")), EVIL_TURNIP(new Food(new int[] {12134, 12136, 12138}, new HealingEffect(6))), SPINACH_ROLL(new Food(new int[] {1969}, new HealingEffect(2))), @@ -147,7 +147,7 @@ public enum Consumables { ORANGE(new Food(new int[] {2108}, new HealingEffect(2))), ORANGE_CHUNKS(new Food(new int[] {2110}, new HealingEffect(2))), ORANGE_SLICES(new Food(new int[] {2112}, new HealingEffect(2))), - PAPAYA_FRUIT(new Food(new int[] {5972}, new HealingEffect(2))), + PAPAYA_FRUIT(new Food(new int[] {5972}, new MultiEffect(new EnergyEffect(5), new HealingEffect(8)))), TENTI_PINEAPPLE(new FakeConsumable(1851, new String[] {"Try using a knife to slice it into pieces."})), PINEAPPLE(new FakeConsumable(2114, new String[] {"Try using a knife to slice it into pieces."})), PINEAPPLE_CHUNKS(new Food(new int[] {2116}, new HealingEffect(2))), @@ -169,8 +169,8 @@ public enum Consumables { STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(30)))), /** Gnome Cooking */ - TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(12))), - PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(12))), + TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(8))), + PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(8))), SPICY_CRUNCHIES(new Food(new int[] {2213}, new HealingEffect(7))), PREMADE_SY_CRUNCH(new Food(new int[] {2241}, new HealingEffect(7))), WORM_CRUNCHIES(new Food(new int[] {2205}, new HealingEffect(8))), @@ -307,7 +307,7 @@ public enum Consumables { OOMLIE_WRAP(new Food(new int[] {Items.COOKED_OOMLIE_WRAP_2343}, new MultiEffect(new HealingEffect(14), new AchievementEffect(DiaryType.KARAMJA, 2, 2)))), ROE(new Food(new int[]{11324}, new HealingEffect(3))), EQUA_LEAVES(new Food(new int[]{2128}, new HealingEffect(1))), - CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(6))), + CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(7))), EDIBLE_SEAWEED(new Food(new int[] {403}, new HealingEffect(4))), FROG_SPAWN(new Food(new int[] {5004}, new RandomHealthEffect(3, 7), "You eat the frogspawn. Yuck.")), @@ -339,7 +339,7 @@ public enum Consumables { FISHING(new Potion(new int[] {2438, 151, 153, 155}, new SkillEffect(Skills.FISHING, 3, 0))), PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))), SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new RestoreEffect(8, 0.25, true))), - ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), + ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1)))), ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new AddTimerEffect("dragonfire:immunity", 600, true))), GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))), MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))), @@ -349,7 +349,7 @@ public enum Consumables { /** Barbarian Mixes */ PRAYERMIX(new BarbarianMix(new int[] {11465, 11467}, new MultiEffect(new PrayerEffect(7, 0.25), new HealingEffect(6)))), - ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))), + ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1)))), ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))), ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new AddTimerEffect("poison:immunity", secondsToTicks(90)), new HealingEffect(3)))), RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new CureDiseaseEffect(), new HealingEffect(3)))), From be76ca143b493c352f695d5334b72d1d524e38ec Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 10:03:20 +0000 Subject: [PATCH 227/306] Fixed softlock in Priest in Peril and The Fremennik Trials --- .../quest/thefremenniktrials/ChieftanBrundtDialogue.kt | 8 ++++---- .../rellekka/quest/thefremenniktrials/ManniDialogue.kt | 5 +++-- .../rellekka/quest/thefremenniktrials/OlafTheBard.kt | 2 +- .../quest/thefremenniktrials/PeerTheSeerDialogue.kt | 4 ++-- .../quest/thefremenniktrials/SeersHouseListeners.kt | 3 ++- .../rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt | 5 +++-- .../rellekka/quest/thefremenniktrials/SigmundDialogue.kt | 5 +++-- .../quest/thefremenniktrials/SwensenTheNavigator.kt | 3 ++- .../quest/thefremenniktrials/TFTInteractionListeners.kt | 4 ++-- .../rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt | 7 ++++--- .../quest/priestinperil/PriestInPerilUseListener.kt | 7 ++++++- 11 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt index d9a4dc814..ac6cc0c24 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt @@ -43,22 +43,22 @@ class ChieftanBrundt(player: Player? = null) : DialoguePlugin(player){ stage = 500 return true } - else if(player.getAttribute("fremtrials:votes",0) >= 7){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player.getAttribute("fremtrials:votes",0) >= 7) { npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 545 return true } - else if(player.getAttribute("fremtrials:votes",0) in 3..6){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player.getAttribute("fremtrials:votes",0) in 3..6) { npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 540 return true } - else if(player.getAttribute("fremtrials:votes",0) == 1){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player.getAttribute("fremtrials:votes",0) == 1) { npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 535 return true } - else if(player.getAttribute("fremtrials:votes",-1) == 0){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player.getAttribute("fremtrials:votes",-1) == 0) { npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 530 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt index 125bf5702..425c617cf 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ManniDialogue.kt @@ -1,6 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem +import core.api.getQuestStage import core.api.removeItem import core.game.node.entity.impl.Animator import core.game.node.entity.npc.NPC @@ -56,8 +57,8 @@ class ManniDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin( return true } } - else if(player?.getAttribute("fremtrials:manni-vote",false) == true){ - npc("e have my vote!") + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player?.getAttribute("fremtrials:manni-vote",false) == true) { + npc("Ye have my vote!") stage = 1000 return true } diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt index 953098cf6..baffb1143 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/OlafTheBard.kt @@ -49,7 +49,7 @@ class OlafTheBard(player: Player? = null) : DialoguePlugin(player){ stage = 98 return true } - else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0){ npc("Hello? Yes? You want something outerlander?") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt index daf4e9d34..58714b206 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/PeerTheSeerDialogue.kt @@ -65,7 +65,7 @@ class PeerTheSeerDialogue(player: Player? = null) : core.game.dialogue.DialogueP stage = 110 return true } - else if(player.getAttribute("fremtrials:peer-vote",false)){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player.getAttribute("fremtrials:peer-vote",false)) { npcl(core.game.dialogue.FacialExpression.SAD,"Uuuh... What was that dark presence I felt?") stage = 120 return true @@ -75,7 +75,7 @@ class PeerTheSeerDialogue(player: Player? = null) : core.game.dialogue.DialogueP stage = 150 return true } - else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0){ npcl(core.game.dialogue.FacialExpression.SAD,"Uuuh... What was that dark presence I felt?") stage = 50 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SeersHouseListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SeersHouseListeners.kt index 37e7434e9..684eece92 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SeersHouseListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SeersHouseListeners.kt @@ -1,5 +1,6 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials +import content.data.Quests import core.api.* import core.game.node.entity.impl.Animator import core.game.node.entity.player.Player @@ -102,7 +103,7 @@ class SeersHouseListeners : InteractionListener { if(!player.getAttribute("PeerStarted",false)){ sendDialogue(player,"You should probably talk to the owner of this home.") } - if(getAttribute(player, "fremtrials:peer-vote", false)) + if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && getAttribute(player, "fremtrials:peer-vote", false)) { sendDialogue(player, "I don't need to go through that again.") return@on true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt index 884959dee..3ccd4e421 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigliTheHuntsman.kt @@ -1,6 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem +import core.api.getQuestStage import core.api.removeItem import core.game.node.entity.player.Player import core.game.node.item.Item @@ -37,7 +38,7 @@ class SigliTheHuntsman(player: Player? = null) : DialoguePlugin(player){ stage = 150 return true } - else if(player?.getAttribute("fremtrials:sigli-vote",false)!!){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player?.getAttribute("fremtrials:sigli-vote",false)!!) { npc("You have my vote!") stage = 1000 return true @@ -52,7 +53,7 @@ class SigliTheHuntsman(player: Player? = null) : DialoguePlugin(player){ stage = 180 return true } - else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0){ npc("What do you want outerlander?") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt index 131d1adb8..b4804f0d2 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SigmundDialogue.kt @@ -1,6 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem +import core.api.getQuestStage import core.api.removeItem import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -28,7 +29,7 @@ class SigmundDialogue (player: Player? = null) : DialoguePlugin(player) { stage = 50 return true } - else if(!player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) <= 0) { playerl(FacialExpression.HAPPY,"Hello there!") stage = 60 return true @@ -48,7 +49,7 @@ class SigmundDialogue (player: Player? = null) : DialoguePlugin(player) { stage = 25 return true } - else if(!player?.getAttribute("fremtrials:sigmund-vote",false)!!){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && !player?.getAttribute("fremtrials:sigmund-vote",false)!!) { playerl(FacialExpression.HAPPY,"Hello there!") stage = 1 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt index 77983ca63..b2f5aada9 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/SwensenTheNavigator.kt @@ -1,6 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem +import core.api.getQuestStage import core.api.removeItem import core.game.node.entity.player.Player import core.plugin.Initializable @@ -52,7 +53,7 @@ class SwensenTheNavigator(player: Player? = null) : DialoguePlugin(player){ stage = 140 return true } - else if(player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0) { player("Hello!") stage = 0 return true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt index 7bd87557a..4005844f9 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt @@ -210,8 +210,8 @@ class TFTInteractionListeners : InteractionListener { return@on true } - on(SWENSEN_LADDER, IntType.SCENERY, "climb"){ player, _ -> - if(!getAttribute(player,"fremtrials:swensen-accepted",false)){ + on(SWENSEN_LADDER, IntType.SCENERY, "climb-down") { player, _ -> + if (!getAttribute(player,"fremtrials:swensen-accepted",false)) { sendNPCDialogue(player,1283,"Where do you think you're going?", core.game.dialogue.FacialExpression.ANGRY) } return@on true diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt index ff0d5deb2..af0ed440f 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ThorvaldDialogue.kt @@ -1,6 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials import core.api.addItem +import core.api.getQuestStage import core.api.removeItem import core.game.node.entity.player.Player import core.plugin.Initializable @@ -45,7 +46,7 @@ class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlug stage = 0 return true } - else if(player!!.getAttribute("fremtrials:thorvald-vote", false)!!){ + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && player!!.getAttribute("fremtrials:thorvald-vote", false)!!) { playerl(core.game.dialogue.FacialExpression.FRIENDLY, "So can I count on your vote at the council of elders now Thorvald?") stage = 160 return true @@ -55,12 +56,12 @@ class ThorvaldDialogue(player: Player? = null) : core.game.dialogue.DialoguePlug stage = 250 return true } - else if(!player.questRepository.hasStarted(Quests.THE_FREMENNIK_TRIALS)){ + else if(getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) == 0){ npcl(core.game.dialogue.FacialExpression.ANNOYED, "Leave me be, outerlander. I have nothing to say to the likes of you.") stage = 1000 return true } - else if (!player!!.getAttribute("fremtrials:thorvald-vote", false)!!) { + else if (getQuestStage(player, Quests.THE_FREMENNIK_TRIALS) > 0 && !player!!.getAttribute("fremtrials:thorvald-vote", false)!!) { if (player!!.getAttribute("fremtrials:warrior-accepted", false)!!) { options("What do I have to do again?", "Who is my opponent?", "Can't I do something else?") stage = 100 diff --git a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt index 8a3b1c912..61a36a6c8 100644 --- a/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt +++ b/Server/src/main/content/region/misthalin/quest/priestinperil/PriestInPerilUseListener.kt @@ -77,7 +77,12 @@ class PriestInPerilUseListener : InteractionListener { } onUseWith(IntType.SCENERY, Items.GOLDEN_KEY_2944, Scenery.MONUMENT_3499) { player, used, _ -> - if (!getAttribute(player, "priest_in_peril:key", false) && removeItem(player, used)) { + // See GL #2112 and sources therein for why we do it this way + val hasNeverGrabbedKey = !getAttribute(player, "priest_in_peril:key", false) + val needsKeyForQuestStage = getQuestStage(player, Quests.PRIEST_IN_PERIL) <= 15 + val hasTotallyLostKey = !hasAnItem(player, Items.IRON_KEY_2945, true).exists() + val giveNewKey = hasNeverGrabbedKey || (needsKeyForQuestStage && hasTotallyLostKey) + if (giveNewKey && removeItem(player, used)) { addItem(player, Items.IRON_KEY_2945) sendMessage(player, "You swap the golden key for the iron key.") setAttribute(player, "/save:priest_in_peril:key", true) From 4f97dbef8c6814f1660b52a9c4cb0a7442078017 Mon Sep 17 00:00:00 2001 From: GregF Date: Sun, 16 Feb 2025 10:19:20 +0000 Subject: [PATCH 228/306] Completed very large refactor of Plague City quest and related functionality --- Server/data/configs/drop_tables.json | 42 +- Server/data/configs/interface_configs.json | 48 ++ Server/data/configs/item_configs.json | 7 +- Server/data/configs/npc_configs.json | 631 +++++++++++------- Server/data/configs/npc_spawns.json | 118 ++-- .../global/dialogue/ManDialoguePlugin.java | 2 +- .../global/handlers/item/TeleTabsListener.kt | 23 +- .../item/withnpc/CatOnArdougneCivilian.kt | 56 -- .../portalchamber/PortalChamberPlugin.java | 14 + .../decoration/study/LecternPlugin.kt | 6 + .../skill/cooking/recipe/HangoverRecipe.kt | 44 ++ .../skill/magic/modern/ModernListeners.kt | 16 +- .../global/skill/slayer/SlayerPlugin.java | 4 - .../castlewars/areas/CastleWarsArea.kt | 1 - .../desert/handlers/ShantayPassPlugin.java | 2 +- .../plaguecity/dialogue/CivilianDialogue.kt | 44 -- .../plaguecity/dialogue/KilronDialogue.kt | 54 -- .../plaguecity/dialogue/ManDialogue.kt | 24 - .../plaguecity/dialogue/MournersDialogue.kt | 41 -- .../plaguecity/dialogue/WomanDialogue.kt | 61 -- .../plaguecity/quest/elena/BravekDialogue.kt | 117 ---- .../plaguecity/quest/elena/ClerkDialogue.kt | 95 --- .../plaguecity/quest/elena/EdmondDialogue.kt | 168 ----- .../plaguecity/quest/elena/MournerDialogue.kt | 87 --- .../quest/elena/PlagueCityListeners.kt | 457 ------------- .../biohazard/dialogue/KilronDialogue.kt | 51 ++ .../biohazard/dialogue/MournerBossDialogue.kt | 149 +++++ .../elena => quest/plaguecity}/PlagueCity.kt | 6 +- .../quest/plaguecity/PlagueCityListeners.kt | 430 ++++++++++++ .../plaguecity}/UndergroundCutscene.kt | 40 +- .../plaguecity/dialogue}/AlrenaDialogue.kt | 44 +- .../plaguecity/dialogue/BravekDialogue.kt | 156 +++++ .../plaguecity/dialogue/ClerkDialogue.kt | 98 +++ .../plaguecity/dialogue/EdmondDialogue.kt | 268 ++++++++ .../plaguecity/dialogue}/JethickDialogue.kt | 41 +- .../dialogue/KidnappedElenaDialogue.kt} | 12 +- .../dialogue}/MarthaRehnisonDialogue.kt | 4 +- .../dialogue}/MilliRehnisonDialogue.kt | 22 +- .../dialogue}/TedRehnisonDialogue.kt | 6 +- .../mourners/MournerArdougneWallDialogue.kt | 61 ++ .../mourners/MournerEdmondHouseDialogue.kt | 115 ++++ .../mourners/MournerGuardDialogue.kt} | 12 +- .../mourners/MournerKidnapDialogue.kt | 184 +++++ .../ardougne/westardougne/MournerUtilities.kt | 57 ++ .../dialogue/CarlaDialogue.kt | 2 +- .../dialogue/ChildDialogue.kt | 10 +- .../westardougne/dialogue/CivilianDialogue.kt | 181 +++++ .../dialogue/HeadMournerDialogue.kt | 115 ++++ .../westardougne/dialogue/ManWomanDialogue.kt | 81 +++ .../westardougne/dialogue/MournerDialogue.kt | 114 ++++ .../dialogue/NurseSarahDialogue.kt | 4 +- .../dialogue/PriestDialogue.kt | 2 +- .../dialogue/RecruiterDialogue.kt | 2 +- .../handlers/MainGatesListener.kt | 32 + .../westardougne/handlers/MournerHQDoors.kt | 66 ++ .../westardougne/handlers/SarahsBox.kt | 38 ++ .../westardougne/handlers/WearMaskListener.kt | 42 ++ .../quest/tree/TreeGnomeVillageListeners.kt | 20 +- Server/src/main/core/ServerConstants.kt | 2 +- Server/src/main/core/api/ContentAPI.kt | 23 +- .../src/main/core/game/activity/Cutscene.kt | 5 +- .../game/dialogue/DialogueInterpreter.java | 49 +- .../core/game/global/action/EquipHandler.kt | 13 +- .../player/info/login/SaveVersionHooks.kt | 15 +- .../entity/player/link/PacketDispatch.java | 7 +- .../system/command/sets/MiscCommandSet.kt | 10 + 66 files changed, 3055 insertions(+), 1696 deletions(-) create mode 100644 Server/src/main/content/global/skill/cooking/recipe/HangoverRecipe.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CivilianDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ManDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/MournersDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/WomanDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt delete mode 100644 Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/KilronDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/MournerBossDialogue.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity}/PlagueCity.kt (96%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCityListeners.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity}/UndergroundCutscene.kt (65%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity/dialogue}/AlrenaDialogue.kt (82%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/BravekDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/ClerkDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/EdmondDialogue.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity/dialogue}/JethickDialogue.kt (65%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena/ElenaDialogue.kt => quest/plaguecity/dialogue/KidnappedElenaDialogue.kt} (79%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity/dialogue}/MarthaRehnisonDialogue.kt (96%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity/dialogue}/MilliRehnisonDialogue.kt (61%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena => quest/plaguecity/dialogue}/TedRehnisonDialogue.kt (90%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerArdougneWallDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerEdmondHouseDialogue.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity/quest/elena/HeadMournerDialogue.kt => quest/plaguecity/dialogue/mourners/MournerGuardDialogue.kt} (96%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/MournerUtilities.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity => westardougne}/dialogue/CarlaDialogue.kt (98%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity => westardougne}/dialogue/ChildDialogue.kt (64%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CivilianDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/HeadMournerDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ManWomanDialogue.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/MournerDialogue.kt rename Server/src/main/content/region/kandarin/ardougne/{plaguecity => westardougne}/dialogue/NurseSarahDialogue.kt (87%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity => westardougne}/dialogue/PriestDialogue.kt (94%) rename Server/src/main/content/region/kandarin/ardougne/{plaguecity => westardougne}/dialogue/RecruiterDialogue.kt (95%) create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MournerHQDoors.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/SarahsBox.kt create mode 100644 Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/WearMaskListener.kt diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index db135d222..c0f25df89 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -11426,47 +11426,11 @@ "weight": "100.0", "id": "526", "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "1506", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "6065", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "6067", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "6069", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "6068", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "6070", - "maxAmount": "1" } ], "charm": [], - "ids": "347,348,357,369,370,371,372,717,718,719,2349,2350,2351,2373,2374,2784,3216", - "description": "", + "ids": "370,357,348,369,347,371", + "description": "all combat mourners", "main": [] }, { @@ -18161,7 +18125,7 @@ "maxAmount": "1" } ], - "ids": "1183,1184,1201,2359,2360,2361,2362,7438,7439,7440,7441", + "ids": "1183,1184,1201,2359,2360,2361,2362,2373,7438,7439,7440,7441", "description": "", "main": [ { diff --git a/Server/data/configs/interface_configs.json b/Server/data/configs/interface_configs.json index 50a5a64ed..95087003a 100644 --- a/Server/data/configs/interface_configs.json +++ b/Server/data/configs/interface_configs.json @@ -95,6 +95,30 @@ "walkable": "false", "tabIndex": "-1" }, + { + "id": "68", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "69", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "70", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "71", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, { "id": "74", "interfaceType": "4", @@ -365,6 +389,30 @@ "walkable": "false", "tabIndex": "-1" }, + { + "id": "245", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "246", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "247", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, + { + "id": "248", + "interfaceType": "4", + "walkable": "false", + "tabIndex": "-1" + }, { "id": "256", "interfaceType": "8", diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 83abfeadb..c7da93ae9 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -16309,6 +16309,7 @@ "examine": "Maybe I should read this...", "durability": null, "name": "A magic scroll", + "tradeable": "false", "archery_ticket_price": "0", "id": "1505" }, @@ -16324,7 +16325,7 @@ "equipment_slot": "0" }, { - "examine": "Quite a small key (Plague City).", + "examine": "Quite a small key.", "durability": null, "name": "A small key", "archery_ticket_price": "0", @@ -55738,7 +55739,7 @@ "equipment_slot": "4" }, { - "examine": "Damaged: These are in need of a good tailor.Repaired: A pair of mourner trousers.", + "examine": "These are in need of a good tailor.", "durability": null, "name": "Mourner trousers", "weight": "2.25", @@ -55746,7 +55747,7 @@ "id": "6066" }, { - "examine": "Damaged: These are in need of a good tailor.Repaired: A pair of mourner trousers.", + "examine": "A pair of mourner trousers.", "durability": null, "name": "Mourner trousers", "weight": "2.25", diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 9faf44635..5e11828b8 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -4784,131 +4784,130 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A mourner, or plague healer.", - "melee_animation": "422", - "range_animation": "0", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", - "death_animation": "836", - "name": "Mourner", - "defence_level": "24", - "safespot": null, - "lifepoints": "34", - "strength_level": "24", - "id": "347", - "range_level": "1", - "attack_level": "24" - }, - { - "examine": "A mourner, or plague healer.", - "melee_animation": "422", - "range_animation": "0", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", - "death_animation": "836", - "name": "Mourner", - "defence_level": "24", - "safespot": null, - "lifepoints": "34", - "strength_level": "24", - "id": "348", - "range_level": "1", - "attack_level": "24" - }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "0", + "range_animation": "", "combat_audio": "511,513,512", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", + "attack_speed": "4", + "defence_animation": "404", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Man", - "defence_level": "2", + "defence_level": "1", "safespot": null, - "lifepoints": "7", - "strength_level": "2", + "lifepoints": "13", + "strength_level": "1", "id": "351", - "clue_level": "0", + "clue_level": "", + "bonuses": "0,0,0,0,0,1,1,1,0,0,0,0,0,0,0", "range_level": "1", "attack_level": "2" }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "0", + "range_animation": "", "combat_audio": "511,506,505", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", + "attack_speed": "4", + "respawn_delay": "50", + "defence_animation": "404", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "2", + "defence_level": "1", "safespot": null, - "lifepoints": "7", - "strength_level": "2", + "lifepoints": "10", + "strength_level": "1", "id": "352", - "clue_level": "0", + "clue_level": "", + "bonuses": "0,0,0,0,0,1,1,1,0,0,0,0,0,0,0", "range_level": "1", "attack_level": "2" }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "0", + "range_animation": "", "combat_audio": "511,506,505", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", + "attack_speed": "4", + "respawn_delay": "50", + "defence_animation": "404", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "2", + "defence_level": "1", "safespot": null, - "lifepoints": "7", - "strength_level": "2", + "lifepoints": "13", + "strength_level": "1", "id": "353", - "clue_level": "0", + "clue_level": "", + "bonuses": "0,0,0,0,0,1,1,1,0,0,0,0,0,0,0", "range_level": "1", "attack_level": "2" }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "0", + "range_animation": "", "combat_audio": "511,506,505", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", + "attack_speed": "4", + "respawn_delay": "50", + "defence_animation": "404", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "2", + "defence_level": "1", "safespot": null, - "lifepoints": "7", - "strength_level": "2", + "lifepoints": "13", + "strength_level": "1", "id": "354", - "clue_level": "0", + "clue_level": "", + "bonuses": "0,0,0,0,0,1,1,1,0,0,0,0,0,0,0", "range_level": "1", "attack_level": "2" }, { "examine": "A child of West Ardougne.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "magic_level": "", + "defence_animation": "", + "poison_amount": "", + "magic_animation": "", + "death_animation": "", "name": "Child", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "movement_radius": "", + "lifepoints": "", + "strength_level": "", "id": "355", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" + }, + { + "examine": "A child of West Ardougne.", + "melee_animation": "", + "range_animation": "", + "magic_level": "", + "defence_animation": "", + "poison_amount": "", + "magic_animation": "", + "death_animation": "", + "name": "Child", + "defence_level": "", + "safespot": null, + "movement_radius": "", + "lifepoints": "", + "strength_level": "", + "id": "356", + "range_level": "", + "attack_level": "" }, { "examine": "A holy man.", @@ -4951,22 +4950,24 @@ { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "422", + "range_animation": "", "combat_audio": "511,506,505", "attack_speed": "4", + "respawn_delay": "50", "defence_animation": "404", - "weakness": "9", - "magic_animation": "422", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "3", + "defence_level": "1", "safespot": null, - "lifepoints": "7", + "lifepoints": "13", "strength_level": "1", "id": "360", - "clue_level": "0", + "clue_level": "", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "range_level": "1", - "attack_level": "3" + "attack_level": "2" }, { "examine": "One of Gielinor's many citizens.", @@ -4974,56 +4975,62 @@ "range_animation": "422", "combat_audio": "511,506,505", "attack_speed": "4", + "respawn_delay": "50", "defence_animation": "404", - "weakness": "9", - "magic_animation": "422", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "3", + "defence_level": "10", "safespot": null, - "lifepoints": "7", - "strength_level": "1", + "lifepoints": "13", + "strength_level": "10", "id": "361", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "range_level": "1", - "attack_level": "3" + "attack_level": "10" }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "422", + "range_animation": "", "combat_audio": "511,506,505", "attack_speed": "4", + "respawn_delay": "50", "defence_animation": "404", - "weakness": "9", - "magic_animation": "422", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "3", + "defence_level": "2", "safespot": null, - "lifepoints": "7", + "lifepoints": "10", "strength_level": "1", "id": "362", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "range_level": "1", - "attack_level": "3" + "attack_level": "1" }, { "examine": "One of Gielinor's many citizens.", "melee_animation": "422", - "range_animation": "422", + "range_animation": "", "combat_audio": "511,506,505", "attack_speed": "4", + "respawn_delay": "50", "defence_animation": "404", - "weakness": "9", - "magic_animation": "422", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Woman", - "defence_level": "3", + "defence_level": "10", "safespot": null, - "lifepoints": "7", - "strength_level": "1", + "lifepoints": "23", + "strength_level": "10", "id": "363", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "range_level": "1", - "attack_level": "3" + "attack_level": "10" }, { "examine": "King Lathas of East Ardougne.", @@ -5087,23 +5094,6 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A mourner, or plague healer.", - "melee_animation": "422", - "range_animation": "0", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", - "death_animation": "836", - "name": "Mourner", - "defence_level": "24", - "safespot": null, - "lifepoints": "34", - "strength_level": "24", - "id": "369", - "range_level": "1", - "attack_level": "24" - }, { "examine": "She's quite a looker!", "melee_animation": "0", @@ -8071,32 +8061,43 @@ "attack_level": "1" }, { - "slayer_exp": "0", + "slayer_exp": "", "examine": "A local civilian.", "name": "Edmond", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "combat_audio": "", + "strength_level": "", "id": "714", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { - "examine": "In charge of people with silly outfits.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Head mourner", - "defence_level": "1", + "slayer_exp": "", + "examine": "A local civilian.", + "name": "Edmond", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "716", - "range_level": "1", - "attack_level": "1" + "lifepoints": "", + "combat_audio": "", + "strength_level": "", + "id": "3213", + "range_level": "", + "attack_level": "" + }, + { + "slayer_exp": "", + "examine": "A local civilian.", + "name": "Edmond", + "defence_level": "", + "safespot": null, + "lifepoints": "", + "combat_audio": "", + "strength_level": "", + "id": "3214", + "range_level": "", + "attack_level": "" }, { "examine": "A member of the Ardougne Royal Army.", @@ -8142,39 +8143,42 @@ }, { "examine": "One of Gielinor's many citizens.", - "melee_animation": "0", - "range_animation": "0", - "combat_audio": "511,513,512", + "melee_animation": "", + "range_animation": "", + "combat_audio": "", + "protect_style": "", + "respawn_delay": "", "defence_animation": "0", - "magic_animation": "0", + "slayer_exp": "", + "magic_animation": "", "death_animation": "0", "name": "Man", "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "safespot": "", + "lifepoints": "", + "strength_level": "", "id": "728", - "clue_level": "0", - "range_level": "1", - "attack_level": "1" + "clue_level": "", + "range_level": "", + "attack_level": "" }, { "examine": "One of Gielinor's many citizens.", - "melee_animation": "0", - "range_animation": "0", - "combat_audio": "511,513,512", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "combat_audio": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Man", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "729", - "clue_level": "0", - "range_level": "1", - "attack_level": "1" + "clue_level": "", + "range_level": "", + "attack_level": "" }, { "examine": "One of Gielinor's many citizens.", @@ -8498,51 +8502,51 @@ }, { "examine": "A citizen of Ardougne.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Civilian", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "785", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "A citizen of Ardougne.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Civilian", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "786", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "A citizen of Ardougne.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Civilian", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "787", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "A gnome who's supposed to be cleaning up a mess.", @@ -24275,36 +24279,37 @@ }, { "examine": "A Mourner showing his true identity.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Head mourner", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "2372", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "A mourner, or plague healer.", "melee_animation": "428", - "range_animation": "0", - "defence_animation": "0", - "weakness": "9", - "magic_animation": "0", + "range_animation": "", + "attack_speed": "4", + "defence_animation": "", + "weakness": "", + "magic_animation": "", "death_animation": "836", "name": "Mourner", - "defence_level": "61", + "defence_level": "80", "safespot": null, "lifepoints": "87", "strength_level": "61", "id": "2373", "aggressive": "true", - "range_level": "1", + "range_level": "", "attack_level": "61" }, { @@ -27188,51 +27193,51 @@ }, { "examine": "Digging.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Slave", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "2785", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "Digging.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Slave", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "2786", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "Confused.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", + "melee_animation": "", + "range_animation": "", + "defence_animation": "", + "magic_animation": "", + "death_animation": "", "name": "Slave", - "defence_level": "1", + "defence_level": "", "safespot": null, - "lifepoints": "10", - "strength_level": "1", + "lifepoints": "", + "strength_level": "", "id": "2787", - "range_level": "1", - "attack_level": "1" + "range_level": "", + "attack_level": "" }, { "examine": "Drill Sergeant from heck!", @@ -30714,22 +30719,6 @@ "range_level": "1", "attack_level": "1" }, - { - "examine": "A mourner, or plague healer.", - "melee_animation": "0", - "range_animation": "0", - "defence_animation": "0", - "magic_animation": "0", - "death_animation": "0", - "name": "Mourner", - "defence_level": "1", - "safespot": null, - "lifepoints": "10", - "strength_level": "1", - "id": "3216", - "range_level": "1", - "attack_level": "1" - }, { "examine": "Loves mining.", "melee_animation": "99", @@ -87739,5 +87728,143 @@ "examine": "A nature impling. Right on, maaan.", "name": "Nature Impling", "id": "1034" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner (boss)", + "defence_level": "10", + "lifepoints": "19", + "melee_animation": "428", + "attack_speed": "4", + "strength_level": "10", + "id": "370", + "bonuses": "0,0,0,0,0,3,2,4,0,0,0,0,0,0,0", + "attack_level": "10" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "717" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "718" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "719" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "3216" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner", + "defence_level": "14", + "melee_animation": "428", + "lifepoints": "24", + "attack_speed": "4", + "strength_level": "14", + "id": "357", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + "attack_level": "14" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner", + "defence_level": "19", + "melee_animation": "422", + "lifepoints": "30", + "attack_speed": "4", + "strength_level": "19", + "id": "348", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + "attack_level": "19" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner", + "defence_level": "19", + "melee_animation": "422", + "lifepoints": "30", + "attack_speed": "4", + "strength_level": "19", + "id": "369", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + "attack_level": "19" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner", + "defence_level": "8", + "lifepoints": "18", + "melee_animation": "428", + "strength_level": "8", + "attack_speed": "4", + "id": "347", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + "attack_level": "8" + }, + { + "examine": "A Mourner, or plague healer.", + "name": "Mourner", + "id": "2374" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "372" + }, + { + "examine": "A mourner, or plague healer.", + "death_animation": "836", + "name": "Mourner", + "defence_level": "8", + "lifepoints": "20", + "melee_animation": "422", + "attack_speed": "4", + "strength_level": "8", + "id": "371", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", + "attack_level": "8" + }, + { + "examine": "In charge of people with silly outfits.", + "name": "Head Mourner", + "id": "716" + }, + { + "examine": "A mourner, or plague healer.", + "name": "Mourner", + "id": "2784" + }, + { + "examine": "She looks concerned.", + "name": "Elena", + "id": "3215" + }, + { + "examine": "She looks concerned.", + "name": "Elena", + "id": "715" + }, + { + "examine": "She doesn't look too happy.", + "name": "Elena", + "id": "3209" + }, + { + "name": "Elena", + "id": "335", + "examine": "She doesn't look too happy." } ] \ No newline at end of file diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 6a550f27b..e2534a0b6 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -213,7 +213,7 @@ }, { "npc_id": "64", - "loc_data": "{2684,9798,0,1,2}-{2959,3917,0,1,0}-{2960,3925,0,1,0}-{2961,3920,0,1,0}-{2962,3915,0,1,0}-{2962,3933,0,1,0}-{2963,3923,0,1,0}-{2963,3929,0,1,0}-{2965,3927,0,1,0}-{2965,3931,0,1,0}-{2691,9814,0,1,5}-{2694,9819,0,1,6}-{2696,9831,0,1,3}-{2702,9837,0,1,6}-{2709,9844,0,1,3}-{2720,9847,0,1,4}-{2724,9843,0,1,6}-{2733,9846,0,1,4}-{2740,9841,0,1,3}-{2745,9836,0,1,4}-{2745,9828,0,1,5}-{2747,9826,0,1,1}-{2819,9950,0,1,0}-{2824,9934,0,1,0}-{2827,9925,0,1,0}-{2828,9956,0,1,0}-{2857,9969,0,1,0}-{2872,9972,0,1,0}-{2869,9912,0,1,0}-{2885,9962,0,1,0}-{2887,9936,0,1,0}-" + "loc_data": "{2869,9912,0,1,0}-{2819,9950,0,1,0}-{2824,9934,0,1,0}-{2827,9925,0,1,0}-{2828,9956,0,1,0}-{2857,9969,0,1,0}-{2872,9972,0,1,0}-{2684,9798,0,1,2}-{2885,9962,0,1,0}-{2887,9936,0,1,0}-{2959,3917,0,1,0}-{2960,3925,0,1,0}-{2961,3920,0,1,0}-{2962,3915,0,1,0}-{2962,3933,0,1,0}-{2963,3923,0,1,0}-{2963,3929,0,1,0}-{2965,3927,0,1,0}-{2965,3931,0,1,0}-{2691,9814,0,1,5}-{2694,9819,0,1,6}-{2696,9831,0,1,3}-{2702,9837,0,1,6}-{2709,9844,0,1,3}-{2720,9847,0,1,4}-{2724,9843,0,1,6}-{2733,9846,0,1,4}-{2740,9841,0,1,3}-{2745,9836,0,1,4}-{2745,9828,0,1,5}-{2747,9826,0,1,1}-" }, { "npc_id": "66", @@ -369,7 +369,7 @@ }, { "npc_id": "111", - "loc_data": "{2811,3506,0,1,0}-{2883,9932,0,1,0}-{2883,9965,0,1,0}-{2920,3800,0,1,3}-{2952,3902,0,1,6}-{2953,3889,0,1,6}-{2947,3921,0,1,6}-{3043,9581,0,1,1}-{3055,9577,0,1,6}-{3061,9576,0,1,4}-{3055,9571,0,1,7}-{3052,9566,0,1,6}-" + "loc_data": "{2920,3800,0,1,3}-{2883,9932,0,1,0}-{2883,9965,0,1,0}-{2952,3902,0,1,6}-{2953,3889,0,1,6}-{2947,3921,0,1,6}-{2811,3506,0,1,0}-{3043,9581,0,1,1}-{3055,9577,0,1,6}-{3061,9576,0,1,4}-{3055,9571,0,1,7}-{3052,9566,0,1,6}-" }, { "npc_id": "112", @@ -417,7 +417,7 @@ }, { "npc_id": "125", - "loc_data": "{2845,3517,0,1,4}-{2848,3515,0,1,4}-{2958,3867,0,1,3}-{2956,3857,0,1,6}-{2952,3862,0,1,3}-{2949,3858,0,1,4}-{2955,3875,0,1,7}-{2954,3874,0,1,5}-{2962,3876,0,1,1}-{2961,3877,0,1,3}-{2947,3878,0,1,6}-{2959,3884,0,1,4}-{2956,3885,0,1,3}-{2956,3886,0,1,3}-{2948,3886,0,1,1}-{2947,3934,0,1,0}-{2948,3917,0,1,0}-{2949,3926,0,1,0}-{2952,3913,0,1,0}-{2952,3936,0,1,0}-{2954,3921,0,1,0}-{2956,3930,0,1,0}-{2964,3944,0,1,0}-{2970,3947,0,1,0}-{2971,3938,0,1,0}-{2977,3953,0,1,0}-{2978,3942,0,1,0}-{2984,3933,0,1,0}-{3227,5443,0,1,5}-{3220,5448,0,1,5}-{3208,5443,0,1,6}-{3207,5448,0,1,4}-{3050,9570,0,1,3}-{3043,9579,0,1,2}-{3056,9585,0,1,0}-{3058,9575,0,1,1}-{3052,9582,0,1,0}-{3049,9577,0,1,4}-{3042,9586,0,1,6}-{3052,9588,0,1,1}-{3049,9590,0,1,5}-{3060,9578,0,1,3}-{3054,9566,0,1,7}-{2834,9940,0,1,0}-{2836,9953,0,1,0}-{2844,9944,0,1,0}-{2822,9901,0,1,0}-{2836,9905,0,1,0}-{2838,9917,0,1,0}-{2847,9919,0,1,0}-{2848,9912,0,1,0}-" + "loc_data": "{2845,3517,0,1,4}-{2848,3515,0,1,4}-{2822,9901,0,1,0}-{2836,9905,0,1,0}-{2838,9917,0,1,0}-{2847,9919,0,1,0}-{2848,9912,0,1,0}-{2834,9940,0,1,0}-{2836,9953,0,1,0}-{2844,9944,0,1,0}-{2958,3867,0,1,3}-{2956,3857,0,1,6}-{2952,3862,0,1,3}-{2949,3858,0,1,4}-{2955,3875,0,1,7}-{2954,3874,0,1,5}-{2962,3876,0,1,1}-{2961,3877,0,1,3}-{2947,3878,0,1,6}-{2959,3884,0,1,4}-{2956,3885,0,1,3}-{2956,3886,0,1,3}-{2948,3886,0,1,1}-{2947,3934,0,1,0}-{2948,3917,0,1,0}-{2949,3926,0,1,0}-{2952,3913,0,1,0}-{2952,3936,0,1,0}-{2954,3921,0,1,0}-{2956,3930,0,1,0}-{2964,3944,0,1,0}-{2970,3947,0,1,0}-{2971,3938,0,1,0}-{2977,3953,0,1,0}-{2978,3942,0,1,0}-{2984,3933,0,1,0}-{3227,5443,0,1,5}-{3220,5448,0,1,5}-{3208,5443,0,1,6}-{3207,5448,0,1,4}-{3050,9570,0,1,3}-{3043,9579,0,1,2}-{3056,9585,0,1,0}-{3058,9575,0,1,1}-{3052,9582,0,1,0}-{3049,9577,0,1,4}-{3042,9586,0,1,6}-{3052,9588,0,1,1}-{3049,9590,0,1,5}-{3060,9578,0,1,3}-{3054,9566,0,1,7}-" }, { "npc_id": "126", @@ -991,6 +991,10 @@ "npc_id": "334", "loc_data": "{2612,3411,0,0,0}-{2165,3268,0,0,4}-{2162,3274,0,0,4}-{2627,3415,0,0,0}-{2639,3698,0,0,4}-{2642,3698,0,0,4}-{2699,2702,0,0,4}-{2694,2706,0,0,4}-{2700,2702,0,0,4}-{2707,2698,0,0,4}-{2700,2702,0,0,0}-{2700,2702,0,0,0}-{2700,2702,0,0,0}-{2707,2698,0,0,0}-{2707,2698,0,0,0}-{2707,2698,0,0,0}-" }, + { + "npc_id": "335", + "loc_data": "{2592,3336,0,1,0}-" + }, { "npc_id": "336", "loc_data": "{2928,3218,0,1,4}-" @@ -1025,11 +1029,11 @@ }, { "npc_id": "347", - "loc_data": "{2523,3292,0,1,0}-{2536,3294,0,1,0}-{2538,3321,0,1,0}-" + "loc_data": "{2524,3292,0,1,3}-{2536,3294,0,1,3}-{2538,3321,0,1,3}-" }, { "npc_id": "348", - "loc_data": "{2501,3315,0,1,0}-{2513,3325,0,1,0}-{2526,3279,0,1,0}-{2528,3297,0,1,0}-{2535,3288,0,1,0}-{2548,3287,0,1,0}-" + "loc_data": "{2501,3315,0,1,3}-{2513,3325,0,1,3}-{2526,3279,0,1,3}-{2528,3297,0,1,3}-{2535,3288,0,1,3}-{2548,3287,0,1,3}-" }, { "npc_id": "349", @@ -1041,31 +1045,31 @@ }, { "npc_id": "351", - "loc_data": "{2507,3325,0,1,4}-" + "loc_data": "{2465,3307,0,1,0}-{2482,3293,0,1,0}-{2509,3325,0,1,0}-" }, { "npc_id": "352", - "loc_data": "{2511,3322,0,1,2}-{2540,3279,0,1,6}-" + "loc_data": "{2453,3307,0,1,0}-{2480,3300,0,1,0}-{2511,3322,0,1,0}-{2540,3279,0,1,0}-" }, { "npc_id": "353", - "loc_data": "{2504,3326,0,1,1}-{2509,3314,0,1,3}-{2545,3278,0,1,3}-" + "loc_data": "{2473,3288,0,1,0}-{2504,3326,0,1,0}-{2509,3314,0,1,0}-{2546,3277,0,1,0}-" }, { "npc_id": "354", - "loc_data": "{2510,3318,0,1,6}-{2524,3271,0,1,3}-" + "loc_data": "{2470,3290,0,1,0}-{2472,3296,0,1,0}-{2483,3318,0,1,0}-{2483,3323,0,1,0}-{2490,3293,0,1,0}-{2510,3318,0,1,0}-{2524,3271,0,1,0}-" }, { "npc_id": "355", - "loc_data": "{2504,3318,0,1,0}-" + "loc_data": "{2464,3302,0,1,0}-{2466,3300,0,1,0}-{2466,3307,0,1,0}-{2467,3306,0,1,0}-{2468,3315,0,1,0}-{2469,3319,0,1,0}-{2471,3323,0,1,0}-{2473,3305,0,1,0}-{2474,3296,0,1,0}-{2476,3307,0,1,0}-{2478,3323,0,1,0}-{2480,3296,0,1,0}-{2481,3313,0,1,0}-{2485,3312,0,1,0}-{2504,3318,0,1,0}-{2547,3277,0,1,0}-" }, { "npc_id": "356", - "loc_data": "{2523,3307,0,1,0}-" + "loc_data": "{2462,3306,0,1,0}-{2465,3305,0,1,0}-{2469,3295,0,1,0}-{2477,3320,0,1,0}-{2482,3311,0,1,0}-{2518,3275,0,1,0}-{2523,3307,0,1,0}-" }, { "npc_id": "357", - "loc_data": "{2518,3309,0,1,0}-{2526,3303,0,1,0}-{2543,3309,0,1,0}-{2550,3319,0,1,0}-{2552,3319,0,1,0}-" + "loc_data": "{2518,3309,0,1,3}-{2526,3303,0,1,3}-{2543,3309,0,1,3}-{2552,3320,0,1,3}-" }, { "npc_id": "358", @@ -1073,19 +1077,19 @@ }, { "npc_id": "360", - "loc_data": "{2550,3272,0,1,4}-" + "loc_data": "{2472,3307,0,1,0}-{2492,3314,0,1,0}-{2553,3275,0,1,0}-" }, { "npc_id": "361", - "loc_data": "{2519,3277,0,1,6}-" + "loc_data": "{2463,3317,0,1,0}-{2482,3296,0,1,0}-{2485,3315,0,1,0}-{2519,3277,0,1,0}-" }, { "npc_id": "362", - "loc_data": "{2537,3324,0,1,6}-" + "loc_data": "{2482,3286,0,1,0}-{2489,3295,0,1,0}-{2537,3324,0,1,0}-" }, { "npc_id": "363", - "loc_data": "{2513,3315,0,1,4}-" + "loc_data": "{2468,3290,0,1,0}-{2475,3325,0,1,0}-{2479,3312,0,1,0}-{2513,3315,0,1,0}-" }, { "npc_id": "364", @@ -1105,19 +1109,19 @@ }, { "npc_id": "369", - "loc_data": "{2542,3326,0,1,0}-{2545,3324,0,1,0}-{2545,3327,0,1,0}-{2552,3326,0,1,0}-{2553,3322,0,1,0}-{2553,3324,0,1,0}-" + "loc_data": "{2548,3324,0,1,3}-{2550,3326,0,1,3}-{2553,3325,0,1,3}-" }, { "npc_id": "370", - "loc_data": "{2551,3324,1,1,0}-{2551,3327,1,1,0}-" + "loc_data": "{2549,3325,1,1,0}-{2550,3327,1,1,0}-" }, { "npc_id": "371", - "loc_data": "{2547,3326,0,1,0}-{2549,3322,0,1,0}-{2550,3326,0,1,0}-{2552,3323,0,1,0}-" + "loc_data": "{2545,3326,0,1,3}-{2551,3322,0,1,3}-{2555,3324,0,1,3}-" }, { "npc_id": "372", - "loc_data": "{2561,3303,0,1,6}-{2561,3305,0,1,4}-{2559,3303,0,1,6}-{2559,3305,0,1,1}-" + "loc_data": "{2561,3305,0,1,2}-{2561,3303,0,1,7}-{2559,3304,0,1,3}-" }, { "npc_id": "373", @@ -2104,20 +2108,24 @@ "loc_data": "{2526,3319,0,0,6}-" }, { - "npc_id": "714", - "loc_data": "{2569,3333,0,1,0}-{2517,9755,0,1,0}-" + "npc_id": "715", + "loc_data": "{2541,9672,0,1,0}-" }, { "npc_id": "716", - "loc_data": "{2540,3286,0,0,1}-" + "loc_data": "{2542,3286,0,1,3}-" }, { "npc_id": "717", - "loc_data": "{2513,3294,0,1,0}-{2518,3320,0,1,0}-{2539,3273,0,0,1}-{2535,3296,0,1,0}-" + "loc_data": "{2513,3294,0,1,0}-{2518,3320,0,1,0}-{2530,3274,0,1,0}-{2535,3296,0,1,0}-" + }, + { + "npc_id": "718", + "loc_data": "{2582,3329,0,1,2}-" }, { "npc_id": "719", - "loc_data": "{2560,3288,0,0,0}-{2026,4619,0,1,6}-{2026,4615,0,0,6}-{2020,4614,0,1,1}-{2021,4614,0,1,6}-{2008,4612,0,1,3}-{2002,4613,0,1,4}-" + "loc_data": "{2560,3288,0,1,2}-" }, { "npc_id": "720", @@ -2145,11 +2153,11 @@ }, { "npc_id": "728", - "loc_data": "{2540,3308,0,1,6}-" + "loc_data": "{2540,3308,0,1,0}-" }, { "npc_id": "729", - "loc_data": "{2536,3308,0,1,4}-" + "loc_data": "{2536,3308,0,1,0}-" }, { "npc_id": "731", @@ -2273,15 +2281,15 @@ }, { "npc_id": "785", - "loc_data": "{2470,3312,0,1,0}-{2479,3315,0,1,0}-" + "loc_data": "{2468,3304,0,1,0}-{2476,3317,0,1,0}-{2478,3291,0,1,0}-{2492,3312,0,1,0}-" }, { "npc_id": "786", - "loc_data": "{2482,3313,0,1,0}-{2477,3311,0,1,0}-" + "loc_data": "{2469,3309,0,1,0}-{2475,3298,0,1,0}-{2487,3308,0,1,0}-{2490,3289,0,1,0}-" }, { "npc_id": "787", - "loc_data": "{2486,3315,0,1,0}-{2479,3313,0,1,0}-" + "loc_data": "{2476,3313,0,1,0}-{2481,3289,0,1,0}-{2490,3313,0,1,0}-{2491,3300,0,1,0}-" }, { "npc_id": "788", @@ -2707,6 +2715,10 @@ "npc_id": "970", "loc_data": "{3081,3247,0,0,1}-" }, + { + "npc_id": "971", + "loc_data": "{2464,3287,0,1,0}-" + }, { "npc_id": "1005", "loc_data": "{3057,3905,0,1,3}-" @@ -5609,11 +5621,15 @@ }, { "npc_id": "2372", - "loc_data": "{2044,4632,0,1,3}-" + "loc_data": "{2044,4628,0,1,0}-" + }, + { + "npc_id": "2373", + "loc_data": "{2037,4636,0,1,0}-{2038,4644,0,1,0}-{2041,4638,0,1,0}-{2044,4642,0,1,0}-" }, { "npc_id": "2374", - "loc_data": "{2041,4632,0,1,3}-{2037,4630,0,1,3}-{2041,4644,0,1,4}-" + "loc_data": "{2036,4633,0,0,6}-" }, { "npc_id": "2381", @@ -6209,7 +6225,23 @@ }, { "npc_id": "2783", - "loc_data": "{1995,4660,0,1,7}-{1989,4660,0,1,0}-{1989,4664,0,1,7}-{1995,4660,0,1,2}-{1997,4664,0,1,3}-{1989,4658,0,1,0}-{2001,4646,0,1,4}-{2000,4645,0,1,3}-{1997,4644,0,1,1}-{2006,4639,0,1,6}-{1999,4636,0,1,3}-" + "loc_data": "{1995,4660,0,1,7}-{1989,4660,0,1,0}-{1989,4664,0,1,7}-{1997,4664,0,1,3}-{1989,4658,0,1,0}-{2001,4646,0,1,4}-{2000,4645,0,1,3}-{1997,4644,0,1,1}-{1999,4636,0,1,3}-{2022,4665,0,1,0}-{2024,4662,0,1,0}-{2020,4660,0,1,0}-{2023,4656,0,1,0}-{2029,4660,0,1,0}-{2031,4665,0,1,0}-{2034,4661,0,1,0}-{2032,4658,0,1,0}-{1991,4653,0,1,0}-{1995,4651,0,1,0}-" + }, + { + "npc_id": "2784", + "loc_data": "{2022,4616,0,1,5}-{2024,4620,0,1,5}-" + }, + { + "npc_id": "2785", + "loc_data": "{2000,4613,0,0,0}-{2000,4611,0,0,5}-" + }, + { + "npc_id": "2786", + "loc_data": "{2008,4613,0,1,0}-" + }, + { + "npc_id": "2787", + "loc_data": "{2023,4612,0,1,0}-" }, { "npc_id": "2790", @@ -6692,12 +6724,16 @@ "loc_data": "{3139,3448,0,1,3}-" }, { - "npc_id": "3215", - "loc_data": "{2541,9672,0,1,3}-" + "npc_id": "3213", + "loc_data": "{2568,3334,0,1,0}-" + }, + { + "npc_id": "3214", + "loc_data": "{2517,9755,0,1,0}-" }, { "npc_id": "3216", - "loc_data": "{2581,3332,0,1,3}-{2534,3273,0,0,1}-" + "loc_data": "{2534,3273,0,0,1}-{2539,3273,0,0,1}-" }, { "npc_id": "3217", @@ -8141,7 +8177,7 @@ }, { "npc_id": "4686", - "loc_data": "{2804,3507,0,1,0}-{2880,9927,0,1,0}-{2887,9955,0,1,0}-{2891,9941,0,1,0}-{2824,3510,0,1,5}-{2954,3894,0,1,4}-{2950,3932,0,1,0}-{2955,3945,0,1,0}-{3213,5548,0,1,4}-" + "loc_data": "{2824,3510,0,1,5}-{2880,9927,0,1,0}-{2887,9955,0,1,0}-{2891,9941,0,1,0}-{2954,3894,0,1,4}-{2950,3932,0,1,0}-{2955,3945,0,1,0}-{3213,5548,0,1,4}-{2804,3507,0,1,0}-" }, { "npc_id": "4687", @@ -10663,14 +10699,6 @@ "npc_id": "6283", "loc_data": "{2877,5326,2,1,2}-{2857,5328,2,1,3}-{2861,5315,2,1,7}-" }, - { - "npc_id": "6339", - "loc_data": "{2547,3277,0,0,0}-" - }, - { - "npc_id": "6345", - "loc_data": "{2518,3275,0,1,0}-" - }, { "npc_id": "6346", "loc_data": "{2799,3186,0,1,7}-{2797,3169,0,0,0}-{2793,3161,0,1,3}-" diff --git a/Server/src/main/content/global/dialogue/ManDialoguePlugin.java b/Server/src/main/content/global/dialogue/ManDialoguePlugin.java index 36785504e..aeff88be1 100644 --- a/Server/src/main/content/global/dialogue/ManDialoguePlugin.java +++ b/Server/src/main/content/global/dialogue/ManDialoguePlugin.java @@ -22,7 +22,7 @@ public class ManDialoguePlugin extends DialoguePlugin { /** * The NPC ids that use this dialogue plugin. */ - private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 351, 352, 353, 354, 359, 360, 361, 362, 363, 726, 727, 728, 729, 730, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,}; + private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,}; public ManDialoguePlugin() { } diff --git a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt index 6b0b7c0d3..9cc72f6c2 100644 --- a/Server/src/main/content/global/handlers/item/TeleTabsListener.kt +++ b/Server/src/main/content/global/handlers/item/TeleTabsListener.kt @@ -1,22 +1,19 @@ package content.global.handlers.item -import core.api.inInventory -import core.api.removeItem -import core.api.teleport +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.Companion.ARDOUGNE_TELE_ATTRIBUTE +import core.api.* import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager import core.game.node.item.Item import core.game.world.map.Location -import core.api.hasRequirement; -import content.data.Quests class TeleTabsListener : InteractionListener { enum class TeleTabs(val item: Int, val location: Location, val exp: Double, val requirementCheck: (Player) -> Boolean = { true }) { ADDOUGNE_TELEPORT(8011, Location.create(2662, 3307, 0), 61.0, { - player -> hasRequirement(player, Quests.PLAGUE_CITY); + player -> getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false) }), AIR_ALTAR_TELEPORT(13599, Location.create(2978, 3296, 0), 0.0), ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0), @@ -52,9 +49,17 @@ class TeleTabsListener : InteractionListener { val tabEnum = TeleTabs.forId(tab) if (tabEnum != null && inInventory(player,tab)) { val tabloc = tabEnum.location - if (inInventory(player, tab) && tabEnum.requirementCheck(player)) { - if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) { - removeItem(player, Item(node.id, 1)) + if (inInventory(player, tab)) { + if (tabEnum.requirementCheck(player)){ + if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) { + removeItem(player, Item(node.id, 1)) + } + } + else { + when (tabEnum){ + TeleTabs.ADDOUGNE_TELEPORT -> sendMessage(player, "You need to complete Plague City to use this tablet.") + else -> sendMessage(player, "You do not have the requirements to use this tablet.") + } } } } diff --git a/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt b/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt index eee377bf4..e69de29bb 100644 --- a/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt +++ b/Server/src/main/content/global/handlers/item/withnpc/CatOnArdougneCivilian.kt @@ -1,56 +0,0 @@ -package content.global.handlers.item.withnpc - -import core.api.Container -import core.api.* -import org.rs09.consts.Items -import org.rs09.consts.NPCs -import core.game.interaction.InteractionListener -import core.game.interaction.IntType - -class CatOnArdougneCivilian: InteractionListener { - - private val civilians = intArrayOf( - NPCs.CIVILIAN_785, - NPCs.CIVILIAN_786, - NPCs.CIVILIAN_787 - ) - - private val cats = intArrayOf( - Items.PET_CAT_1561, - Items.PET_CAT_1562, - Items.PET_CAT_1563, - Items.PET_CAT_1564, - Items.PET_CAT_1565, - Items.PET_CAT_1566, - Items.OVERGROWN_CAT_1567, - Items.OVERGROWN_CAT_1568, - Items.OVERGROWN_CAT_1569, - Items.OVERGROWN_CAT_1570, - Items.OVERGROWN_CAT_1571, - Items.OVERGROWN_CAT_1572, - Items.LAZY_CAT_6551, - Items.LAZY_CAT_6552, - Items.LAZY_CAT_6553, - Items.LAZY_CAT_6554, - Items.WILY_CAT_6555, - Items.WILY_CAT_6556, - Items.WILY_CAT_6557, - Items.WILY_CAT_6558, - Items.WILY_CAT_6559, - Items.WILY_CAT_6560, - Items.HELL_CAT_7582, - Items.OVERGROWN_HELLCAT_7581, - Items.LAZY_HELL_CAT_7584, - Items.WILY_HELLCAT_7585, - ) - - override fun defineListeners() { - onUseWith(IntType.NPC,cats,*civilians){ player, used, _ -> - sendItemDialogue(player,Items.DEATH_RUNE_560,"You hand over the cat.
You are given 100 Death Runes.") - player.familiarManager.removeDetails(used.id) - removeItem(player,used,Container.INVENTORY) - addItem(player,Items.DEATH_RUNE_560,100) - return@onUseWith true - } - } -} \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java b/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java index 3c658fec2..ad8c68db8 100644 --- a/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java +++ b/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java @@ -17,6 +17,8 @@ import core.plugin.Initializable; import core.plugin.Plugin; import core.plugin.ClassScanner; +import static content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.ARDOUGNE_TELE_ATTRIBUTE; + /** * PortalChamberPlugin * @author Clayton Williams @@ -87,6 +89,12 @@ public class PortalChamberPlugin extends OptionHandler { } for (Locations l : Locations.values()) { if (l.name().contains(identifier)) { + if (l == Locations.ARDOUGNE){ + if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){ + player.sendMessage("You do not have the requirements to direct the portal there"); + return; + } + } Item[] runes = l.runes; if (!player.getInventory().containsItems(runes)) { player.sendMessage("You do not have the required runes to build this portal"); @@ -130,6 +138,12 @@ public class PortalChamberPlugin extends OptionHandler { case "enter": String objectName = object.getName(); for (Locations l : Locations.values()) { + if (l == Locations.ARDOUGNE){ + if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){ + player.sendMessage("You do not have the requirements to enter this portal."); + return false; + } + } if (objectName.toLowerCase().contains(l.name().toLowerCase())) { player.teleport(l.location); if (player.getHouseManager().isInHouse(player) && node.getId() == 13635) { diff --git a/Server/src/main/content/global/skill/construction/decoration/study/LecternPlugin.kt b/Server/src/main/content/global/skill/construction/decoration/study/LecternPlugin.kt index 826056ce3..eb4accf67 100644 --- a/Server/src/main/content/global/skill/construction/decoration/study/LecternPlugin.kt +++ b/Server/src/main/content/global/skill/construction/decoration/study/LecternPlugin.kt @@ -10,6 +10,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills import content.global.skill.construction.Decoration +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.Companion.ARDOUGNE_TELE_ATTRIBUTE import core.game.node.entity.combat.spell.MagicStaff import core.game.node.item.Item import core.game.system.task.Pulse @@ -84,6 +85,11 @@ class LecternPlugin : OptionHandler() { player.sendMessages("You need the Bones to Peaches ability purchased from MTA before making these.", "This requirement doesn't apply to actually using the tabs.") return false } + if(this == ARDOUGNE && !getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false)){ + sendMessage(player, "You need to unlock Ardougne teleport before you can make a tablet.") + return false + + } var found = false for (d in requiredDecorations) if (d.objectId == objectId) found = true if (!found) { diff --git a/Server/src/main/content/global/skill/cooking/recipe/HangoverRecipe.kt b/Server/src/main/content/global/skill/cooking/recipe/HangoverRecipe.kt new file mode 100644 index 000000000..063b85ce4 --- /dev/null +++ b/Server/src/main/content/global/skill/cooking/recipe/HangoverRecipe.kt @@ -0,0 +1,44 @@ +package content.global.skill.cooking.recipe + +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.skill.Skills +import org.rs09.consts.Items + +class HangoverRecipe : InteractionListener { + + companion object{ + private const val SNAPE_GRASS = Items.SNAPE_GRASS_231 + private const val HANGOVER_CURE = Items.HANGOVER_CURE_1504 + private const val BUCKET_OF_MILK = Items.BUCKET_OF_MILK_1927 + private const val CHOCOLATE_DUST = Items.CHOCOLATE_DUST_1975 + private const val CHOCOLATE_MILK = Items.CHOCOLATEY_MILK_1977 + } + + override fun defineListeners() { + onUseWith(IntType.ITEM, CHOCOLATE_DUST, BUCKET_OF_MILK) { player, _, _ -> + if(hasLevelDyn(player, Skills.COOKING, 4)){ + if(removeItem(player, CHOCOLATE_DUST) and removeItem(player, BUCKET_OF_MILK)){ + addItem(player, CHOCOLATE_MILK) + sendItemDialogue(player, CHOCOLATE_MILK, "You mix the chocolate into the bucket.") + } + } + else { + sendDialogue(player, "You need a Cooking level of at least 4 to make chocolate milk.") + } + return@onUseWith true + } + + onUseWith(IntType.ITEM, SNAPE_GRASS, CHOCOLATE_MILK) { player, _, _ -> + if (removeItem(player, SNAPE_GRASS) && removeItem(player, CHOCOLATE_MILK)) + { + sendItemDialogue(player, HANGOVER_CURE, "You mix the snape grass into the bucket.") + addItem(player, HANGOVER_CURE) + return@onUseWith true + } + return@onUseWith false + } + + } +} diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 1ae76e091..085f447bd 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -1,5 +1,6 @@ package content.global.skill.magic.modern +import content.data.Quests import content.global.skill.magic.SpellListener import content.global.skill.magic.SpellUtils.hasRune import content.global.skill.magic.TeleportMethod @@ -22,6 +23,7 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners import core.game.node.item.Item import core.game.world.map.Location import core.game.world.update.flag.context.Animation @@ -29,7 +31,6 @@ import core.game.world.update.flag.context.Graphics import org.rs09.consts.Items import org.rs09.consts.Scenery import org.rs09.consts.Sounds -import content.data.Quests class ModernListeners : SpellListener("modern"){ override fun defineListeners() { @@ -66,10 +67,15 @@ class ModernListeners : SpellListener("modern"){ } onCast(Modern.ARDOUGNE_TELEPORT, NONE){ player, _ -> - if (!hasRequirement(player, Quests.PLAGUE_CITY)) - return@onCast - requires(player,51, arrayOf(Item(Items.WATER_RUNE_555,2),Item(Items.LAW_RUNE_563,2))) - sendTeleport(player,61.0, Location.create(2662, 3307, 0)) + if (getAttribute(player, PlagueCityListeners.ARDOUGNE_TELE_ATTRIBUTE, false)){ + 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)) + } + else { + // source https://runescape.salmoneus.net/forums/topic/289818-ardougne-teleport-help/ + sendDialogue(player, "You haven\'t learnt how to cast this spell yet") + } + return@onCast } onCast(Modern.WATCHTOWER_TELEPORT, NONE){ player, _ -> diff --git a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java index 4e93e4fe0..53e426aa3 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java +++ b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java @@ -28,7 +28,6 @@ public class SlayerPlugin extends OptionHandler { @Override public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(8783).getHandlers().put("option:open", this); SceneryDefinition.forId(8785).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(23158).getHandlers().put("option:exit", this); SceneryDefinition.forId(23157).getHandlers().put("option:exit", this); @@ -53,9 +52,6 @@ public class SlayerPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { switch (node.getId()) { - case 8783: - player.teleport(new Location(2044, 4649, 0)); - break; case 8785: player.teleport(new Location(2543, 3327, 0)); break; diff --git a/Server/src/main/content/minigame/castlewars/areas/CastleWarsArea.kt b/Server/src/main/content/minigame/castlewars/areas/CastleWarsArea.kt index ab1089bdc..c6b336c55 100644 --- a/Server/src/main/content/minigame/castlewars/areas/CastleWarsArea.kt +++ b/Server/src/main/content/minigame/castlewars/areas/CastleWarsArea.kt @@ -65,7 +65,6 @@ abstract class CastleWarsArea : MapArea, LogoutListener, InteractionListener { defineAreaBorders().forEach { border -> if (border.insideBorder(player)) { sendMessage(player, "You can't remove your team's colours") - // TODO: Equipping a cape or helmet causes issues return@onUnequip false } } diff --git a/Server/src/main/content/region/desert/handlers/ShantayPassPlugin.java b/Server/src/main/content/region/desert/handlers/ShantayPassPlugin.java index 73a4d96dd..74ae051e1 100644 --- a/Server/src/main/content/region/desert/handlers/ShantayPassPlugin.java +++ b/Server/src/main/content/region/desert/handlers/ShantayPassPlugin.java @@ -92,7 +92,7 @@ public class ShantayPassPlugin extends OptionHandler { case "quick-pass": if (player.getLocation().getY() > 3116) { if (!inInventory(player, Items.SHANTAY_PASS_1854, 1)) { - sendNPCDialogue(player, 838, "You need a Shantay pass to get through this gate. See Shantay, he will sell you one for a very reasonable price.", FacialExpression.NEUTRAL); + sendNPCDialogue(player, 838, "You need a Shantay pass to get through this gate. See Shantay, he will sell you one for a very reasonable price.", FacialExpression.NEUTRAL, false); return true; } if (!removeItem(player, Items.SHANTAY_PASS_1854, Container.INVENTORY)) return true; diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CivilianDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CivilianDialogue.kt deleted file mode 100644 index 0dc0d3c96..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CivilianDialogue.kt +++ /dev/null @@ -1,44 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue - -import core.api.inEquipment -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.Items -import org.rs09.consts.NPCs - -@Initializable -class CivilianDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - if(inEquipment(player, Items.GAS_MASK_1506)) { - playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage = 4 } - } else { - playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage = 0 } - } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when (stage) { - 0 -> npcl(FacialExpression.FRIENDLY, "I'm a bit busy to talk right now, sorry.").also { stage++ } - 1 -> playerl(FacialExpression.FRIENDLY, "Why? What are you doing?").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "Trying to kill these mice! What I really need is a cat!").also { stage++ } - 3 -> playerl(FacialExpression.FRIENDLY, "No, you're right, you don't see many around.").also { stage = END_DIALOGUE } - 4 -> npcl(FacialExpression.FRIENDLY, "If you Mourners really wanna help, why don't you do something about these mice?!").also { stage = END_DIALOGUE } - } - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { - return CivilianDialogue(player) - } - - override fun getIds(): IntArray { - return intArrayOf(NPCs.CIVILIAN_785, NPCs.CIVILIAN_786, NPCs.CIVILIAN_787) - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt deleted file mode 100644 index 75c806a89..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/KilronDialogue.kt +++ /dev/null @@ -1,54 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue - -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.NPCs -import content.data.Quests - -@Initializable -class KilronDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)){ - npcl(FacialExpression.FRIENDLY, "Looks like you won't be needing the rope ladder any more, adventurer. I heard it was you who started the revolution and freed West Ardougne!").also { stage = END_DIALOGUE } - } else { - playerl(FacialExpression.FRIENDLY, "Hello there.") - } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when (stage) { - 0 -> npcl(FacialExpression.FRIENDLY, "Hello.").also { stage++ } - 1 -> playerl(FacialExpression.FRIENDLY, "How are you?").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "Busy.").also { stage = END_DIALOGUE } - } - return true - } - - /* After Biohazard and before Plague's End - 0 -> playerl(FacialExpression.FRIENDLY, "Hello Kilron.").also { stage++ } - 1 -> npcl(FacialExpression.FRIENDLY, "Hello traveller. Do you need to go back over?").also { stage++ } - 2 -> options("Not yet Kilron", "Yes I do").also { stage++ } - 3 -> when(buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Not yet Kilron.").also { stage = 4 } - 2 -> playerl(FacialExpression.FRIENDLY, "Yes I do.").also { stage = 5 } - } - 4 -> npcl(FacialExpression.FRIENDLY, "Okay, just give me the word.").also { stage = END_DIALOGUE } - 5 -> npcl(FacialExpression.FRIENDLY, "Okay, quickly now!").also { stage = END_DIALOGUE } - */ - - override fun newInstance(player: Player?): DialoguePlugin { - return KilronDialogue(player) - } - - override fun getIds(): IntArray { - return intArrayOf(NPCs.KILRON_349) - } - -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ManDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ManDialogue.kt deleted file mode 100644 index 006f72819..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ManDialogue.kt +++ /dev/null @@ -1,24 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue - -import core.game.dialogue.DialogueFile -import core.game.dialogue.FacialExpression -import core.plugin.Initializable -import core.tools.END_DIALOGUE - -@Initializable -class ManDialogue : DialogueFile() { - - override fun handle(componentID: Int, buttonID: Int) { - when (stage) { - 0 -> npcl(FacialExpression.HALF_GUILTY, "We don't have good days here anymore. Curse King Tyras.").also { stage++ } - 1 -> options("Oh okay, bad day then.", "Why, what has he done?", "I'm looking for a woman called Elena.").also { stage++ } - 2 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Oh okay, bad day then.").also { stage = END_DIALOGUE } - 2 -> playerl(FacialExpression.FRIENDLY, "Why, what has he done?").also { stage = 3 } - 3 -> playerl(FacialExpression.FRIENDLY, "I'm looking for a woman called Elena.").also { stage = 4 } - } - 3 -> npcl(FacialExpression.FRIENDLY, "His army curses our city with this plague then wanders off again, leaving us to clear up the pieces.").also { stage = END_DIALOGUE } - 4 -> npcl(FacialExpression.THINKING, "Not heard of her.").also { stage = END_DIALOGUE } - } - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/MournersDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/MournersDialogue.kt deleted file mode 100644 index 2b1ceaac5..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/MournersDialogue.kt +++ /dev/null @@ -1,41 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue - -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.NPCs - -@Initializable -class MournersDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - playerl(FacialExpression.FRIENDLY, "Hi.").also { stage = 0 } - return true - } - - override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when (stage) { - 0 -> npcl(FacialExpression.SAD, "What are you up to?").also { stage++ } - 1 -> playerl(FacialExpression.NEUTRAL,"Just sight-seeing.").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "This is no place for sight-seeing. Don't you know there's been a plague outbreak?").also { stage++ } - 3 -> playerl(FacialExpression.FRIENDLY, "Yes, I had heard.").also { stage++ } - 4 -> npcl(FacialExpression.FRIENDLY, "Then I suggest you leave as soon as you can.").also { stage++ } - 5 -> playerl(FacialExpression.FRIENDLY, "Thanks for the advice.").also { stage = END_DIALOGUE } - } - return true - } - - override fun newInstance(player: Player?): DialoguePlugin { - return MournersDialogue(player) - } - - override fun getIds(): IntArray { - return intArrayOf( - NPCs.MOURNER_347, NPCs.MOURNER_348, NPCs.MOURNER_357, NPCs.MOURNER_369, NPCs.MOURNER_371, NPCs.MOURNER_370) - } - -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/WomanDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/WomanDialogue.kt deleted file mode 100644 index 7e7b14fdd..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/WomanDialogue.kt +++ /dev/null @@ -1,61 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue - -import core.game.dialogue.DialogueFile -import core.game.dialogue.FacialExpression -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import core.tools.RandomFunction - -@Initializable -class WomanDialogue : DialogueFile() { - - override fun handle(componentID: Int, buttonID: Int) { - when (RandomFunction.random(1,4)) { - 1 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello, how's it going?").also { stage++ } - 1 -> npcl(FacialExpression.FRIENDLY, "Bah, those mourners... they're meant to be helping us, but I think they're doing more harm here than good. They won't even let me send a letter out to my family.").also { stage++ } - 2 -> options("Have you seen a lady called Elena around here?", "You should stand up to them more.").also { stage++ } - 3 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Have you seen a lady called Elena around here?").also { stage = 4 } - 2 -> playerl(FacialExpression.FRIENDLY, "You should stand up to them more.").also { stage = 6 } - } - 4 -> npcl(FacialExpression.FRIENDLY, "Yes, I've seen her. Very helpful person.").also { stage++ } - 5 -> npcl(FacialExpression.FRIENDLY, "Not for the last few days though... I thought maybe she'd gone home.").also { stage = END_DIALOGUE } - 6 -> npcl(FacialExpression.FRIENDLY, "Oh I'm not one to cause a fuss.").also { stage = END_DIALOGUE } - } - - 2 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello, how's it going?").also { stage++ } - 1 -> npcl(FacialExpression.FRIENDLY, "Life is tough.").also { stage++ } - 2 -> options("Yes, living in a plague city must be hard.", "I'm sorry to hear that.", "I'm looking for a lady called Elena.").also { stage++ } - 3 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Yes, living in a plague city must be hard.").also { stage = 4 } - 2 -> playerl(FacialExpression.FRIENDLY, "I'm sorry to hear that.").also { stage = 6 } - 3 -> playerl(FacialExpression.FRIENDLY, "I'm looking for a lady called Elena.").also { stage = 7 } - } - 4 -> npcl(FacialExpression.FRIENDLY, "Plague? Pah, that's no excuse for the treatment we've received. It's obvious pretty quickly if someone has the plague.").also { stage++ } - 5 -> npcl(FacialExpression.FRIENDLY, "I'm thinking about making a break for it. I'm perfectly healthy, not gonna infect anyone.").also { stage = END_DIALOGUE } - 6 -> npcl(FacialExpression.FRIENDLY, "Well, ain't much either you or me can do about it.").also { stage = END_DIALOGUE } - 7 -> npcl(FacialExpression.FRIENDLY, "I've not heard of her. Old Jethick knows a lot of people, maybe he'll know where you can find her.").also { stage = END_DIALOGUE } - } - - 3 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello, how's it going?").also { stage++ } - 1 -> npcl(FacialExpression.FRIENDLY, "We don't have good days here anymore. Curse King Tyras.").also { stage++ } - 2 -> options("Oh okay, bad day then.", "Why, what has he done?", "I'm looking for a woman called Elena.").also { stage++ } - 3 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Oh okay, bad day then.").also { stage = END_DIALOGUE } - 2 -> playerl(FacialExpression.FRIENDLY, "Why, what has he done?").also { stage = 4 } - 3 -> playerl(FacialExpression.FRIENDLY, "I'm looking for a lady called Elena.").also { stage = 5 } - } - 4 -> npcl(FacialExpression.FRIENDLY, "His army curses our city with this plague then wanders off again, leaving us to clear up the pieces.").also { stage = END_DIALOGUE } - 5 -> npcl(FacialExpression.FRIENDLY, "Not heard of her.").also { stage = END_DIALOGUE } - } - 4 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello, how's it going?").also { stage++ } - 1 -> npcl(FacialExpression.HALF_ASKING, "An outsider! Can you get me out of this hell hole?").also { stage++ } - 2 -> playerl(FacialExpression.HALF_GUILTY, "Sorry, that's not what I'm here to do.").also { stage = END_DIALOGUE } - } - } - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt deleted file mode 100644 index 00b3d95e4..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/BravekDialogue.kt +++ /dev/null @@ -1,117 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena - -import core.api.* -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.Items -import org.rs09.consts.NPCs -import content.data.Quests - -@Initializable -class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 0) { - npcl(FacialExpression.ANGRY, "Go away, I'm busy! I'm... Um... In a meeting!").also { stage = END_DIALOGUE } - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 13) { - npcl(FacialExpression.NEUTRAL, "My head hurts! I'll speak to you another day...").also { stage = 1 } - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 14) { - npcl(FacialExpression.NEUTRAL, "Uurgh! My head still hurts too much to think straight. Oh for one of Trudi's hangover cures!").also { stage = 1 } - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 16) { - npcl(FacialExpression.NEUTRAL, "Thanks again for the hangover cure.").also { stage = 1 } - } else { - npcl(FacialExpression.ANGRY, "Go away, I'm busy! I'm... Um... In a meeting!").also { stage = END_DIALOGUE } - } - return true - } - - override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { - - 13 -> when (stage) { - 1 -> playerl(FacialExpression.FRIENDLY, "This is really important though!").also { stage = 2 } - 2 -> npcl(FacialExpression.FRIENDLY, "I can't possibly speak to you with my head spinning like this... I went a bit heavy on the drink last night.").also { stage++ } - 3 -> npcl(FacialExpression.FRIENDLY, "Curse my herbalist, she made the best hangover cures. Darn inconvenient of her catching the plague.").also { stage++ } - 4 -> options("You shouldn't drink so much then!", "Do you know what's in the cure?", "Okay, goodbye.").also { stage++ } - 5 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "You shouldn't drink so much then!").also { stage = 7 } - 2 -> playerl(FacialExpression.FRIENDLY, "Do you know what's in the cure?").also { stage = 20 } - 3 -> playerl(FacialExpression.FRIENDLY, "Okay, goodbye.").also { stage = END_DIALOGUE } - } - 7 -> npcl(FacialExpression.FRIENDLY, "Well positions of responsibility are hard, I need something to take my mind off things... Especially with the problems this place has..").also { stage++ } - 8 -> playerl(FacialExpression.FRIENDLY, "I don't think drink is the solution.").also { stage++ } - 9 -> npcl(FacialExpression.FRIENDLY, "Uurgh! My head still hurts too much to think straight. Oh for one of Trudi's hangover cures!").also { stage++ } - 10 -> npcl(FacialExpression.FRIENDLY, "I'll see what I can do I suppose. Mr. Bravek, there's someone here who really needs to speak to you.").also { stage++ } - 11 -> sendNPCDialogue(player!!, NPCs.BRAVEK_711, "I suppose they can come in then. If they keep it short.").also { stage = END_DIALOGUE } - 20 -> npcl(FacialExpression.FRIENDLY, "Hmmm let me think... Ouch! Thinking isn't clever. Ah here, she did scribble it down for me.").also { stage++ } - 21 -> if (freeSlots(player!!) == 0) { - end() - sendItemDialogue(player!!, Items.A_SCRUFFY_NOTE_1508, "Bravek waves a tatty piece of paper at you, but you don't have room to take it.").also { stage = END_DIALOGUE } - } else { - end() - sendItemDialogue(player!!, Items.A_SCRUFFY_NOTE_1508, "Bravek hands you a tatty piece of paper.").also { stage++ } - addItem(player!!, Items.A_SCRUFFY_NOTE_1508) - setQuestStage(player!!, Quests.PLAGUE_CITY, 14) - } - } - - 14 -> when (stage) { - 1 -> if(removeItem(player!!, Items.HANGOVER_CURE_1504)) { - playerl(FacialExpression.FRIENDLY, "Try this.").also { stage++ } - } else { - end() - stage = END_DIALOGUE - } - 2 -> { - animate(npc, 1330) // Drink hangover cure. - findLocalNPC(player!!, NPCs.BRAVEK_711)!!.sendChat("Grruurgh!") - sendItemDialogue(player!!, Items.HANGOVER_CURE_1504, "You give Bravek the hangover cure.").also { stage++ } - } - 3 -> sendDialogue(player!!, "Bravek gulps down the foul-looking liquid.").also { stage++ } - 4 -> npcl(FacialExpression.NEUTRAL, "Ooh that's much better! Thanks, that's the clearest my head has felt in a month. Ah now, what was it you wanted me to do for you?").also { stage++ } - 5 -> playerl(FacialExpression.FRIENDLY, "I need to rescue a kidnap victim named Elena. She's being held in a plague house, I need permission to enter.").also { stage++ } - 6 -> options("Ok, I'll go speak to them.", "Is that all anyone says around here?", "They won't listen to me!").also { stage++ } - 7 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Ok, I'll go speak to them.").also { stage = 6 } - 2 -> playerl(FacialExpression.FRIENDLY, "Is that all anyone says around here?").also { stage = 11 } - 3 -> playerl(FacialExpression.FRIENDLY, "They won't listen to me! They say I'm not properly equipped to go in the house, though I do have a very effective gasmask.").also { stage++ } - } - 8 -> npcl(FacialExpression.FRIENDLY, "Hmmm, well I guess they're not taking the issue of a kidnapping seriously enough. They do go a bit far sometimes.").also { stage++ } - 9 -> npcl(FacialExpression.FRIENDLY, "I've heard of Elena, she has helped us a lot... Ok, I'll give you this warrant to enter the house.").also { stage = 17 } - 11 -> npcl(FacialExpression.FRIENDLY, "Well, they know best about plague issues.").also { stage++ } - 12 -> playerl(FacialExpression.FRIENDLY, "Don't you want to take an interest in it at all?").also { stage++ } - 13 -> npcl(FacialExpression.FRIENDLY, "Nope, I don't wish to take a deep interest in plagues. That stuff is too scary for me!").also { stage++ } - 14 -> playerl(FacialExpression.FRIENDLY, "I can see why people say you're a weak leader.").also { stage++ } - 15 -> npcl(FacialExpression.FRIENDLY, "Bah, people always criticise their leaders but delegating is the only way to lead. I delegate all plague issues to the mourners.").also { stage++ } - 16 -> playerl(FacialExpression.FRIENDLY, "This whole city is a plague issue!").also { stage = 6 } - 17 -> if (freeSlots(player!!) == 0) { - end() - sendItemDialogue(player!!, Items.WARRANT_1503, "Bravek waves a warrant at you, but you don't have room to take it.").also { stage = END_DIALOGUE } - } else { - end() - sendItemDialogue(player!!, Items.WARRANT_1503, "Bravek hands you a warrant.").also { stage = END_DIALOGUE } - addItem(player!!, Items.WARRANT_1503) - setQuestStage(player!!, Quests.PLAGUE_CITY, 16) - } - } - - 16 -> when (stage) { - 1 -> playerl(FacialExpression.NEUTRAL, "Not a problem, happy to help out.").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "I'm just having a little drop of whisky, then I'll feel really good.").also { stage = END_DIALOGUE } - } - - in 17..100 -> when (stage) { - 1 -> playerl(FacialExpression.FRIENDLY, "Not a problem, happy to help out.").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "I'm just having a little drop of whisky, then I'll feel really good.").also { stage = END_DIALOGUE } - } - } - return true - } - - override fun getIds(): IntArray = intArrayOf(NPCs.BRAVEK_711) -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt deleted file mode 100644 index 485367c39..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ClerkDialogue.kt +++ /dev/null @@ -1,95 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena - -import core.api.getQuestStage -import core.api.sendNPCDialogue -import core.api.setQuestStage -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.NPCs -import content.data.Quests - -@Initializable -class ClerkDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - npcl(FacialExpression.NEUTRAL, "Hello, welcome to the Civic Office of West Ardougne. How can I help you?").also { stage = 0 } - return true - } - - override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { - - 11 -> when (stage) { - 0 -> options("Who is through that door?", "I'm just looking thanks.").also { stage++ } - 1 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Who is through that door?").also { stage = 2 } - 2 -> playerl(FacialExpression.FRIENDLY, "I'm just looking thanks.").also { stage = END_DIALOGUE } - } - 2 -> npcl(FacialExpression.FRIENDLY, "The city warder Bravek is in there.").also { stage++ } - 3 -> playerl(FacialExpression.FRIENDLY,"Can I go in?").also { stage++ } - 4 -> npcl(FacialExpression.FRIENDLY, "He has asked not to be disturbed.").also { stage = END_DIALOGUE } - } - - 12 -> when (stage) { - 0 -> options("I need permission to enter a plague house.", "Who is through that door?", "I'm just looking thanks.").also { stage++ } - 1 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "I need permission to enter a plague house.").also { stage = 2 } - 2 -> playerl(FacialExpression.FRIENDLY, "Who is through that door?").also { stage = 12 } - 3 -> playerl(FacialExpression.FRIENDLY, "I'm just looking thanks.").also { stage = END_DIALOGUE } - } - 2 -> npcl(FacialExpression.FRIENDLY, "Rather you than me! The mourners usually deal with that stuff, you should speak to them. Their headquarters are right near the city gate.").also { stage++ } - 3 -> options("I'll try asking them then.", "Surely you don't let them run everything for you?").also { stage++ } - 4 -> when (buttonID) { - 1 -> playerl(FacialExpression.HALF_GUILTY, "I'll try asking them then.").also { stage = END_DIALOGUE } - 2 -> playerl(FacialExpression.HALF_GUILTY, "Surely you don't let them run everything for you?").also { stage = 5 } - } - 5 -> npcl(FacialExpression.FRIENDLY, "Well, they do know what they're doing here. If they did start doing something badly Bravek, the city warder, would have the power to override them. I can't see that happening though.").also { stage++ } - 6 -> options("I'll try asking them then.", "Can I speak to Bravek anyway?", "This is urgent though! Someone's been kidnapped!").also { stage++ } - 7 -> when (buttonID) { - 1 -> playerl(FacialExpression.HALF_GUILTY, "I'll try asking them then.").also { stage = END_DIALOGUE } - 2 -> playerl(FacialExpression.HALF_GUILTY, "Can I speak to Bravek anyway?").also { stage = 8 } - 3 -> playerl(FacialExpression.HALF_GUILTY, "This is urgent though! Someone's been kidnapped!").also { stage = 11 } - } - 8 -> npcl(FacialExpression.FRIENDLY, "He has asked not to be disturbed.").also { stage++ } - 9 -> options("This is urgent though! Someone's been kidnapped!", "Okay, I'll leave him alone.", "Do you know when he will be available?").also { stage++ } - 10 -> when (buttonID) { - 1 -> playerl(FacialExpression.HALF_GUILTY, "This is urgent though! Someone's been kidnapped!").also { stage = 11 } - 2 -> playerl(FacialExpression.HALF_GUILTY, "Okay, I'll leave him alone.").also { stage = END_DIALOGUE } - 3 -> playerl(FacialExpression.HALF_GUILTY, "Do you know when he will be available?").also { stage = 14 } - } - 11 -> npcl(FacialExpression.HALF_GUILTY, "I'll see what I can do I suppose.").also { stage++ } - 12 -> npcl(FacialExpression.HALF_GUILTY, "Mr Bravek, there's a man here who really needs to speak to you.").also { stage++ } - 13 -> { - end() - setQuestStage(player!!, Quests.PLAGUE_CITY, 13) - sendNPCDialogue(player!!, NPCs.BRAVEK_711, "I suppose they can come in then. If they keep it short.").also { stage++ } - } - 14 -> npcl(FacialExpression.HALF_GUILTY, "Oh I don't know, an hour or so maybe.").also { stage = END_DIALOGUE } - } - - in 13..15 -> when (stage) { - 0 -> npcl(FacialExpression.FRIENDLY, "Bravek will see you now but keep it short!").also { stage++ } - 1 -> playerl(FacialExpression.FRIENDLY, "Thanks, I won't take much of his time.").also { stage = END_DIALOGUE } - } - - in 16..100 -> when (stage) { - 0 -> options("Who is through that door?", "I'm just looking thanks.").also { stage++ } - 1 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Who is through that door?").also { stage = 2 } - 2 -> playerl(FacialExpression.FRIENDLY, "I'm just looking thanks.").also { stage = END_DIALOGUE } - } - 2 -> npcl(FacialExpression.FRIENDLY, "The city warder Bravek is in there.").also { stage++ } - 3 -> playerl(FacialExpression.FRIENDLY,"Can I go in?").also { stage++ } - 4 -> npcl(FacialExpression.FRIENDLY, "I suppose so.").also { stage = END_DIALOGUE } - } - } - return true - } - - override fun getIds(): IntArray = intArrayOf(NPCs.CLERK_713) -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt deleted file mode 100644 index eae81dfa8..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/EdmondDialogue.kt +++ /dev/null @@ -1,168 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena - -import core.api.* -import core.game.dialogue.DialoguePlugin -import core.game.dialogue.FacialExpression -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.Items -import org.rs09.consts.NPCs -import content.data.Quests - -@Initializable -class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { - - override fun open(vararg args: Any?): Boolean { - npc = args[0] as NPC - if(inEquipmentOrInventory(player, Items.GAS_MASK_1506) && (player.questRepository.getStage(Quests.PLAGUE_CITY) == 2)) { - playerl(FacialExpression.FRIENDLY, "Hi Edmond, I've got the gas mask now.").also { stage++ } - } else if(player.questRepository.getStage(Quests.PLAGUE_CITY) > 2) { - playerl(FacialExpression.FRIENDLY, "Hello Edmond.").also { stage++ } - } else { - playerl(FacialExpression.FRIENDLY, "Hello old man.").also { stage++ } - } - return true - } - - override fun handle(componentID: Int, buttonID: Int): Boolean { - when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { - - 0 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Sorry, I can't stop to talk...").also { stage++ } - 2 -> playerl(FacialExpression.FRIENDLY, "Why, what's wrong?").also { stage++ } - 3 -> npcl(FacialExpression.FRIENDLY, "I've got to find my daughter. I pray that she is still alive...").also { stage++ } - 4 -> options("What's happened to her?", "Well, good luck finding her.").also { stage++ } - 5 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "What's happened to her?").also { stage = 6 } - 2 -> playerl(FacialExpression.FRIENDLY, "Well, good luck finding her.").also { stage = END_DIALOGUE } - } - 6 -> npcl(FacialExpression.NEUTRAL, "Elena's a missionary and a healer. Three weeks ago she managed to cross the Ardougne wall...").also { stage++ } - 7 -> npcl(FacialExpression.NEUTRAL, "No-one's allowed to cross the wall in case they spread the plague. But after hearing the screams of suffering she felt she had to help.").also { stage++ } - 8 -> npcl(FacialExpression.NEUTRAL, "She said she'd be gone for a few days but we've heard nothing since.").also { stage++ } - 9 -> options("Tell me more about the plague.", "Can I help find her?", "I'm sorry, I have to go.").also { stage++ } - 10 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Tell me more about the plague.").also { stage = 12 } - 2 -> playerl(FacialExpression.FRIENDLY, "Can I help find her?").also { stage = 13 } - 3 -> playerl(FacialExpression.FRIENDLY, "I'm sorry, I have to go.").also { stage = END_DIALOGUE } - } - 12 -> npcl(FacialExpression.FRIENDLY, "The mourners can tell you more than me. They're the only ones allowed to cross the border. I do know the plague is a horrible way to go... That's why Elena felt she had to go help.").also { stage = 9 } - 13 -> npcl(FacialExpression.FRIENDLY, "Really, would you? I've been working on a plan to get into West Ardougne, but I'm too old and tired to carry it through.").also { stage++ } - 14 -> npcl(FacialExpression.FRIENDLY, "If you're going into West Ardougne you'll need protection from the plague. My wife made a special gas mask for Elena with dwellberries rubbed into it.").also { stage++ } - 15 -> npcl(FacialExpression.FRIENDLY, "Dwellberries help repel the virus! We need some more though...").also { stage++ } - 16 -> playerl(FacialExpression.ASKING, "Where can I find these dwellberries?").also { stage++ } - 17 -> npcl(FacialExpression.FRIENDLY, "The only place I know of is McGrubor's Wood just north of the Rangers' Guild.").also { stage++ } - 18 -> playerl(FacialExpression.FRIENDLY, "Ok, I'll go and get some.").also { stage++ } - 19 -> npcl(FacialExpression.NEUTRAL, "The foresters keep a close eye on it, but there is a back way in.").also { stage++ } - 20 -> { - end() - setQuestStage(player!!, Quests.PLAGUE_CITY, 1) - } - } - - 1 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Have you got the dwellberries yet?").also { stage++ } - 2 -> if (!inInventory(player, Items.DWELLBERRIES_2126)) { - playerl(FacialExpression.FRIENDLY, "Sorry, I'm afraid not.").also { stage = 3 } - } else { - playerl(FacialExpression.FRIENDLY, "Yes I've got some here.").also { stage = 6 } - } - 3 -> npcl(FacialExpression.NEUTRAL, "You'll probably find them in McGrubor's Wood it's just west of Seers village.").also { stage++ } - 4 -> playerl(FacialExpression.NEUTRAL, "Ok, I'll go and get some.").also { stage++ } - 5 -> npcl(FacialExpression.NEUTRAL, "The foresters keep a close eye on it, but there is a back way in.").also { stage = END_DIALOGUE } - 6 -> npcl(FacialExpression.NEUTRAL, "Take them to my wife Alrena, she's inside.").also { stage = END_DIALOGUE } - } - - 2 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Good stuff, now for the digging. Beneath us are the Ardougne sewers, there you'll find the access to West Ardougne.").also { stage++ } - 2 -> npcl(FacialExpression.NEUTRAL, "The problem is the soil is rock hard. You'll need to pour on several buckets of water to soften it up. I'll keep an eye out for the mourners.").also { stage++ } - 3 -> { - end() - setQuestStage(player!!, Quests.PLAGUE_CITY, 3) - } - } - - 3 -> when (stage) { - 1 -> if (player!!.getAttribute("/save:elena:dig", false) == true) { - playerl(FacialExpression.NEUTRAL, "I've soaked the soil with water.").also { stage = 3 } - } else { - npcl(FacialExpression.FRIENDLY, "How's it going?").also { stage = 2 } - } - 2 -> if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 1) { - playerl(FacialExpression.NEUTRAL, "I still need to pour three more buckets of water on the soil.").also { stage = END_DIALOGUE } - } else if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 2){ - playerl(FacialExpression.NEUTRAL, "I still need to pour two more buckets of water on the soil.").also { stage = END_DIALOGUE } - } else if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 3) { - playerl(FacialExpression.NEUTRAL, "I still need to pour one more bucket of water on the soil.").also { stage = END_DIALOGUE } - } - 3 -> npcl(FacialExpression.FRIENDLY, "That's great, it should be soft enough to dig through now.").also { stage = END_DIALOGUE } - } - - 4 -> when (stage) { - 1 -> npcl(FacialExpression.FRIENDLY, "I think it's the pipe to the south that comes up in West Ardougne.").also { stage++ } - 2 -> playerl(FacialExpression.NEUTRAL, "Alright I'll check it out.").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "Once you're in the city look for a man called Jethick, he's an old friend and should help you. Send him my regards, I haven't seen him since before Elena was born.").also { stage++ } - 4 -> playerl(FacialExpression.NEUTRAL, "Alright, thanks I will.").also { stage = END_DIALOGUE } - } - - 5 -> when (stage) { - 1 -> playerl(FacialExpression.NEUTRAL, "Edmond, I can't get through to West Ardougne! There's an iron grill blocking my way, I can't pull it off alone.").also { stage++ } - 2 -> npcl(FacialExpression.NEUTRAL, "If you get some rope you could tie to the grill, then we could both pull it at the same time.").also { stage = END_DIALOGUE } - } - - 6 -> when (stage) { - 1 -> playerl(FacialExpression.NEUTRAL, "I've tied a rope to the grill over there, will you help me pull it off?").also { stage++ } - 2 -> npcl(FacialExpression.NEUTRAL, "Alright, let's get to it...").also { stage++ } - 3 -> { - end() - UndergroundCutscene(player!!).start() - } - } - - 7 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Have you found Elena yet?").also { stage++ } - 2 -> playerl(FacialExpression.NEUTRAL, "Not yet, it's a big city over there.").also { stage++ } - 3 -> npcl(FacialExpression.FRIENDLY, "Don't forget to look for my friend Jethick. He may be able to help.").also { stage = END_DIALOGUE } - } - - 8 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Have you found Elena yet?").also { stage++ } - 2 -> playerl(FacialExpression.NEUTRAL, "Not yet, it's a big city over there. Do you have a picture of Elena?").also { stage++ } - 3 -> npcl(FacialExpression.FRIENDLY, "There should be a picture of Elena in the house. Please find her quickly, I hope it's not too late.").also { stage = END_DIALOGUE } - } - - 99 -> when (stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "Thank you, thank you! Elena beat you back by minutes.").also { stage++ } - 2 -> npcl(FacialExpression.NEUTRAL, "Now I said I'd give you a reward. What can I give you as a reward I wonder?").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "Here take this magic scroll, I have little use for it but it may help you.").also { stage++ } - 4 -> { - end() - player!!.questRepository.getQuest(Quests.PLAGUE_CITY).finish(player) - } - } - - 100 -> when (stage) { - 1 -> if (!inInventory(player!!, Items.ARDOUGNE_TELEPORT_8011)) { - npcl(FacialExpression.FRIENDLY, "Ah hello again, and thank you again for rescuing my daughter.").also { stage = 2 } - } else { - npcl(FacialExpression.FRIENDLY, "Ah hello again, and thank you again for rescuing my daughter.").also { stage = 5 } - } - 2 -> options("Do you have any more of those scrolls?", "No problem.").also { stage++ } - 3 -> when (buttonID) { - 1 -> playerl(FacialExpression.NEUTRAL, "Do you have any more of those scrolls?").also { stage = 4 } - 2 -> playerl(FacialExpression.NEUTRAL, "No problem.").also { stage = END_DIALOGUE } - } - 4 -> npcl(FacialExpression.FRIENDLY, "Here take this magic scroll, I have little use for it but it may help you.").also { stage = 6 } - 5 -> playerl(FacialExpression.NEUTRAL, "No problem.").also { stage = END_DIALOGUE } - 6 -> { - end() - addItemOrDrop(player!!, Items.A_MAGIC_SCROLL_1505) - } - } - } - return true - } - - override fun getIds(): IntArray = intArrayOf(NPCs.EDMOND_714) -} diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt deleted file mode 100644 index 450e37ae5..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MournerDialogue.kt +++ /dev/null @@ -1,87 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena - -import core.api.* -import core.game.dialogue.DialogueFile -import core.game.dialogue.FacialExpression -import core.game.global.action.DoorActionHandler -import core.game.node.entity.npc.NPC -import core.game.world.map.RegionManager.getObject -import core.plugin.Initializable -import core.tools.END_DIALOGUE -import org.rs09.consts.NPCs -import content.data.Quests - -@Initializable -class MournerDialogue : DialogueFile() { - override fun handle(componentID: Int, buttonID: Int) { - npc = NPC(NPCs.MOURNER_3216) - when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { - - in 0..6 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello.").also { stage++ } - 1 -> npcl(FacialExpression.NEUTRAL, "What are you up to with old man Edmond?").also { stage++ } - 2 -> playerl(FacialExpression.FRIENDLY, "Nothing, we've just been chatting.").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "What about his daughter?").also { stage++ } - 4 -> playerl(FacialExpression.FRIENDLY, "you know about that then?").also { stage++ } - 5 -> npcl(FacialExpression.NEUTRAL, "We know about everything that goes on in Ardougne. We have to if we are to contain the plague.").also { stage++ } - 6 -> playerl(FacialExpression.FRIENDLY, "Have you see his daughter recently?").also { stage++ } - 7 -> npcl(FacialExpression.NEUTRAL, "I imagine she's caught the plague. Either way she won't be allowed out of West Ardougne, the risk is too great.").also { stage == END_DIALOGUE } - } - - 7 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } - 1 -> npcl(FacialExpression.NEUTRAL, "Been digging have we?").also { stage++ } - 2 -> playerl(FacialExpression.FRIENDLY, "What do you mean?").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "Your hands are covered in mud.Player: Oh that...").also { stage++ } - 4 -> npcl(FacialExpression.NEUTRAL, "Funny, you don't look like the gardening type.").also { stage++ } - 5 -> playerl(FacialExpression.FRIENDLY, "Oh no, I love gardening! It's my favorite pastime.").also { stage = END_DIALOGUE } - } - - 8 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } - 1 -> npcl(FacialExpression.NEUTRAL, "Do you have a problem traveller?").also { stage++ } - 2 -> playerl(FacialExpression.NEUTRAL, "No, I just wondered why you're wearing that outfit... Is it fancy dress?").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "No! It's for protection.").also { stage++ } - 4 -> playerl(FacialExpression.NEUTRAL, "Protection from what?").also { stage++ } - 5 -> npcl(FacialExpression.FRIENDLY, "The plague of course...").also { stage = END_DIALOGUE } - } - - in 9..15 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } - 1 -> npcl(FacialExpression.NEUTRAL, "Can I help you?").also { stage++ } - 2 -> playerl(FacialExpression.NEUTRAL, "What are you doing?").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "I'm guarding the border to West Ardougne. No-one except we mourners can pass through.").also { stage++ } - 4 -> playerl(FacialExpression.NEUTRAL, "Why?").also { stage++ } - 5 -> npcl(FacialExpression.FRIENDLY, "The plague of course. We can't risk cross contamination.").also { stage++ } - 6 -> playerl(FacialExpression.FRIENDLY, "Ok then, see you around.").also { stage++ } - 7 -> npcl(FacialExpression.FRIENDLY, "Maybe...").also { stage = END_DIALOGUE } - } - - 16 -> when (stage) { - 0 -> if (inBorders(player!!, 2532, 3272, 2534, 3273)) { - player!!.dialogueInterpreter.sendDialogue("The door won't open.", "You notice a black cross on the door.").also { stage = END_DIALOGUE } - } else { - playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } - } - 1 -> playerl(FacialExpression.FRIENDLY, "I have a warrant from Bravek to enter here.").also { stage++ } - 2 -> npcl(FacialExpression.NEUTRAL, "This is highly irregular. Please wait...").also { stage++ } - 3 -> { - runTask(player!!, 0) { - findLocalNPC(player!!, NPCs.MOURNER_717)!!.sendChat("Hay... I got someone here with a warrant from Bravek, what should we do?") - findLocalNPC(player!!, NPCs.MOURNER_3216)!!.sendChat("Well you can't let them in...", 1) - }.also { - end() - setQuestStage(player!!, Quests.PLAGUE_CITY, 17) - DoorActionHandler.handleAutowalkDoor(player, getObject(location(2540, 3273, 0))!!.asScenery()) - sendDialogue(player!!, "You wait until the mourner's back is turned and sneak into the building.") - } - } - } - - in 17..100 -> when (stage) { - 0 -> playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } - 1 -> npcl(FacialExpression.FRIENDLY, "I'd stand away from there. That black cross means that house has been touched by the plague.").also { stage = END_DIALOGUE } - } - } - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt b/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt deleted file mode 100644 index d7f508651..000000000 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCityListeners.kt +++ /dev/null @@ -1,457 +0,0 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena - -import content.region.kandarin.ardougne.plaguecity.dialogue.ManDialogue -import content.region.kandarin.ardougne.plaguecity.dialogue.WomanDialogue -import core.api.* -import core.game.dialogue.DialogueFile -import core.game.dialogue.FacialExpression -import core.game.global.action.DoorActionHandler -import core.game.interaction.IntType -import core.game.interaction.InteractionListener -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.game.system.task.Pulse -import core.game.world.map.Direction -import core.game.world.map.Location -import core.tools.END_DIALOGUE -import org.rs09.consts.Items -import org.rs09.consts.NPCs -import org.rs09.consts.Scenery -import content.data.Quests - -class PlagueCityListeners : InteractionListener { - companion object { - - const val BUCKET_USES_ATTRIBUTE = "/save:elena:bucket" - - const val BRAVEK = NPCs.BRAVEK_711 - const val HEAD_MOURNER = NPCs.HEAD_MOURNER_716 - const val BILLI = 723 - - val MANS = intArrayOf(NPCs.MAN_728,NPCs.MAN_729, NPCs.MAN_351) - val WOMANS = intArrayOf(NPCs.WOMAN_352, NPCs.WOMAN_353, NPCs.WOMAN_354, NPCs.WOMAN_360, NPCs.WOMAN_362, NPCs.WOMAN_363) - - const val MUD_PILE = Scenery.MUD_PILE_2533 - const val GRILL = Scenery.GRILL_11423 - const val MUD_PATCH = Scenery.MUD_PATCH_11418 - const val PIPE = Scenery.PIPE_2542 - const val WARDROBE = Scenery.WARDROBE_2525 - const val LEFT_DOOR = Scenery.ARDOUGNE_WALL_DOOR_9738 - const val RIGHT_DOOR = Scenery.ARDOUGNE_WALL_DOOR_9330 - const val PLAGUE_TED_DOORS = Scenery.DOOR_2537 - const val HEAD_DOORS = Scenery.DOOR_35991 - const val BARREL = Scenery.BARREL_2530 - const val SPOOKY_STAIRS_DOWN = Scenery.SPOOKY_STAIRS_2522 - const val SPOOKY_STAIRS_UP = Scenery.SPOOKY_STAIRS_2523 - const val PRISON_DOORS = Scenery.DOOR_2526 - const val BRAVEK_DOORS = Scenery.DOOR_2528 - const val MANHOLE_CLOSED = Scenery.MANHOLE_2543 - const val MANHOLE_OPEN = Scenery.MANHOLE_2544 - const val MANHOLE_COVER = Scenery.MANHOLE_COVER_2545 - - private const val SNAPE_GRASS = Items.SNAPE_GRASS_231 - private const val SPADE = Items.SPADE_952 - private const val ROPE = Items.ROPE_954 - private const val HANGOVER_CURE = Items.HANGOVER_CURE_1504 - private const val MAGIC_SCROLL = Items.A_MAGIC_SCROLL_1505 - private const val GAS_MASK = Items.GAS_MASK_1506 - private const val SMALL_KEY = Items.A_SMALL_KEY_1507 - private const val SCRUFFY_NOTE = Items.A_SCRUFFY_NOTE_1508 - private const val BOOK = Items.BOOK_1509 - private const val EMPTY_BUCKET = Items.BUCKET_1925 - private const val BUCKET_OF_MILK = Items.BUCKET_OF_MILK_1927 - private const val BUCKET_OF_WATER = Items.BUCKET_OF_WATER_1929 - private const val CHOCOLATE_DUST = Items.CHOCOLATE_DUST_1975 - private const val CHOCOLATE_MILK = Items.CHOCOLATEY_MILK_1977 - - private const val TRYING_TO_OPEN_GRILL = 3192 - private const val POUR_THE_WATER = 2283 - private const val CLIMB_LADDER = 828 - private const val GO_INTO_PIPE = 10580 - private const val TIE_THE_ROPE = 3191 - private const val DIG_WITH_SPADE = 830 - - } - - override fun defineListeners() { - - on(BILLI, IntType.NPC, "talk-to") { player, _ -> - sendMessage(player, "Billy isn't interested in talking.") - return@on true - } - - on(HEAD_MOURNER, IntType.NPC, "talk-to") { player, _ -> - openDialogue(player, HeadMournerDialogue()) - return@on true - } - - on(MANS, IntType.NPC, "talk-to") { player, _ -> - if(inBorders(player, 2496, 3280,2557, 3336)) { - openDialogue(player, ManDialogue()) - } - return@on true - } - - on(WOMANS, IntType.NPC, "talk-to") { player, _ -> - if(inBorders(player, 2496, 3280,2557, 3336)) { - openDialogue(player, WomanDialogue()) - } - return@on true - } - - on(LEFT_DOOR, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else if(inBorders(player, 2556, 3298, 2557, 3301)){ - lock(player,2) - sendMessage(player, "You pull on the large wooden doors...") - runTask(player,2){ - sendMessage(player, "...But they will not open.") - } - } else { - face(player, Location.create(2559, 3302, 0)) - sendNPCDialogue(player, NPCs.MOURNER_2349, "Oi! What are you doing? Get away from there!") - } - return@on true - } - - on(RIGHT_DOOR, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getQuest(Quests.PLAGUE_CITY).isCompleted(player)) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else if(inBorders(player, 2556, 3298, 2557, 3301)){ - lock(player,2) - sendMessage(player, "You pull on the large wooden doors...") - runTask(player,2){ - sendMessage(player, "...But they will not open.") - } - } else { - face(player, Location.create(2559, 3302, 0)) - sendNPCDialogue(player, NPCs.MOURNER_2349, "Oi! What are you doing? Get away from there!") - } - return@on true - } - - on(MANHOLE_CLOSED, IntType.SCENERY, "open") { player, node -> - replaceScenery(node.asScenery(), MANHOLE_OPEN, -1) - addScenery(MANHOLE_COVER, Location(2529, 3302, 0),0,10) - sendMessage(player, "You pull back the manhole cover.") - return@on true - } - - on(MANHOLE_COVER, IntType.SCENERY, "close") { player, node -> - removeScenery(node.asScenery()) - getScenery(location(2529, 3303, 0))?.let { replaceScenery(it, MANHOLE_CLOSED, -1) } - sendMessage(player, "You close the manhole cover.") - return@on true - } - - on(MANHOLE_OPEN, IntType.SCENERY, "climb-down") { player, _ -> - teleport(player, Location(2514, 9739, 0)) - sendMessage(player, "You climb down through the manhole.") - return@on true - } - - on(BRAVEK_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 13) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else { - sendNPCDialogue(player,BRAVEK,"Go away, I'm busy! I'm... Umm... In a meeting!") - } - return@on true - } - - on(MUD_PILE, IntType.SCENERY, "climb") { player, _ -> - animate(player, CLIMB_LADDER) - runTask(player, 2){ - teleport(player, Location(2566, 3332)) - sendDialogue(player, "You climb up the mud pile.") - } - return@on true - } - - on(MAGIC_SCROLL, IntType.ITEM, "read") { player, _ -> - sendItemDialogue(player, MAGIC_SCROLL, "You memorise what is written on the scroll.") - removeItem(player, MAGIC_SCROLL) - sendDialogue(player, "You can now cast the Ardougne Teleport spell provided you have the required runes and magic level.") - return@on true - } - - on(SCRUFFY_NOTE, IntType.ITEM, "read") { player, _ -> - sendMessage(player, "You guess it really says something slightly different.") - openInterface(player, 222).also { scruffyNote(player) } - return@on true - } - - on(HEAD_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 11) { - openDialogue(player, HeadMournerDialogue()) - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 16) { - openDialogue(player, MournerDialogue()) - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) > 16) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else { - openDialogue(player, MournerDialogue()) - } - return@on true - } - - on(WARDROBE, IntType.SCENERY, "search") { player, _ -> - if (freeSlots(player) == 0 && !inEquipmentOrInventory(player, GAS_MASK)) { - sendItemDialogue(player, GAS_MASK, "You find a protective mask but you don't have enough room to take it.") - } else if (inEquipmentOrInventory(player, GAS_MASK)) { - sendMessage(player, "You search the wardrobe but you find nothing.") - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 2) { - sendItemDialogue(player, GAS_MASK, "You find a protective mask.") - addItem(player, GAS_MASK) - } - return@on true - } - - onUseWith(IntType.SCENERY, BUCKET_OF_WATER, MUD_PATCH) { player, _, _ -> - if (player.getAttribute(BUCKET_USES_ATTRIBUTE, 0) in 0..2 && removeItem(player, BUCKET_OF_WATER)) { - animate(player, POUR_THE_WATER) - player.dialogueInterpreter.sendDialogue( - "You pour water onto the soil.", - "The soil softens slightly." - ) - player.incrementAttribute(BUCKET_USES_ATTRIBUTE, 1) - addItem(player, EMPTY_BUCKET) - return@onUseWith true - } else if (player.getAttribute(BUCKET_USES_ATTRIBUTE, 0) == 3 && removeItem(player, BUCKET_OF_WATER)) { - animate(player, POUR_THE_WATER) - player.dialogueInterpreter.sendDialogue( - "You pour water onto the soil.", - "The soil is now soft enough to dig into." - ) - player.setAttribute("/save:elena:dig", true) - addItem(player, EMPTY_BUCKET) - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - onUseWith(IntType.SCENERY, SPADE, MUD_PATCH) { player, _, _ -> - if (player.getAttribute("/save:elena:dig", false) == true) { - player.pulseManager.run(object : Pulse() { - var counter = 0 - override fun pulse(): Boolean { - when (counter++) { - 0 -> sendItemDialogue(player, SPADE,"You dig deep into the soft soil... Suddenly it crumbles away!") - 1 -> animate(player, DIG_WITH_SPADE) - 3 -> { - teleport(player, Location(2518, 9759)) - setQuestStage(player, Quests.PLAGUE_CITY, 4) - player.dialogueInterpreter.sendDialogue( - "You fall through...", - "...you land in the sewer.", - "Edmond follows you down the hole." - ) - return true - } - } - return false - } - }) - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - on(GRILL, IntType.SCENERY, "open") { player, _ -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 4) { - sendDialogue(player, "The grill is too secure. You can't pull it off alone.") - animate(player, TRYING_TO_OPEN_GRILL) - setQuestStage(player, Quests.PLAGUE_CITY, 5) - } else { - sendDialogue(player, "There is a grill blocking your way") - } - return@on true - } - - on(PIPE, IntType.SCENERY, "climb-up") { player, _ -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 7 && inEquipment(player, GAS_MASK)) { - animate(player, GO_INTO_PIPE,true) - forceMove(player, Location(2514, 9739, 0), Location(2514, 9734, 0), 0, 4,Direction.SOUTH) - runTask(player, 3) { - teleport(player, Location(2529, 3304, 0)) - sendDialogue(player, "You climb up through the sewer pipe.") - } - } else if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 7 && !inEquipment(player, GAS_MASK)) { - sendNPCDialogue(player, NPCs.EDMOND_714, "I can't let you enter the city without your gasmask on.") - } else { - sendDialogue(player, "There is a grill blocking your way") - } - return@on true - } - - onUseWith(IntType.SCENERY, ROPE, PIPE) { player, _, _ -> - sendPlayerDialogue(player, "Maybe I should try opening it first.") - return@onUseWith true - } - - onUseWith(IntType.SCENERY, ROPE, GRILL) { player, _, _ -> - if(removeItem(player, ROPE)) { - player.pulseManager.run(object : Pulse() { - var counter = 0 - override fun pulse(): Boolean { - when (counter++) { - 0 -> forceWalk(player, Location.create(2514, 9740, 0), "SMART") - 2 -> face(player, Location.create(2514, 9739, 0), -1) - 3 -> { - animate(player, TIE_THE_ROPE) - setVarbit(player, 1787, 5, true) // Tied rope to the grill. - } - 4 -> { - setQuestStage(player, Quests.PLAGUE_CITY, 6) - sendItemDialogue(player, ROPE, "You tie the end of the rope to the sewer pipe's grill.") - } - } - return false - } - }) - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - class TedRehnisonDoors : DialogueFile() { - override fun handle(componentID: Int, buttonID: Int) { - npc = NPC(NPCs.TED_REHNISON_721) - when (stage) { - 0 -> if(removeItem(player!!, BOOK)){ - playerl(FacialExpression.NEUTRAL, "I'm a friend of Jethick's, I have come to return a book he borrowed.").also { stage++ } - } else { - npcl(FacialExpression.FRIENDLY, "Go away. We don't want any.").also { stage = END_DIALOGUE } - } - 1 -> npcl(FacialExpression.FRIENDLY, "Oh... why didn't you say, come in then.").also { stage++ } - 2 -> sendItemDialogue(player!!, BOOK, "You hand the book to Ted as you enter.").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "Thanks, I've been missing that.").also { stage++ } - 4 -> { - end() - DoorActionHandler.handleAutowalkDoor(player, getScenery(2531, 3328, 0)) - setQuestStage(player!!, Quests.PLAGUE_CITY, 9) - } - } - } - } - - on(PLAGUE_TED_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 9) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else { - openDialogue(player, TedRehnisonDoors()) - } - return@on true - } - - on(BARREL, IntType.SCENERY, "search") { player, _ -> - if (inInventory(player, SMALL_KEY)) { - sendMessage(player, "You don't find anything interesting.") - return@on true - } else { - sendItemDialogue(player, SMALL_KEY, "You find a small key in the barrel.") - addItem(player, SMALL_KEY) - } - } - - onUseWith(IntType.ITEM, CHOCOLATE_DUST, BUCKET_OF_MILK) { player, _, _ -> - if (player.questRepository.hasStarted(Quests.PLAGUE_CITY) && removeItem(player, CHOCOLATE_DUST) && removeItem(player, BUCKET_OF_MILK)) { - sendItemDialogue(player, CHOCOLATE_MILK, "You mix the chocolate into the bucket.") - addItem(player, CHOCOLATE_MILK) - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - onUseWith(IntType.ITEM, SNAPE_GRASS, CHOCOLATE_MILK) { player, _, _ -> - if (player.questRepository.hasStarted(Quests.PLAGUE_CITY) && removeItem(player, SNAPE_GRASS) && removeItem(player, CHOCOLATE_MILK)) { - sendItemDialogue(player, HANGOVER_CURE, "You mix the snape grass into the bucket.") - addItem(player, HANGOVER_CURE) - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - on(SPOOKY_STAIRS_DOWN, IntType.SCENERY, "walk-down") { player, _ -> - sendMessage(player, "You walk down the stairs...") - teleport(player, Location.create(2537, 9671)) - return@on true - } - - on(SPOOKY_STAIRS_UP, IntType.SCENERY, "walk-up") { player, _ -> - teleport(player, Location.create(2536, 3271, 0)) - sendMessage(player, "You walk up the stairs...") - return@on true - } - - class ElenaDoorDialogue : DialogueFile() { - override fun handle(componentID: Int, buttonID: Int) { - npc = NPC(NPCs.ELENA_3215) - when (stage) { - 0 -> sendDialogue(player!!, "The door is locked.").also { stage++ } - 1 -> npcl(FacialExpression.CRYING, "Hey get me out of here please!").also { stage++ } - 2 -> playerl(FacialExpression.FRIENDLY, "I would do but I don't have a key.").also { stage++ } - 3 -> npcl(FacialExpression.SAD, "I think there may be one around somewhere. I'm sure I heard them stashing it somewhere.").also { stage++ } - 4 -> options("Have you caught the plague?", "Okay, I'll look for it.").also { stage++ } - 5 -> when (buttonID) { - 1 -> playerl(FacialExpression.FRIENDLY, "Have you caught the plague?").also { stage = 6 } - 2 -> playerl(FacialExpression.FRIENDLY, "Okay, I'll look for it.").also { stage = END_DIALOGUE } - } - 6 -> npcl(FacialExpression.HALF_WORRIED, "No, I have none of the symptoms.").also { stage++ } - 7 -> playerl(FacialExpression.THINKING, "Strange, I was told this house was plague infected.").also { stage++ } - 8 -> playerl(FacialExpression.THINKING, "I suppose that was a cover up by the kidnappers.").also { stage = 4 } - } - } - } - - onUseWith(IntType.SCENERY, SMALL_KEY, PRISON_DOORS) { player, _, _ -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 16) { - DoorActionHandler.handleAutowalkDoor(player, core.game.world.map.RegionManager.getObject(Location(2539, 9672, 0))!!.asScenery()) - sendDialogue(player, "You unlock the door.") - } else { - sendMessage(player, "Nothing interesting happens.") - } - return@onUseWith true - } - - on(PRISON_DOORS, IntType.SCENERY, "open") { player, node -> - if (player.questRepository.getStage(Quests.PLAGUE_CITY) >= 99) { - DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) - } else { - openDialogue(player, ElenaDoorDialogue()) - } - return@on true - } - } - - private fun scruffyNote(player: Player) { - val scruffynotes = - arrayOf( - "Got a bncket of nnilk", - "Tlen grind sorne lhoculate", - "vnith a pestal and rnortar", - "ald the grourd dlocolate to tho milt", - "finales add 5cme snape gras5", - ) - setInterfaceText(player, scruffynotes.joinToString("
"), 222, 5) - } - - override fun defineDestinationOverrides() { - setDest(IntType.SCENERY, intArrayOf(GRILL), "open") { _, _ -> - return@setDest Location.create(2514, 9739, 0) - } - - setDest(IntType.SCENERY, intArrayOf(PIPE), "climb-up") { _, _ -> - return@setDest Location.create(2514, 9739, 0) - } - - setDest(IntType.SCENERY, intArrayOf(MANHOLE_OPEN), "climb-down") { _, _ -> - return@setDest Location.create(2529, 3304, 0) - } - } -} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/KilronDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/KilronDialogue.kt new file mode 100644 index 000000000..83be1b46c --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/KilronDialogue.kt @@ -0,0 +1,51 @@ +package content.region.kandarin.ardougne.quest.biohazard.dialogue + +import content.data.Quests +import core.api.getQuestStage +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +@Initializable +class KilronDialogue(player: Player? = null) : DialoguePlugin(player) { + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + playerl(FacialExpression.FRIENDLY, "Hello there.") + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + if (getQuestStage(player, Quests.BIOHAZARD) > 0){ + when(stage){ + 0 -> playerl(FacialExpression.FRIENDLY, "Hello Kilron.").also { stage++ } + 1 -> npcl(FacialExpression.FRIENDLY, "Hello traveller. Do you need to go back over?").also { stage++ } + 2 -> showTopics( + Topic("Not yet Kilron.", 4), + Topic("Yes I do.", 5) + ) + 4 -> npcl(FacialExpression.FRIENDLY, "Okay, just give me the word.").also { stage = END_DIALOGUE } + 5 -> npcl(FacialExpression.FRIENDLY, "Okay, quickly now!").also { stage = END_DIALOGUE } + } + + } + else { + when (stage) { + 0 -> npcl(FacialExpression.FRIENDLY, "Hello.").also { stage++ } + 1 -> playerl(FacialExpression.FRIENDLY, "How are you?").also { stage++ } + 2 -> npcl(FacialExpression.FRIENDLY, "Busy.").also { stage = END_DIALOGUE } + } + } + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.KILRON_349) + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/MournerBossDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/MournerBossDialogue.kt new file mode 100644 index 000000000..0bad783a8 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/biohazard/dialogue/MournerBossDialogue.kt @@ -0,0 +1,149 @@ +package content.region.kandarin.ardougne.quest.biohazard.dialogue + +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.interaction.QueueStrength +import core.game.node.entity.Entity +import core.game.node.entity.npc.AbstractNPC +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + + +/** + * For some reason the level 13 mourner upstairs is called the boss + * And despite the fact that other NPCs say there's one sick person upstairs they're 2 up there. + * + * We should be using key 423 but that got incorrectly used for Lost Tribe + */ + +@Initializable +class MournerBossDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object{ + const val HOLD_BREATH = 10 + const val PRAY = 20 + const val FATAL = 30 + const val HAVE_KEY = 40 + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + if (inEquipment(player!!, Items.DOCTORS_GOWN_430)){ + playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage = if (hasAnItem(player!!, Items.KEY_5010).exists()) HAVE_KEY else START_DIALOGUE + 1 } + return true + } + else { + sendDialogue("The mourner doesn't feel like talking.").also { stage = END_DIALOGUE } + return false + } + } + + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(stage){ + START_DIALOGUE + 1 -> npcl(FacialExpression.ASKING, "A doctor? At last! I don't know what I've eaten but I feel like I'm on death's door.").also { stage++ } + START_DIALOGUE + 2 -> playerl(FacialExpression.NEUTRAL, "Hmm... interesting, sounds like food poisoning.").also { stage++ } + // Jagex didn't include a question mark here + START_DIALOGUE + 3 -> npcl(FacialExpression.ASKING, "Yes, I'd figured that out already. What can you give me to help.").also { stage++ } + START_DIALOGUE + 4 -> showTopics( + Topic("Just hold your breath and count to ten.", HOLD_BREATH), + Topic("The best I can do is pray for you.", PRAY), + Topic("There's nothing I can do, it's fatal.", FATAL) + ) + + + HOLD_BREATH -> npcl(FacialExpression.SUSPICIOUS, "What? How will that help? What kind of doctor are you?").also { stage++ } + HOLD_BREATH + 1 -> player(FacialExpression.HALF_GUILTY, "Erm... I'm new, I just started.").also { stage++ } + HOLD_BREATH + 2 -> npcl(FacialExpression.ANGRY, "You're no doctor!").also { + stage = END_DIALOGUE + fight(player) + } + + PRAY -> npcl(FacialExpression.ANGRY, "Pray for me? You're no doctor... You're an imposter!").also { + stage = END_DIALOGUE + fight(player) + } + + FATAL -> npcl(FacialExpression.PANICKED, "No, I'm too young to die! I've never even had a girlfriend.").also { stage++ } + FATAL + 1 -> playerl(FacialExpression.SAD, "That's life for you.").also { stage++ } + FATAL + 2 -> npcl(FacialExpression.ASKING, "Wait a minute, where's your equipment?").also { stage++ } + FATAL + 3 -> playerl(FacialExpression.HALF_GUILTY, "It's erm... at home.").also { stage++ } + FATAL + 4 -> npcl(FacialExpression.ANGRY, "You're no doctor!").also { + stage = END_DIALOGUE + fight(player) + } + + HAVE_KEY -> npcl(FacialExpression.NEUTRAL, "Sorry, I'd like to be left in peace.").also { stage = END_DIALOGUE } + + } + + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_370) + } + + private fun fight(player: Player){ + queueScript(player) { stage: Int -> + if (stage == 1){ + npc.attack(player) + return@queueScript stopExecuting(player) + } + return@queueScript delayScript(player, 1) + } + } +} + +/** + * Handles the key drop from the mourner boss + */ +@Initializable +class MournerBossNPC : AbstractNPC { + var target: Player? = null + private val supportRange: Int = 5 + + //Constructor spaghetti because Arios I guess + constructor() : super(NPCs.MOURNER_370, null, true) {} + private constructor(id: Int, location: Location) : super(id, location) {} + override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC { + return MournerBossNPC(id, location) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_370) + } + + override fun finalizeDeath(killer: Entity?) { + val p = killer as Player + if (!hasAnItem(p, Items.KEY_5010).exists()){ + queueScript(p, 1, QueueStrength.NORMAL){ stage: Int -> + when(stage){ + 0 -> { + sendMessage(p, "You search the mourner...") + } + 2 ->{ + sendMessage(p, "and find a key.") + // If the player doesn't have space bad luck + // They can kill another mourner boss + // todo change this key and fix lost tribe key at the same time + // It should be 423 here and 5010 over there + // addItemOrDrop(p, Items.KEY_5010) + return@queueScript stopExecuting(p) + } + } + return@queueScript delayScript(p, 1) + } + } + super.finalizeDeath(killer) + } + +} diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCity.kt similarity index 96% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCity.kt index b3ae7dbaf..d34a8904d 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/PlagueCity.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCity.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity +import content.data.Quests import core.api.addItemOrDrop import core.api.removeAttributes import core.api.rewardXP @@ -8,7 +9,6 @@ import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills import core.plugin.Initializable import org.rs09.consts.Items -import content.data.Quests @Initializable class PlagueCity : Quest(Quests.PLAGUE_CITY, 98, 97, 1, 165, 0, 1, 29) { @@ -35,7 +35,7 @@ class PlagueCity : Quest(Quests.PLAGUE_CITY, 98, 97, 1, 165, 0, 1, 29) { if (stage >= 2) { line++ - line(player, "Alrena has given me a Gasmask to protect me", line++, stage >= 3) + line(player, "Alrena has given me a gas mask to protect me", line++, stage >= 3) line(player, "from the plague while in West Ardougne.", line++, stage >= 3) line++ } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCityListeners.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCityListeners.kt new file mode 100644 index 000000000..1b3855785 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/PlagueCityListeners.kt @@ -0,0 +1,430 @@ +package content.region.kandarin.ardougne.quest.plaguecity + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.dialogue.mourners.MournerKidnapDialogueFile +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Direction +import core.game.world.map.Location +import core.game.world.update.flag.context.Graphics +import core.tools.END_DIALOGUE +import org.rs09.consts.* +import core.game.node.scenery.Scenery as SceneryNode + +class PlagueCityListeners : InteractionListener { + companion object { + + const val BUCKET_USES_ATTRIBUTE = "/save:elena:bucket" + const val ARDOUGNE_TELE_ATTRIBUTE = "/save:Ardougne:teleport" + + private const val TRYING_TO_OPEN_GRILL = 3192 + private const val POUR_THE_WATER = 2283 + private const val CLIMB_LADDER = 828 + private const val GO_INTO_PIPE = 10580 + private const val TIE_THE_ROPE = 3191 + private const val DIG_WITH_SPADE = 830 + + } + + override fun defineListeners() { + + on(NPCs.BILLY_REHNISON_723, IntType.NPC, "talk-to") { player, _ -> + sendMessage(player, "Billy isn't interested in talking.") + return@on true + } + + on(Scenery.MANHOLE_2543, IntType.SCENERY, "open") { player, node -> + replaceScenery(node.asScenery(), Scenery.MANHOLE_2544, -1) + addScenery(Scenery.MANHOLE_COVER_2545, Location(node.location.x, node.location.y-1, 0),0,10) + sendMessage(player, "You pull back the manhole cover.") + return@on true + } + + on(Scenery.MANHOLE_COVER_2545, IntType.SCENERY, "close") { player, node -> + removeScenery(node.asScenery()) + getScenery(location(node.location.x, node.location.y+1, 0))?.let { replaceScenery(it, Scenery.MANHOLE_2543, -1) } + sendMessage(player, "You close the manhole cover.") + return@on true + } + + on(Scenery.MANHOLE_2544, IntType.SCENERY, "climb-down") { player, _ -> + teleport(player, Location(2514, 9739, 0)) + face(player, Location.create(2514, 9740)) + sendMessage(player, "You climb down through the manhole.") + return@on true + } + + on(Scenery.DOOR_2528, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, Quests.PLAGUE_CITY) >= 13) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + sendNPCDialogue(player, NPCs.BRAVEK_711,"Go away, I'm busy! I'm... Umm... In a meeting!") + // This typo is authentic + sendMessage(player, "The door won't open") + } + return@on true + } + + on(Scenery.MUD_PILE_2533, IntType.SCENERY, "climb") { player, _ -> + animate(player, CLIMB_LADDER) + queueScript(player, 2){ + teleport(player, Location(2566, 3332)) + sendDialogue(player, "You climb up the mud pile.") + return@queueScript true + } + return@on true + } + + on(Scenery.DUG_HOLE_11417, IntType.SCENERY, "Climb-down") { player, _ -> + teleport(player, Location(2518, 9759)) + sendDialogue(player, "You climb down the tunnel into the sewer.") + return@on true + } + + on(Items.A_MAGIC_SCROLL_1505, IntType.ITEM, "read") { player, item -> + if (removeItem(player, item)){ + if (getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false)){ + sendGraphics(Graphics(157,96), player.location) + impact(player, 0) + sendMessage(player, "The scroll explodes.") + addItem(player, Items.ASHES_592) + } + else{ + sendItemDialogue(player, Items.A_MAGIC_SCROLL_1505, "You memorise what is written on the scroll.") + sendDialogue(player, "You can now cast the Ardougne Teleport spell provided you have the required runes and magic level.") + setAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, true) + } + return@on true + } + return@on false + } + + on(Items.A_SCRUFFY_NOTE_1508, IntType.ITEM, "read") { player, _ -> + sendMessage(player, "You guess it really says something slightly different.") + openInterface(player, 222).also { scruffyNote(player) } + return@on true + } + + class KidnapDoorDialogue : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + + when(stage) { + 0 -> { + // Face the door + face(player!!, Location.create(player!!.location.x, 3270, 0)) + sendDialogue(player!!, "The door won't open. You notice a black cross on the door.").also { stage++ } + } + 1 -> openDialogue(player!!, MournerKidnapDialogueFile(), NPC(NPCs.MOURNER_3216)) + } + } + + } + + on(Scenery.DOOR_35991, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, Quests.PLAGUE_CITY) > 16) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } + else { + // Make sure we are standing in front of the door + forceWalk(player, Location.create(node.location.x, node.location.y), "smart") + openDialogue(player, KidnapDoorDialogue()) + } + return@on true + } + + on(Scenery.WARDROBE_2525, IntType.SCENERY, "search") { player, _ -> + if(getQuestStage(player, Quests.PLAGUE_CITY) >= 2){ + if (!hasAnItem(player, Items.GAS_MASK_1506).exists()){ + if(freeSlots(player) == 0) { + sendItemDialogue(player, Items.GAS_MASK_1506, "You find a protective mask but you don't have enough room to take it.") + return@on true + } + else { + sendItemDialogue(player, Items.GAS_MASK_1506, "You find a protective mask.") + addItem(player, Items.GAS_MASK_1506) + return@on true + } + } + } + // The player should not be given a mask for whatever reason + sendMessage(player, "You search the wardrobe but you find nothing.") + return@on false + } + + onUseWith(IntType.SCENERY, Items.BUCKET_OF_WATER_1929, Scenery.MUD_PATCH_11418) { player, _, _ -> + if (getAttribute(player, BUCKET_USES_ATTRIBUTE, 0) in 0..2 && removeItem(player, Items.BUCKET_OF_WATER_1929)) { + animate(player, POUR_THE_WATER) + sendDialogueLines(player, "You pour water onto the soil.", "The soil softens slightly." + ) + player.incrementAttribute(BUCKET_USES_ATTRIBUTE, 1) + addItem(player, Items.BUCKET_1925) + return@onUseWith true + } else if (getAttribute(player, BUCKET_USES_ATTRIBUTE, 0) == 3 && removeItem(player, Items.BUCKET_OF_WATER_1929)) { + animate(player, POUR_THE_WATER) + player.incrementAttribute(BUCKET_USES_ATTRIBUTE, 1) + sendDialogueLines(player, + "You pour water onto the soil.", + "The soil is now soft enough to dig into." + ) + setAttribute(player, "/save:elena:dig", true) + addItem(player, Items.BUCKET_1925) + } else { + sendDialogue(player, "You don't need to pour on any more water the soil is soft enough already.") + } + return@onUseWith true + } + + + onDig(Location.create(2566, 3332, 0)){ player: Player -> + dig(player) + } + + onUseWith(IntType.SCENERY, Items.SPADE_952, Scenery.MUD_PATCH_11418) { player, _, _ -> + dig(player) + return@onUseWith true + } + + on(Scenery.GRILL_11423, IntType.SCENERY, "open") { player, _ -> + if (getQuestStage(player, Quests.PLAGUE_CITY) == 4) { + sendDialogue(player, "The grill is too secure. You can't pull it off alone.") + animate(player, TRYING_TO_OPEN_GRILL) + setQuestStage(player, Quests.PLAGUE_CITY, 5) + } else { + sendDialogue(player, "There is a grill blocking your way") + } + return@on true + } + + on(Scenery.PIPE_2542, IntType.SCENERY, "climb-up") { player, _ -> + if (getQuestStage(player, Quests.PLAGUE_CITY) >= 7) { + if (inEquipment(player, Items.GAS_MASK_1506)){ + animate(player, GO_INTO_PIPE,true) + queueScript(player, 3) { + teleport(player, Location(2529, 3304, 0)) + sendDialogue(player, "You climb up through the sewer pipe.") + return@queueScript stopExecuting(player) + } + forceMove(player, Location(2514, 9739, 0), Location(2514, 9734, 0), 0, 5,Direction.SOUTH) + } + else { + sendNPCDialogue(player, NPCs.EDMOND_714, "I can't let you enter the city without your gas mask on.") + } + } + else { + sendDialogue(player, "There is a grill blocking your way") + } + return@on true + } + + onUseWith(IntType.SCENERY, Items.ROPE_954, Scenery.PIPE_2542) { player, _, _ -> + sendPlayerDialogue(player, "Maybe I should try opening it first.") + return@onUseWith true + } + + onUseWith(IntType.SCENERY, Items.ROPE_954, Scenery.GRILL_11423) { player, _, _ -> + if(removeItem(player, Items.ROPE_954)) { + queueScript(player, 1) { stage: Int -> + when (stage) { + 0 -> forceWalk(player, Location.create(2514, 9740, 0), "SMART") + 2 -> face(player, Location.create(2514, 9739, 0), -1) + 3 -> { + animate(player, TIE_THE_ROPE) + setVarbit(player, 1787, 5, true) // Tied rope to the grill. + } + + 4 -> { + setQuestStage(player, Quests.PLAGUE_CITY, 6) + sendItemDialogue( + player, + Items.ROPE_954, + "You tie the end of the rope to the sewer pipe's grill." + ) + return@queueScript stopExecuting(player) + } + } + return@queueScript delayScript(player, 1) + } + return@onUseWith true + } else { + sendMessage(player, "Nothing interesting happens.") + } + return@onUseWith true + } + + class TedRehnisonDoors : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + npc = NPC(NPCs.TED_REHNISON_721) + when (stage) { + 0 -> { + npcl(FacialExpression.FRIENDLY, "Go away. We don't want any.").also { + if(hasAnItem(player!!, Items.BOOK_1509).exists()){ + stage++ + } else { + stage = END_DIALOGUE } + } + } + 1 -> playerl(FacialExpression.NEUTRAL, "I'm a friend of Jethick's, I have come to return a book he borrowed.").also { stage++ } + // todo change this back after sendItemDialogue is fixed for having a single line before See #1885 + 2 -> npc(FacialExpression.FRIENDLY, "", "Oh... why didn't you say, come in then.", "").also { stage++ } + 3 -> sendItemDialogue(player!!, Items.BOOK_1509, "You hand the book to Ted as you enter.").also { + DoorActionHandler.handleAutowalkDoor(player, getScenery(2531, 3328, 0)) + setQuestStage(player!!, Quests.PLAGUE_CITY, 9) + removeItem(player!!, Items.BOOK_1509) + stage++ + } + 4 -> npcl(FacialExpression.NEUTRAL, "Thanks, I've been missing that.").also { stage = END_DIALOGUE } + } + } + } + + on(Scenery.DOOR_2537, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, Quests.PLAGUE_CITY) >= 9) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + openDialogue(player, TedRehnisonDoors()) + } + return@on true + } + + on(Scenery.BARREL_2530, IntType.SCENERY, "search") { player, _ -> + if (inInventory(player, Items.A_SMALL_KEY_1507)) { + sendMessage(player, "You don't find anything interesting.") + return@on true + } else { + sendItemDialogue(player, Items.A_SMALL_KEY_1507, "You find a small key in the barrel.") + addItem(player, Items.A_SMALL_KEY_1507) + } + } + + on(Scenery.SPOOKY_STAIRS_2522, IntType.SCENERY, "walk-down") { player, _ -> + sendMessage(player, "You walk down the stairs...") + teleport(player, Location.create(2537, 9671)) + return@on true + } + + on(Scenery.SPOOKY_STAIRS_2523, IntType.SCENERY, "walk-up") { player, _ -> + teleport(player, Location.create(2536, 3271, 0)) + sendMessage(player, "You walk up the stairs...") + return@on true + } + + class ElenaDoorDialogue : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + npc = NPC(NPCs.ELENA_3215) + when (stage) { + 0 -> sendDialogue(player!!, "The door is locked.").also { stage++ } + 1 -> npcl(FacialExpression.CRYING, "Hey get me out of here please!").also { stage++ } + 2 -> playerl(FacialExpression.FRIENDLY, "I would do but I don't have a key.").also { stage++ } + 3 -> npcl(FacialExpression.SAD, "I think there may be one around somewhere. I'm sure I heard them stashing it somewhere.").also { stage++ } + 4 -> options("Have you caught the plague?", "Okay, I'll look for it.").also { stage++ } + 5 -> when (buttonID) { + 1 -> playerl(FacialExpression.WORRIED, "Have you caught the plague?").also { stage = 6 } + 2 -> playerl(FacialExpression.NEUTRAL, "Okay, I'll look for it.").also { stage = END_DIALOGUE } + } + 6 -> npcl(FacialExpression.HALF_WORRIED, "No, I have none of the symptoms.").also { stage++ } + 7 -> playerl(FacialExpression.THINKING, "Strange, I was told this house was plague infected.").also { stage++ } + 8 -> npcl(FacialExpression.THINKING, "I suppose that was a cover up by the kidnappers.").also { stage = END_DIALOGUE } + } + } + } + + onUseWith(IntType.SCENERY, Items.A_SMALL_KEY_1507, Scenery.DOOR_2526) { player, _, node -> + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + sendDialogue(player, "You unlock the door.") + return@onUseWith true + } + + on(Scenery.DOOR_2526, IntType.SCENERY, "open") { player, node -> + if (getQuestStage(player, Quests.PLAGUE_CITY) >= 99 || hasAnItem(player, Items.A_SMALL_KEY_1507).exists()) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else { + openDialogue(player, ElenaDoorDialogue()) + } + return@on true + } + + onUseWith(IntType.NPC, Items.HANGOVER_CURE_1504, NPCs.BRAVEK_711) { player, _, _ -> + openDialogue(player, NPCs.BRAVEK_711) + return@onUseWith true + } + + on(Scenery.DOOR_2054, IntType.SCENERY, "open"){ player, node -> + if (isQuestComplete(player, Quests.PLAGUE_CITY)){ + DoorActionHandler.handleDoor(player, node as SceneryNode) + } + else{ + sendMessage(player, "This door is locked") + } + return@on true + } + + } + + private fun dig(p : Player) { + if (getAttribute(p, "/save:elena:dig", false)) { + // Only remove the counter now that you have dug a hole + removeAttribute(p, BUCKET_USES_ATTRIBUTE) + queueScript(p, 1) { stage: Int -> + when (stage) { + 0 -> sendItemDialogue( + p, Items.SPADE_952, + "You dig deep into the soft soil... Suddenly it crumbles away!" + ) + + 1 -> animate(p, DIG_WITH_SPADE) + 3 -> { + teleport(p, Location(2518, 9759)) + setQuestStage(p, Quests.PLAGUE_CITY, 4) + setVarbit(p, Vars.VARBIT_QUEST_PLAGUE_CITY_EDMOND_TUNNELS, 1) + setVarbit(p, Vars.VARBIT_QUEST_PLAGUE_CITY_MUD_PILE, 1) + sendDialogueLines( + p, + "You fall through...", + "...you land in the sewer.", + "Edmond follows you down the hole." + ) + // We've dug the hole so don't keep track + removeAttribute(p, "/save:elena:dig") + return@queueScript stopExecuting(p) + } + } + return@queueScript delayScript(p, 1) + + } + } else { + sendMessage(p, "Nothing interesting happens.") + } + } + + private fun scruffyNote(player: Player) { + val scruffynotes = + arrayOf( + "Got a bncket of nnilk", + "Tlen grind sorne lhoculate", + "vnith a pestal and rnortar", + "ald the grourd dlocolate to tho milt", + "finales add 5cme snape gras5", + ) + setInterfaceText(player, scruffynotes.joinToString("
"), 222, 5) + } + + override fun defineDestinationOverrides() { + setDest(IntType.SCENERY, intArrayOf(Scenery.GRILL_11423), "open") { _, _ -> + return@setDest Location.create(2514, 9739, 0) + } + + setDest(IntType.SCENERY, intArrayOf(Scenery.PIPE_2542), "climb-up") { _, _ -> + return@setDest Location.create(2514, 9739, 0) + } + + setDest(IntType.SCENERY, intArrayOf(Scenery.MANHOLE_2544), "climb-down") { _, node -> + return@setDest Location.create(node.location.x, node.location.y+1, 0) + } + } +} diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/UndergroundCutscene.kt similarity index 65% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/UndergroundCutscene.kt index 27869f495..eea5f2ffa 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/UndergroundCutscene.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/UndergroundCutscene.kt @@ -1,12 +1,12 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity +import content.data.Quests import core.api.* import core.game.activity.Cutscene import core.game.dialogue.FacialExpression import core.game.node.entity.player.Player import core.game.world.map.Direction import core.game.world.map.Location -import content.data.Quests class UndergroundCutscene(player: Player) : Cutscene(player) { @@ -29,12 +29,22 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { } 1 -> { - teleport(player, 18, 13) + teleport(player, 18, 12) + setVarbit(player, 1787, 2, true) // Grill removal. timedUpdate(1) } 2 -> { move(player, 18, 12) + face(player, base.transform(18, 11, 0)) + // You have to remove the stubborn previous sceneries before adding your own. + removeScenery(getScenery(base.transform(18, 11, 0))!!) + removeScenery(getScenery(base.transform(18, 12, 0))!!) + removeScenery(getScenery(base.transform(18, 13, 0))!!) + // Add the rope sceneries to animate. + addScenery(11416, base.transform(18, 11, 0),2,10) + addScenery(11412, base.transform(18, 12, 0),2,10) + addScenery(11414, base.transform(18, 13, 0),2,10) fadeFromBlack() moveCamera(21, 16) rotateCamera(18, 13) @@ -42,20 +52,22 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { } 3 -> { - visualize(getNPC(EDMOND)!!, ROPE_PULL, 2270) - visualize(player, ROPE_PULL, 2270) + animate(getNPC(EDMOND)!!, ROPE_PULL) + animate(player, ROPE_PULL) + animateScenery(player, getScenery(base.transform(18, 11, 0))!!, 3189) + animateScenery(player, getScenery(base.transform(18, 12, 0))!!, 3188) + animateScenery(player, getScenery(base.transform(18, 13, 0))!!, 3188) sendChat(player, "1... 2... 3... Pull!") timedUpdate(6) } 4 -> { - setVarbit(player, 1787, 6, true) // Grill removal. face(player, getNPC(EDMOND)!!.location) timedUpdate(2) } 5 -> { - dialogueUpdate(EDMOND, FacialExpression.FRIENDLY, "Once you're in the city look for a man called Jethick, he's an old friend and should help you. Send") + dialogueUpdate(EDMOND, FacialExpression.FRIENDLY, "Once you're in the city look for a man called Jethick, he's an old friend and should help you. Send", hide=true) sendChat(getNPC(EDMOND)!!, "Once you're in the city") timedUpdate(4) } @@ -76,7 +88,7 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { } 9 -> { - dialogueUpdate(EDMOND, FacialExpression.FRIENDLY, "him my regards, I Haven't seen him since before Elena was born.") + dialogueUpdate(EDMOND, FacialExpression.FRIENDLY, "him my regards, I haven't seen him since before Elena was born.", hide=true) sendChat(getNPC(EDMOND)!!, "him my regards, I haven't") timedUpdate(4) } @@ -93,15 +105,11 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { 12 -> { sendChat(player, "Alright, thanks I will.") - timedUpdate(3) + // todo change this to true once no continue button player model size is fixed + sendPlayerDialogue(player,"Alright, thanks I will.", hide = false) + timedUpdate(2) } - 13 -> { - sendPlayerDialogue(player,"Alright, thanks I will.") - timedUpdate(4) - } - - 14 -> { end { setQuestStage(player, Quests.PLAGUE_CITY, 7) } @@ -111,6 +119,6 @@ class UndergroundCutscene(player: Player) : Cutscene(player) { companion object { private const val EDMOND = 714 - private val ROPE_PULL = 3187 + private const val ROPE_PULL = 3187 } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/AlrenaDialogue.kt similarity index 82% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/AlrenaDialogue.kt index c5bee2f92..56384c44b 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/AlrenaDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/AlrenaDialogue.kt @@ -1,5 +1,7 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -9,7 +11,6 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs -import content.data.Quests @Initializable class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -17,7 +18,8 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 1) { - playerl(FacialExpression.FRIENDLY, "Hello, Edmond has asked me to help find your daughter.").also { stage++ } + // playerl formats this weirdly + player(FacialExpression.FRIENDLY, "Hello, Edmond has asked me to help find your","daughter.").also { stage++ } } else { playerl(FacialExpression.FRIENDLY, "Hello Madam.").also { stage++ } } @@ -44,15 +46,15 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { sendItemDialogue(player!!, Items.DWELLBERRIES_2126, "You give the dwellberries to Alrena.").also { stage++ } removeItem(player!!, Items.DWELLBERRIES_2126) } - 4 -> sendDialogue(player!!, "Alrena crushes the berries into a smooth paste. She then smears the paste over a strange mask.").also { stage++ } - 5 -> npcl(FacialExpression.FRIENDLY, "There we go, all done. While in West Ardougne you must wear this at all times, or you could catch the plague. I'll make a spare mask. I'll hide it in the wardrobe in case the mourners come in.").also { stage++ } - 6 -> sendItemDialogue(player!!, Items.GAS_MASK_1506, "Alrena gives you the mask.").also { stage++ } - 7 -> { - end() - addItem(player!!, Items.GAS_MASK_1506) + // sendDialogue formats this weirdly + 4 -> sendDialogueLines(player!!, "Alrena crushes the berries into a smooth paste. She then smears the", "paste over a strange mask.").also { stage++ } + // npcl formats this weirdly + 5 -> npc(FacialExpression.FRIENDLY, "There we go, all done. While in West Ardougne you", "must wear this at all times, or you could catch the","plague.").also { stage++ } + 6 -> { setQuestStage(player!!, Quests.PLAGUE_CITY, 2) - setAttribute(player!!, PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) - sendNPCDialogue(player!!, NPCs.ALRENA_710, "I'll make a spare mask. I'll hide it in the wardrobe in case the mourners come in.") + addItem(player!!, Items.GAS_MASK_1506) + sendItemDialogue(player!!, Items.GAS_MASK_1506, "Alrena gives you the mask.").also { stage++ } + // Jump down to quest stage 2 from here } 8 -> playerl(FacialExpression.NEUTRAL, "Ok, I'll go and get some.").also { stage = END_DIALOGUE } } @@ -60,6 +62,9 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { 2 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Hello darling, I think Edmond had a good idea of how to get into West Ardougne, you should hear his idea.").also { stage++ } 2 -> playerl(FacialExpression.FRIENDLY, "Alright I'll go and see him now.").also { stage = END_DIALOGUE } + + // This gets entered from quest stage 1 + 7 -> npcl(FacialExpression.FRIENDLY, "I'll make a spare mask. I'll hide it in the wardrobe in case the mourners come in.").also { stage = END_DIALOGUE } } 3 -> when (stage) { @@ -113,19 +118,26 @@ class AlrenaDialogue(player: Player? = null) : DialoguePlugin(player) { 5 -> npcl(FacialExpression.FRIENDLY, " Yes. There should be one in the house somewhere. Let me know if you need anything else.").also { stage = END_DIALOGUE } } - in 15..98 -> when (stage) { + 15 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Hello, any word on Elena?").also { stage++ } 2 -> playerl(FacialExpression.FRIENDLY, "Not yet I'm afraid, I need to find some Snape grass first, any idea where I'd find some?").also { stage++ } 3 -> npcl(FacialExpression.FRIENDLY, "It's not common round here, though I hear it's easy to find by the coast south west of Falador.").also { stage++ } 4 -> playerl(FacialExpression.FRIENDLY, "Thanks, I'll go take a look.").also { stage++ } 5 -> playerl(FacialExpression.FRIENDLY, "I also need to get some chocolate powder for a hangover cure for the city warder.").also { stage++ } 6 -> npcl(FacialExpression.FRIENDLY, "Well I don't have any chocolate, but this may help.").also { stage++ } - 7 -> sendItemDialogue(player!!, Items.PESTLE_AND_MORTAR_233, "Alrena hands you a pestle and mortar.").also { stage++ } - 8 -> playerl(FacialExpression.FRIENDLY, "Thanks.").also { stage++ } - 9 -> { - end() + 7 -> sendItemDialogue(player!!, Items.PESTLE_AND_MORTAR_233, "Alrena hands you a pestle and mortar.").also { addItem(player!!, Items.PESTLE_AND_MORTAR_233) + stage++ } + 8 -> playerl(FacialExpression.FRIENDLY, "Thanks.").also { stage = END_DIALOGUE } + } + + in 16 .. 98 -> when(stage){ + 1 -> npcl(FacialExpression.WORRIED, "Hello, any word on Elena?").also { stage++ } + 2 -> playerl(FacialExpression.NEUTRAL, "Not yet I'm afraid.").also { stage++ } + 3 -> npcl(FacialExpression.WORRIED, "Is there anything else I can do to help?").also { stage++ } + 4 -> playerl(FacialExpression.SAD, "Sorry but not right now.").also {stage = END_DIALOGUE } + } 99 -> when (stage) { diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/BravekDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/BravekDialogue.kt new file mode 100644 index 000000000..3eeb1e39e --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/BravekDialogue.kt @@ -0,0 +1,156 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue + +import content.data.Quests +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class BravekDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object{ + const val SPEAK_ANOTHER_DAY = 10 + const val WAITING_FOR_CURE = 20 + const val CURED = 30 + const val IMPORTANT = 50 + const val DRINK_TOO_MUCH = 60 + const val CURE = 70 + const val WHAT_HELP = 80 + const val ALL_PEOPLE_SAY = 90 + const val NOT_LISTEN = 100 + const val INTEREST = 110 + const val WEAK_LEADER = 120 + } + + override fun open(vararg args: Any?): Boolean { + npc = if (args[0] is Int) NPC(args[0] as Int) else args[0] as NPC + when(getQuestStage(player, Quests.PLAGUE_CITY)){ + in 0..13 -> npcl(FacialExpression.ANNOYED, "My head hurts! I'll speak to you another day...").also { stage = SPEAK_ANOTHER_DAY } + 14 -> npcl(FacialExpression.ANNOYED, " Uurgh! My head still hurts too much to think straight. " + + "Oh for one of Trudi's hangover cures!").also { stage = if(hasAnItem(player, Items.HANGOVER_CURE_1504).exists()) WAITING_FOR_CURE else END_DIALOGUE } + 15 -> npcl(FacialExpression.FRIENDLY, "Ah now, what was it you wanted me to do for you?").also { stage = WHAT_HELP } + else -> npcl(FacialExpression.FRIENDLY, "Thanks again for the hangover cure.").also { stage = if(hasAnItem(player, Items.WARRANT_1503).exists() || getQuestStage(player, Quests.PLAGUE_CITY) >= 99) CURED else WHAT_HELP } + + } + return true + } + + override fun handle(componentID: Int, buttonID: Int): Boolean { + when (stage){ + + SPEAK_ANOTHER_DAY -> showTopics( + Topic("This is really important though!", IMPORTANT), + Topic("Ok, goodbye.", END_DIALOGUE) + ) + + IMPORTANT -> npc(FacialExpression.ANNOYED, + "I can't possibly speak to you with my head spinning like", + "this... I went a bit heavy on the drink again last night.", + "Curse my herbalist, she made the best hang over cures.", + "Darn inconvenient of her catching the plague.").also { stage++ } + IMPORTANT + 1 -> showTopics( + Topic("Ok, goodbye.", END_DIALOGUE), + Topic(" You shouldn't drink so much then!", DRINK_TOO_MUCH), + Topic("Do you know what's in the cure?", CURE) + ) + + DRINK_TOO_MUCH -> npcl(FacialExpression.ANNOYED, "Well positions of responsibility are hard, " + + "I need something to take my mind off things... Especially with the problems this place has.").also { stage++ } + DRINK_TOO_MUCH + 1 -> showTopics( + Topic("Ok, goodbye.", END_DIALOGUE), + Topic("Do you know what's in the cure?", CURE), + Topic("I don't think drink is the solution.", DRINK_TOO_MUCH+2) + ) + DRINK_TOO_MUCH + 2 -> npcl(FacialExpression.ANNOYED, "Uurgh! My head still hurts too much to think straight. Oh for one of Trudi's hangover cures!").also { stage = END_DIALOGUE } + + CURE -> npc(FacialExpression.NEUTRAL, + "Hmmm let me think... Ouch! Thinking isn't clever. Ah", + "here, she did scribble it down for me.").also { stage++ } + CURE + 1 -> { + if(hasSpaceFor(player!!, Item(Items.A_SCRUFFY_NOTE_1508))) { + sendItemDialogue( + player!!, + Items.A_SCRUFFY_NOTE_1508, + "Bravek hands you a tatty piece of paper." + ).also { stage++ } + } + else{ + sendItemDialogue(player!!, Items.A_SCRUFFY_NOTE_1508, "Bravek waves a note in front of you but you do not have space for it").also { stage = END_DIALOGUE } + } + } + CURE + 2 ->{ + addItem(player!!, Items.A_SCRUFFY_NOTE_1508) + setQuestStage(player!!, Quests.PLAGUE_CITY, 14) + end() + } + + WAITING_FOR_CURE -> playerl(FacialExpression.NEUTRAL, "Try this.").also { stage++ } + WAITING_FOR_CURE + 1 -> { + animate(npc, 1330) // Drink hangover cure. + findLocalNPC(player!!, NPCs.BRAVEK_711)!!.sendChat("Grruurgh!") + sendItemDialogue(player!!, Items.HANGOVER_CURE_1504, "You give Bravek the hangover cure. Bravek gulps down the foul-looking liquid.").also { stage++ } + setQuestStage(player, Quests.PLAGUE_CITY, 15) + removeItem(player, Items.HANGOVER_CURE_1504) + } + WAITING_FOR_CURE + 2 -> npcl(FacialExpression.HAPPY, "Ooh that's much better! Thanks, that's the clearest my head has felt in a month." + + "Ah now, what was it you wanted me to do for you?" + ).also { stage = WHAT_HELP } + + WHAT_HELP -> playerl(FacialExpression.ASKING, "I need to rescue a kidnap victim called Elena. She's being held in a plague house, I need permission to enter.").also { stage++ } + WHAT_HELP + 1 -> npcl(FacialExpression.HALF_GUILTY, "Well the mourners deal with that sort of thing...").also { stage++ } + WHAT_HELP + 2 -> showTopics( + Topic("Ok, I'll go speak to them.", END_DIALOGUE), + Topic("Is that all anyone says around here?", ALL_PEOPLE_SAY), + Topic("They won't listen to me!", NOT_LISTEN, skipPlayer = true) + ) + + ALL_PEOPLE_SAY -> npcl(FacialExpression.HALF_GUILTY, "Well, they know best about plague issues.").also { stage++ } + ALL_PEOPLE_SAY + 1 -> showTopics( + Topic("Don't you want to take an interest in it at all?", INTEREST), + Topic("They won't listen to me!", NOT_LISTEN, skipPlayer = true) + ) + + INTEREST -> npcl(FacialExpression.HALF_GUILTY, "Nope, I don't wish to take a deep interest in plagues. That stuff is too scary for me!").also { stage++ } + INTEREST + 1 -> showTopics( + Topic("I see why people say you're a weak leader.", WEAK_LEADER), + Topic("Ok, I'll talk to the mourners.", END_DIALOGUE), + Topic("They won't listen to me!", NOT_LISTEN, skipPlayer = true) + ) + + WEAK_LEADER -> npcl(FacialExpression.ANNOYED, "Bah, people always criticise their leaders but delegating is the only way to lead. I delegate all plague issues to the mourners.").also { stage++ } + WEAK_LEADER + 1 -> playerl(FacialExpression.ANNOYED, "This whole city is a plague issue!").also { stage = END_DIALOGUE } + + NOT_LISTEN -> playerl(FacialExpression.ANNOYED, "They won't listen to me! They say I'm not properly equipped to go in the house, though I do have a very effective gas mask.").also { stage++ } + // npcl does not work + NOT_LISTEN + 1 -> npc(FacialExpression.ANNOYED, + "Hmmm, well I guess they're not taking the issue of a", + "kidnapping seriously enough. They do go a bit far", + "sometimes. I've heard of Elena, she has helped us a lot...", + "Ok, I'll give you this warrant to enter the house." + ).also { stage++ } + NOT_LISTEN + 2 -> { + if (freeSlots(player!!) == 0) { + sendItemDialogue(player!!, Items.WARRANT_1503, "Bravek waves a warrant at you, but you don't have room to take it.").also { stage = END_DIALOGUE } + } else { + sendItemDialogue(player!!, Items.WARRANT_1503, "Bravek hands you a warrant.").also { stage = END_DIALOGUE } + addItem(player!!, Items.WARRANT_1503) + setQuestStage(player!!, Quests.PLAGUE_CITY, 16) + } + } + + CURED -> playerl(FacialExpression.FRIENDLY, "Not a problem, happy to help out.").also { stage++ } + CURED + 1 -> npcl(FacialExpression.FRIENDLY, " I'm just having a little drop of whisky, then I'll feel really good.").also { stage = END_DIALOGUE } + } + return true + } + + override fun getIds(): IntArray = intArrayOf(NPCs.BRAVEK_711) +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/ClerkDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/ClerkDialogue.kt new file mode 100644 index 000000000..639cd0a8b --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/ClerkDialogue.kt @@ -0,0 +1,98 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue + +import content.data.Quests +import core.api.getQuestStage +import core.api.setQuestStage +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.IfTopic +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +@Initializable +class ClerkDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object{ + const val TALK_AGAIN = 10 + + const val THROUGH_DOOR = 20 + const val PERMISSION = 30 + const val QUESTIONS = 40 + const val URGENT = 60 + const val RUN_EVERYTHING = 70 + const val WHEN_AVAILABLE = 80 + const val DISTURBED = 90 + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + if (getQuestStage(player, Quests.PLAGUE_CITY) < 13) + npcl(FacialExpression.NEUTRAL, "Hello, welcome to the Civic Office of West Ardougne. How can I help you?").also { stage = QUESTIONS } + else + npcl(FacialExpression.FRIENDLY, "Bravek will see you now but keep it short!").also { stage = TALK_AGAIN } + + return true + } + + override fun handle(componentID: Int, buttonID: Int): Boolean { + + when(stage){ + + QUESTIONS -> showTopics( + IfTopic("I need permission to enter a plague house.", PERMISSION, getQuestStage(player, Quests.PLAGUE_CITY) > 11), + Topic("Who is through that door?", THROUGH_DOOR), + Topic("I'm just looking thanks.", END_DIALOGUE), + ) + + // npcl does not wordwrap right + PERMISSION -> npc(FacialExpression.NEUTRAL, "Rather you than me! The mourners normally deal with", + "that stuff, you should speak to them. Their headquarters","are right near the city gate.").also { stage++ } + PERMISSION + 1 -> showTopics( + Topic("I'll try asking them then.", END_DIALOGUE), + Topic("Surely you don't let them run everything for you?", RUN_EVERYTHING), + Topic("This is urgent though!", URGENT, skipPlayer = true) + ) + + RUN_EVERYTHING -> npcl(FacialExpression.NEUTRAL, " Well, they do know what they're doing here. " + + "If they did start doing something badly Bravek, the city warder, would have the power to override them. " + + "I can't see that happening though.").also { stage++ } + RUN_EVERYTHING + 1 -> showTopics( + Topic("I'll try asking them then.", END_DIALOGUE), + Topic("Can I speak to Bravek anyway?", DISTURBED) + ) + + URGENT -> playerl(FacialExpression.PANICKED, " This is urgent though! Someone's been kidnapped and is being held in a plague house!").also { stage++ } + URGENT+ 1 -> npcl(FacialExpression.NEUTRAL, "I'll see what I can do I suppose.").also { stage++ } + URGENT + 2 -> npcl(FacialExpression.NEUTRAL, " Mr Bravek, there's a ${if (player.isMale) "man" else "lady"} here who really needs to speak to you.").also { + stage++ + npc = NPC(NPCs.BRAVEK_711) + } + URGENT + 3 -> npc(FacialExpression.ANNOYED, " I suppose they can come in then. If they keep it short.").also { + stage = END_DIALOGUE + setQuestStage(player, Quests.PLAGUE_CITY, 13) + } + + THROUGH_DOOR -> npcl(FacialExpression.NEUTRAL, "The city warder Bravek is in there.").also { stage++ } + THROUGH_DOOR + 1 -> playerl(FacialExpression.ASKING, " Can I go in?").also { stage = DISTURBED } + + DISTURBED -> npcl(FacialExpression.NEUTRAL, " He has asked not to be disturbed.").also { stage++ } + DISTURBED + 1 -> showTopics( + IfTopic("This is urgent though!", URGENT, getQuestStage(player, Quests.PLAGUE_CITY) > 11, skipPlayer = true), + Topic("Ok, I'll leave him alone.", END_DIALOGUE), + Topic("Do you know when he will be available?", WHEN_AVAILABLE) + ) + + WHEN_AVAILABLE -> npcl(FacialExpression.NEUTRAL, " Oh I don't know, an hour or so maybe.").also { stage = END_DIALOGUE } + + TALK_AGAIN -> playerl(FacialExpression.FRIENDLY, "Thanks, I won't take much of his time.").also { stage = END_DIALOGUE } + } + + return true + } + + override fun getIds(): IntArray = intArrayOf(NPCs.CLERK_713) +} diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/EdmondDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/EdmondDialogue.kt new file mode 100644 index 000000000..8b88a5c9e --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/EdmondDialogue.kt @@ -0,0 +1,268 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners +import content.region.kandarin.ardougne.quest.plaguecity.UndergroundCutscene +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class EdmondDialogue(player: Player? = null) : DialoguePlugin(player) { + + override fun open(vararg args: Any?): Boolean { + val questStage = getQuestStage(player, Quests.PLAGUE_CITY) + npc = args[0] as NPC + if(inEquipmentOrInventory(player, Items.GAS_MASK_1506) && (questStage == 2)) { + playerl(FacialExpression.FRIENDLY, "Hi Edmond, I've got the gas mask now.").also { stage++ } + } + else if (questStage == 4) { + // npcl not formatted quite right + npc(FacialExpression.FRIENDLY, "I think it's the pipe to the south that comes up in West", "Ardougne.").also { stage++ } + + } + else if(questStage == 5){ + playerl( FacialExpression.NEUTRAL, + "Edmond, I can't get through to West Ardougne! There's an iron grill blocking my way, I can't pull it off alone." + ).also { stage++ } + + } + else if(questStage == 6){ + // playerl not formatted quite right + player(FacialExpression.NEUTRAL, "I've tied a rope to the grill over there, will you help me","pull it off?").also { stage++ } + + } + else if(questStage > 2) { + playerl(FacialExpression.FRIENDLY, "Hello Edmond.").also { stage++ } + } + else { + playerl(FacialExpression.FRIENDLY, "Hello old man.").also { stage++ } + } + return true + } + + override fun handle(componentID: Int, buttonID: Int): Boolean { + when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { + + 0 -> when (stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Sorry, I can't stop to talk...").also { stage++ } + 2 -> playerl(FacialExpression.FRIENDLY, "Why, what's wrong?").also { stage++ } + 3 -> npcl( + FacialExpression.FRIENDLY, + "I've got to find my daughter. I pray that she is still alive..." + ).also { stage++ } + + 4 -> options("What's happened to her?", "Well, good luck finding her.").also { stage++ } + 5 -> when (buttonID) { + 1 -> playerl(FacialExpression.FRIENDLY, "What's happened to her?").also { stage = 6 } + 2 -> playerl(FacialExpression.FRIENDLY, "Well, good luck finding her.").also { + stage = END_DIALOGUE + } + } + // npcl does not word wrap correctly + 6 -> npc( + FacialExpression.NEUTRAL, + "Elena's a missionary and a healer. Three weeks ago she", + "managed to cross the Ardougne wall... No-one's allowed", + "to cross the wall in case they spread the plague. But", + "after hearing the screams of suffering she felt she had" + ).also { stage++ } + + 7 -> npcl( + FacialExpression.NEUTRAL, + "to help. She said she'd be gone for a few days but we've heard nothing since." + ).also { stage++ } + + 8 -> options( + "Tell me more about the plague.", + "Can I help find her?", + "I'm sorry, I have to go." + ).also { stage++ } + + 9 -> when (buttonID) { + 1 -> playerl(FacialExpression.FRIENDLY, "Tell me more about the plague.").also { stage = 10 } + 2 -> playerl(FacialExpression.FRIENDLY, "Can I help find her?").also { stage = 11 } + 3 -> playerl(FacialExpression.FRIENDLY, "I'm sorry, I have to go.").also { stage = END_DIALOGUE } + } + + 10 -> npcl( + FacialExpression.FRIENDLY, + "The mourners can tell you more than me. They're the only ones allowed to cross the border. I do know the plague is a horrible way to go... That's why Elena felt she had to go help." + ).also { stage = 8 } + + 11 -> npcl( + FacialExpression.FRIENDLY, + "Really, would you? I've been working on a plan to get into West Ardougne, but I'm too old and tired to carry it through. If you're going into West Ardougne you'll need protection from the plague. My wife made a" + ).also { stage++ } + + 12 -> npcl( + FacialExpression.FRIENDLY, + "special gas mask for Elena with dwellberries rubbed into it. Dwellberries help repel the virus! We need some more though..." + ).also { stage++ } + + 13 -> playerl(FacialExpression.ASKING, "Where can I find these dwellberries?").also { stage++ } + 14 -> npcl( + FacialExpression.FRIENDLY, + "The only place I know of is McGrubor's Wood just north of the Rangers' Guild." + ).also { stage++ } + + 15 -> playerl(FacialExpression.FRIENDLY, "Ok, I'll go and get some.").also { stage++ } + 16 -> npcl( + FacialExpression.NEUTRAL, + "The foresters keep a close eye on it, but there is a back way in." + ).also { stage++ } + + 17 -> { + end() + setQuestStage(player!!, Quests.PLAGUE_CITY, 1) + } + } + + 1 -> when (stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Have you got the dwellberries yet?").also { stage++ } + 2 -> if (!inInventory(player, Items.DWELLBERRIES_2126)) { + playerl(FacialExpression.FRIENDLY, "Sorry, I'm afraid not.").also { stage = 3 } + } else { + playerl(FacialExpression.FRIENDLY, "Yes I've got some here.").also { stage = 6 } + } + + 3 -> npcl( + FacialExpression.NEUTRAL, + "You'll probably find them in McGrubor's Wood it's just west of Seers village." + ).also { stage++ } + + 4 -> playerl(FacialExpression.NEUTRAL, "Ok, I'll go and get some.").also { stage++ } + 5 -> npcl( + FacialExpression.NEUTRAL, + "The foresters keep a close eye on it, but there is a back way in." + ).also { stage = END_DIALOGUE } + + 6 -> npcl(FacialExpression.NEUTRAL, "Take them to my wife Alrena, she's inside.").also { + stage = END_DIALOGUE + } + } + + 2 -> when (stage) { + // npcl formats this wrong + 1 -> npc( + FacialExpression.NEUTRAL, + "Good stuff, now for the digging. Beneath us are the", + "Ardougne sewers, there you'll find", + "access to West Ardougne." + ).also { stage++ } + + 2 -> npc( + FacialExpression.NEUTRAL, "The problem is the soil is rock hard. You'll need to pour", + "on several buckets of water to soften it up. I'll keep an", + "eye out for the mourners." + ).also { stage++ } + + 3 -> { + end() + setQuestStage(player!!, Quests.PLAGUE_CITY, 3) + } + } + + 3 -> when (stage) { + 1 -> if (player!!.getAttribute("/save:elena:dig", false) == true) { + playerl(FacialExpression.NEUTRAL, "I've soaked the soil with water.").also { stage = 3 } + } else { + npcl(FacialExpression.FRIENDLY, "How's it going?").also { stage = 2 } + } + + 2 -> if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 1) { + playerl( + FacialExpression.NEUTRAL, + "I still need to pour three more buckets of water on the soil." + ).also { stage = END_DIALOGUE } + } else if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 2) { + playerl( + FacialExpression.NEUTRAL, + "I still need to pour two more buckets of water on the soil." + ).also { stage = END_DIALOGUE } + } else if (player.getAttribute(PlagueCityListeners.BUCKET_USES_ATTRIBUTE, 0) == 3) { + playerl( + FacialExpression.NEUTRAL, + "I still need to pour one more bucket of water on the soil." + ).also { stage = END_DIALOGUE } + } + + 3 -> npcl( + FacialExpression.FRIENDLY, + "That's great, it should be soft enough to dig through now." + ).also { stage = END_DIALOGUE } + } + + 4 -> when (stage) { + 1 -> playerl(FacialExpression.NEUTRAL, "Alright I'll check it out.").also { stage = END_DIALOGUE } + } + + 5 -> when (stage) { + 1 -> npcl( + FacialExpression.NEUTRAL, + "If you get some rope you could tie to the grill, then we could both pull it at the same time." + ).also { stage = END_DIALOGUE } + } + + 6 -> when(stage){ + 1 -> npcl(FacialExpression.NEUTRAL, "Alright, let's get to it...").also { stage++ } + 2 -> end().also{ UndergroundCutscene(player!!).start() } + } + 7-> when (stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Have you found Elena yet?").also { stage++ } + 2 -> playerl(FacialExpression.NEUTRAL, "Not yet, it's a big city over there.").also { stage++ } + 3 -> npcl(FacialExpression.FRIENDLY, "Don't forget to look for my friend Jethick. He may be able to help.").also { stage = END_DIALOGUE } + } + + 8 -> when (stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Have you found Elena yet?").also { stage++ } + 2 -> playerl(FacialExpression.NEUTRAL, "Not yet, it's a big city over there. Do you have a picture of Elena?").also { stage++ } + 3 -> npcl(FacialExpression.FRIENDLY, "There should be a picture of Elena in the house. Please find her quickly, I hope it's not too late.").also { stage = END_DIALOGUE } + } + + // No source for this branch + in 9..98 -> when(stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Have you found Elena yet?").also { stage++ } + 2 -> playerl(FacialExpression.SAD, "Not yet.").also { stage++ } + 3 -> npcl(FacialExpression.WORRIED, "Please find her quickly, I hope it's not too late.").also { stage = END_DIALOGUE } + } + + 99 -> when (stage) { + 1 -> npcl(FacialExpression.NEUTRAL, "Thank you, thank you! Elena beat you back by minutes.").also { stage++ } + 2 -> npcl(FacialExpression.NEUTRAL, "Now I said I'd give you a reward. What can I give you as a reward I wonder?").also { stage++ } + 3 -> npcl(FacialExpression.NEUTRAL, "Here take this magic scroll, I have little use for it but it may help you.").also { stage++ } + 4 -> { + end() + player!!.questRepository.getQuest(Quests.PLAGUE_CITY).finish(player) + } + } + + 100 -> when (stage) { + 1 -> npcl(FacialExpression.FRIENDLY, "Ah hello again, and thank you again for rescuing my daughter.").also { + stage = if ( + getAttribute(player, PlagueCityListeners.ARDOUGNE_TELE_ATTRIBUTE, false) + || hasAnItem(player, Items.A_MAGIC_SCROLL_1505).exists()) 5 else 2 + } + 2 -> showTopics( + Topic("Do you have any more of those scrolls?", 3), + Topic("No problem.", END_DIALOGUE) + ) + 3 -> npcl(FacialExpression.FRIENDLY, "Here take this magic scroll, I have little use for it but it may help you.").also { + stage = END_DIALOGUE + addItemOrDrop(player!!, Items.A_MAGIC_SCROLL_1505) + } + 5 -> playerl(FacialExpression.NEUTRAL, "No problem.").also { stage = END_DIALOGUE } + } + } + return true + } + + override fun getIds(): IntArray = intArrayOf(NPCs.EDMOND_3213, NPCs.TUNNEL_EDMOND_3214) +} diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/JethickDialogue.kt similarity index 65% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/JethickDialogue.kt index 4674daa6f..4ab027d70 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/JethickDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/JethickDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests import core.api.* import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -9,7 +10,6 @@ import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.Items import org.rs09.consts.NPCs -import content.data.Quests @Initializable class JethickDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -32,28 +32,37 @@ class JethickDialogue(player: Player? = null) : DialoguePlugin(player) { } in 7..9 -> when (stage) { - 1 -> options("Hi, I'm looking for a woman from East Ardougne called Elena.", "So who's in charge here?").also { stage++ } + 1 -> options("Hi, I'm looking for a woman from East Ardougne.", "So who's in charge here?").also { stage++ } 2 -> when (buttonID) { + // This line is authentically different than the question you click 1 -> playerl(FacialExpression.FRIENDLY, "Hi, I'm looking for a woman from East Ardougne called Elena.").also { stage = 3 } 2 -> playerl(FacialExpression.FRIENDLY, "So who's in charge here?").also { stage = END_DIALOGUE } } - 3 -> npcl(FacialExpression.FRIENDLY, "East Ardougnian women are easier to find in East Ardougne. Not many would come to West Ardougne to find one. Although the name is familiar, what does she look like?").also { stage++ } - 4 -> playerl(FacialExpression.NEUTRAL, "Um... brown hair... in her twenties...").also { stage++ } - 5 -> npcl(FacialExpression.NEUTRAL, "Hmm, that doesn't narrow it down a huge amount... I'll need to know more than that, or see a picture?").also { stage++ } - 6 -> if (inInventory(player!!, Items.PICTURE_1510)) { - sendItemDialogue(player!!, Items.PICTURE_1510, "You show Jethick the picture.").also { stage++ } + // word wrap is wrong with npcl + 3 -> npc(FacialExpression.FRIENDLY, "East Ardougnian women are easier to find in East", + "Ardougne. Not many would come to West Ardougne to", + "find one. Although the name is familiar, what does she", + "look like?").also { stage++ } + 4 -> if (inInventory(player!!, Items.PICTURE_1510)) { + sendItemDialogue(player!!, Items.PICTURE_1510, "You show Jethick the picture.").also { stage = 7 } } else { - end() - stage = END_DIALOGUE + playerl(FacialExpression.NEUTRAL, "Um... brown hair... in her twenties...").also { stage++ } } - 7 -> npcl(FacialExpression.FRIENDLY, "She came over here to help to aid plague victims. I think she is staying over with the Rehnison family. They live in the small timbered building at the far north side of town.").also { stage++ } - 8 -> npcl(FacialExpression.FRIENDLY, "I've not seen her around here for a while, mind. I don't suppose you could run me a little errand while you're over there? I borrowed this book from them, could you return it?").also { stage++ } - 9 -> options("Yes, I'll return it for you.", "No, I don't have time for that.").also { stage++ } - 10 -> when (buttonID) { - 1 -> playerl(FacialExpression.NEUTRAL, "Yes, I'll return it for you.").also { stage = 11 } + 5 -> npcl(FacialExpression.NEUTRAL, "Hmm, that doesn't narrow it down a huge amount... I'll need to know more than that, or see a picture?").also { stage = END_DIALOGUE } + + // npcl doesn't wrap right + 7 -> npc(FacialExpression.FRIENDLY, "She came over here to help to aid plague victims. I", + "think she is staying over with the Rehnison family. They", + "live in the small timbered building at the far north side", + "of town. I've not seen her around here in a while,").also { stage++ } + 8 -> npcl(FacialExpression.FRIENDLY, "mind. ").also { stage++ } + 9 -> npcl(FacialExpression.FRIENDLY, "I don't suppose you could run me a little errand while you're over there? I borrowed this book from them, can you return it?").also { stage++ } + 10 -> options("Yes, I'll return it for you.", "No, I don't have time for that.").also { stage++ } + 11 -> when (buttonID) { + 1 -> playerl(FacialExpression.NEUTRAL, "Yes, I'll return it for you.").also { stage = 12 } 2 -> playerl(FacialExpression.NEUTRAL, "No, I don't have time for that.").also { stage = END_DIALOGUE } } - 11 -> if(freeSlots(player) == 0) { + 12 -> if(freeSlots(player) == 0) { end() sendItemDialogue(player!!, Items.BOOK_1509, "Jethick shows you the book, but you don't have room to take it.") stage = END_DIALOGUE diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/KidnappedElenaDialogue.kt similarity index 79% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/KidnappedElenaDialogue.kt index 01f40dc88..2fe574b61 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/ElenaDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/KidnappedElenaDialogue.kt @@ -1,6 +1,8 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests import core.api.setQuestStage +import core.api.setVarbit import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC @@ -8,10 +10,10 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs -import content.data.Quests +import org.rs09.consts.Vars @Initializable -class ElenaDialogue(player: Player? = null) : DialoguePlugin(player) { +class KidnappedElenaDialogue(player: Player? = null) : DialoguePlugin(player) { override fun open(vararg args: Any?): Boolean { npc = args[0] as NPC @@ -31,11 +33,13 @@ class ElenaDialogue(player: Player? = null) : DialoguePlugin(player) { 4 -> { end() setQuestStage(player!!, Quests.PLAGUE_CITY, 99) + setVarbit(player, Vars.VARBIT_QUEST_PLAGUE_CITY_RESCUE_ELENA, 1) + setVarbit(player, Vars.VARBIT_QUEST_PLAGUE_CITY_EDMOND_TUNNELS, 0) stage = END_DIALOGUE } } return true } - override fun getIds(): IntArray = intArrayOf(NPCs.ELENA_3215) + override fun getIds(): IntArray = intArrayOf(NPCs.KIDNAPPED_ELENA_715) } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MarthaRehnisonDialogue.kt similarity index 96% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MarthaRehnisonDialogue.kt index 8893f9c3d..4b2aa051e 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MarthaRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MarthaRehnisonDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests import core.api.getQuestStage import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -8,7 +9,6 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs -import content.data.Quests @Initializable class MarthaRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MilliRehnisonDialogue.kt similarity index 61% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MilliRehnisonDialogue.kt index 649a922f1..3f5fe54a9 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/MilliRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/MilliRehnisonDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests import core.api.getQuestStage import core.api.setQuestStage import core.game.dialogue.DialoguePlugin @@ -9,7 +10,6 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs -import content.data.Quests @Initializable class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -19,7 +19,7 @@ class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { if (player.questRepository.getStage(Quests.PLAGUE_CITY) == 9) { playerl(FacialExpression.FRIENDLY, "Hello. Your parents say you saw what happened to Elena...").also { stage++ } } else { - npcl(FacialExpression.FRIENDLY, "Any luck finding Elena yet?").also { stage++ } + npcl(FacialExpression.CHILD_FRIENDLY, "Any luck finding Elena yet?").also { stage++ } } return true } @@ -28,24 +28,26 @@ class MilliRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { 9 -> when(stage) { - 1 -> npcl(FacialExpression.NEUTRAL, "*sniff* Yes I was near the south east corner when I saw Elena walking by. I was about to run to greet her when some men jumped out. They shoved a sack over her head and dragged her into a building.").also { stage++ } + // Wordwrap doesn't match using npcl + 1 -> npc(FacialExpression.CHILD_SAD, "*sniff* Yes I was near the south east corner when I", + "saw Elena walking by. I was about to run to greet her", + "when some men jumped out. They shoved a sack over", + "her head and dragged her into a building.").also { stage++ } 2 -> playerl(FacialExpression.FRIENDLY, "Which building?").also { stage++ } - 3 -> npcl(FacialExpression.NEUTRAL, "It was the boarded up building with no windows in the south east corner of West Ardougne.").also { stage++ } - 4 -> { - end() - setQuestStage(player!!, Quests.PLAGUE_CITY, 11) + 3 -> npcl(FacialExpression.CHILD_NORMAL, "It was the boarded up building with no windows in the south east corner of West Ardougne.").also { stage = END_DIALOGUE + setQuestStage(player!!, Quests.PLAGUE_CITY, 11) } } in 10..98 -> when (stage) { 1 -> playerl(FacialExpression.FRIENDLY, "Not yet...").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "I wish you luck, she did a lot for us.").also { stage = END_DIALOGUE } + 2 -> npcl(FacialExpression.CHILD_FRIENDLY, "I wish you luck, she did a lot for us.").also { stage = END_DIALOGUE } } in 99..100 -> when (stage) { 1 -> playerl(FacialExpression.FRIENDLY, "Yes, she is safe at home now.").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "That's good to hear, she helped us a lot.").also { stage = END_DIALOGUE } + 2 -> npcl(FacialExpression.CHILD_FRIENDLY, "That's good to hear, she helped us a lot.").also { stage = END_DIALOGUE } } } return true diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/TedRehnisonDialogue.kt similarity index 90% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/TedRehnisonDialogue.kt index 9eadacf27..b26c60d26 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/TedRehnisonDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/TedRehnisonDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue +import content.data.Quests import core.api.getQuestStage import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -8,7 +9,6 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs -import content.data.Quests @Initializable class TedRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { @@ -30,7 +30,7 @@ class TedRehnisonDialogue(player: Player? = null) : DialoguePlugin(player) { 9 -> when (stage) { 1 -> npcl(FacialExpression.FRIENDLY, "Yes she was staying here, but slightly over a week ago she was getting ready to go back. However she never managed to leave. My daughter Milli was playing near the west wall when she saw some shadowy figures jump").also { stage++ } - 2 -> npcl(FacialExpression.FRIENDLY, "out and grab her. Milli is upstairs if you wish to speak to her.").also { stage = END_DIALOGUE } + 2 -> npc(FacialExpression.FRIENDLY, "out and grab her. Milli is upstairs if you wish to speak", "to her.").also { stage = END_DIALOGUE } } in 10..98 -> when (stage) { diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerArdougneWallDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerArdougneWallDialogue.kt new file mode 100644 index 000000000..83b1c9d52 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerArdougneWallDialogue.kt @@ -0,0 +1,61 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue.mourners + +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +/** + * This is the Mourner patrolling close to the wall in E Ardougne + */ +@Initializable +class MournerArdougneWallDialogue(player: Player? = null) : DialoguePlugin(player){ + + companion object{ + const val START_DIALOGUE = 0 + const val PLAGUE = 20 + const val SYMPTOMS = 40 + } + + override fun open(vararg args: Any?): Boolean { + playerl(FacialExpression.NEUTRAL, "Hi.").also { stage = START_DIALOGUE } + return true + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(stage){ + START_DIALOGUE -> npcl(FacialExpression.NEUTRAL, " What are you up to?").also { stage++ } + START_DIALOGUE + 1 -> playerl(FacialExpression.NEUTRAL, " Just sight-seeing.").also { stage++ } + START_DIALOGUE + 2 -> npcl(FacialExpression.NEUTRAL, "This is no place for sight-seeing. Don't you know there's been a plague outbreak?").also { stage++ } + START_DIALOGUE + 3 -> playerl(FacialExpression.NEUTRAL, " Yes, I had heard.").also { stage++ } + START_DIALOGUE + 4 -> npcl(FacialExpression.NEUTRAL, " Then I suggest you leave as soon as you can.").also { stage++ } + START_DIALOGUE + 5 -> showTopics( + Topic("What brought the plague to Ardougne?", PLAGUE), + Topic("What are the symptoms of the plague?", SYMPTOMS), + Topic("Thanks for the advice.", END_DIALOGUE), + ) + + PLAGUE -> npcl(FacialExpression.NEUTRAL, " It's all down to King Tyras of West Ardougne. " + + "'Rather than protecting his people he spends his time in the lands to the West. ").also { stage++ } + PLAGUE + 1 -> npcl(FacialExpression.NEUTRAL, "When he returned last he brought the plague with him then left before the problem became serious.").also { stage++ } + PLAGUE + 2 -> playerl(FacialExpression.ASKING, " Does he know how bad the situation is now?").also { stage++ } + PLAGUE + 3 -> npcl(FacialExpression.ANGRY, " If he did he wouldn't care. I believe he wants his people to suffer, he's an evil man.").also { stage++ } + PLAGUE + 4 -> playerl(FacialExpression.EXTREMELY_SHOCKED, " Isn't that treason?").also { stage++ } + PLAGUE + 5 -> npcl(FacialExpression.DISGUSTED_HEAD_SHAKE, " He's not my king.").also { stage = END_DIALOGUE } + + SYMPTOMS -> npcl(FacialExpression.NEUTRAL, "The first signs are typical flu symptoms. These tend to be followed by severe nightmares, horrifying hallucinations which drive many to madness.").also { stage++ } + SYMPTOMS + 1 -> playerl(FacialExpression.DISGUSTED, "Sounds nasty.").also { stage++ } + SYMPTOMS + 2 -> npcl(FacialExpression.NEUTRAL, " It gets worse. Next the victim's blood changes into a thick black tar-like liquid, at this point they're past help.").also { stage++ } + SYMPTOMS + 3 -> npcl(FacialExpression.NEUTRAL, "Their skin is cold to the touch, the victim is now brain dead. Their body however lives on driven by the virus, roaming like a zombie, spreading itself further wherever possible.").also { stage++ } + SYMPTOMS + 4 -> playerl(FacialExpression.DISGUSTED_HEAD_SHAKE, " I think I've heard enough.").also { stage = END_DIALOGUE } + + } + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_719) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerEdmondHouseDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerEdmondHouseDialogue.kt new file mode 100644 index 000000000..97d62f0ff --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerEdmondHouseDialogue.kt @@ -0,0 +1,115 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue.mourners + +import content.data.Quests +import core.api.getQuestStage +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +/** + * This is for the mourner wandering around Edmonds house + */ + +@Initializable +class MournerEdmondHouseDialogue(player: Player? = null) : DialoguePlugin(player){ + + companion object { + const val BEFORE_PLAGUE_CITY = 10 + const val BEFORE_GAS_MASK = 20 + const val BEFORE_SOFTEN_GROUND = 30 + const val SYMPTOMS1 = 40 + const val FEEL_FINE = 50 + const val PLAGUE_SOURCE1 = 60 + const val BEFORE_DIG = 70 + const val AFTER_DIG = 80 + const val AFTER_ENTER_W_ARDOUGNE = 90 + } + + override fun open(vararg args: Any?): Boolean { + when (getQuestStage(player, Quests.PLAGUE_CITY)){ + 0 -> playerl(FacialExpression.NEUTRAL, "Hello there.").also { stage = BEFORE_PLAGUE_CITY } + 1 -> playerl(FacialExpression.NEUTRAL, "Hello.").also { stage = BEFORE_GAS_MASK } + 2 -> playerl(FacialExpression.NEUTRAL, "Hello.").also { stage = BEFORE_SOFTEN_GROUND } + 3 -> playerl(FacialExpression.NEUTRAL, "Hello.").also { stage = BEFORE_DIG } + 4 -> playerl(FacialExpression.NEUTRAL, "Hello there.").also { stage = AFTER_DIG } + else -> playerl(FacialExpression.NEUTRAL, "Hello.").also { stage = AFTER_ENTER_W_ARDOUGNE } + } + return true + } + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(stage){ + BEFORE_PLAGUE_CITY -> npcl(FacialExpression.NEUTRAL, "Do you have a problem traveller?").also { stage++ } + BEFORE_PLAGUE_CITY + 1 -> playerl(FacialExpression.ASKING, "No, I just wondered why you're wearing that outfit... Is it fancy dress?").also { stage++ } + BEFORE_PLAGUE_CITY + 2 -> npcl(FacialExpression.NEUTRAL, "No! It's for protection.").also { stage++ } + BEFORE_PLAGUE_CITY + 3 -> playerl(FacialExpression.ASKING, "Protection from what?").also { stage++ } + BEFORE_PLAGUE_CITY + 4 -> npcl(FacialExpression.NEUTRAL, "The plague of course...").also { stage = END_DIALOGUE } + + BEFORE_GAS_MASK -> npcl(FacialExpression.NEUTRAL, "What do you want?").also { stage++ } + BEFORE_GAS_MASK + 1 -> showTopics( + Topic("Who are you?", BEFORE_GAS_MASK + 3), + Topic("Nothing, just being polite.", BEFORE_GAS_MASK + 2) + ) + BEFORE_GAS_MASK + 2 -> npcl(FacialExpression.NEUTRAL, "Hmmm, ok then. Be on your way.").also { stage = END_DIALOGUE } + BEFORE_GAS_MASK + 3 -> npcl(FacialExpression.NEUTRAL, "I'm a mourner. It's my job to help heal the plague victims of West Ardougne and to make sure the disease is contained.").also { stage++ } + BEFORE_GAS_MASK + 4 -> playerl(FacialExpression.THINKING, "Very noble of you.").also { stage++ } + BEFORE_GAS_MASK + 5 -> npcl(FacialExpression.NEUTRAL, "If you come down with any symptoms such as flu or nightmares let me know immediately.").also { stage = END_DIALOGUE } + + BEFORE_SOFTEN_GROUND -> npcl(FacialExpression.NEUTRAL, "Are you ok?").also { stage++ } + BEFORE_SOFTEN_GROUND + 1 -> playerl(FacialExpression.NEUTRAL, "Yes, I'm fine thanks.").also { stage++ } + BEFORE_SOFTEN_GROUND + 2 -> npcl(FacialExpression.NEUTRAL, "Have you experienced any plague symptoms?").also { stage++ } + BEFORE_SOFTEN_GROUND + 3 -> showTopics( + Topic("What are the symptoms?", SYMPTOMS1), + Topic("No, I feel fine", FEEL_FINE), + Topic("No, but can you tell me where the plague came from?", PLAGUE_SOURCE1) + ) + + SYMPTOMS1 -> npcl(FacialExpression.NEUTRAL, "First you'll come down with heavy flu, this is usually followed by horrifying nightmares.").also { stage++ } + SYMPTOMS1 + 1 -> playerl(FacialExpression.HALF_WORRIED, "I used to have nightmares when I was younger.").also { stage++ } + SYMPTOMS1 + 2 -> npcl(FacialExpression.NEUTRAL, "Not like these I assure you. Soon after a thick black liquid will seep from your nose and eyes.").also { stage++ } + SYMPTOMS1 + 3 -> playerl(FacialExpression.HALF_WORRIED, "Yuck!").also { stage++ } + SYMPTOMS1 + 4 -> npcl(FacialExpression.HALF_WORRIED, "When it gets to that stage there's nothing we can do for you.").also { stage = END_DIALOGUE } + + FEEL_FINE -> npcl(FacialExpression.NEUTRAL, "Well if you take a turn for the worse let me know straight away.").also { stage++ } + FEEL_FINE + 1 -> playerl(FacialExpression.HALF_WORRIED, "Can you cure it then?").also { stage++ } + FEEL_FINE + 2 -> npcl(FacialExpression.NEUTRAL, "No... But you will have to be treated.").also { stage++ } + FEEL_FINE + 3 -> playerl(FacialExpression.WORRIED, "Treated?").also { stage++ } + FEEL_FINE + 4 -> npcl(FacialExpression.NEUTRAL, "We have to take measures to contain the disease. " + + "That's why you must let us know immediately if you take a turn for the worse.").also { stage = END_DIALOGUE } + + PLAGUE_SOURCE1 -> npcl(FacialExpression.NEUTRAL, "It all started when King Tyras of West Ardougne came back from one of his visits to the lands west of here.").also { stage++ } + PLAGUE_SOURCE1 + 1 -> npcl(FacialExpression.NEUTRAL, "Some of his men must have unknowingly caught it out there and brought it back with them").also { stage = END_DIALOGUE } + + BEFORE_DIG -> npcl(FacialExpression.ASKING, "What are you up to with old man Edmond?").also { stage++ } + BEFORE_DIG + 1 -> playerl(FacialExpression.HALF_GUILTY, "Nothing, we've just been chatting.").also { stage++ } + BEFORE_DIG + 2 -> npcl(FacialExpression.ASKING, "What about his daughter?").also { stage++ } + BEFORE_DIG + 3 -> playerl(FacialExpression.HALF_GUILTY, "Oh, you know about that then?").also { stage++ } + BEFORE_DIG + 4 -> npcl(FacialExpression.NEUTRAL, "We know about everything that goes on in Ardougne. We have to if we are to contain the plague.").also { stage++ } + BEFORE_DIG + 5 -> playerl(FacialExpression.HALF_ASKING, "Have you see his daughter recently?").also { stage++ } + BEFORE_DIG + 6 -> npcl(FacialExpression.NEUTRAL, "I imagine she's caught the plague. Either way she won't be allowed out of West Ardougne, the risk is too great.").also { stage = END_DIALOGUE } + + AFTER_DIG -> npcl(FacialExpression.ASKING, "Been digging have we?").also { stage++ } + AFTER_DIG + 1 -> playerl(FacialExpression.HALF_GUILTY, "What do you mean?").also { stage++ } + AFTER_DIG + 2 -> npcl(FacialExpression.NEUTRAL, "Your hands are covered in mud.").also { stage++ } + AFTER_DIG + 3 -> playerl(FacialExpression.HALF_GUILTY, "Oh that...").also { stage++ } + AFTER_DIG + 4 -> npcl(FacialExpression.THINKING, "Funny, you don't look like the gardening type.").also { stage++ } + AFTER_DIG + 5 -> playerl(FacialExpression.NEUTRAL, "Oh no, I love gardening! It's my favorite pastime.").also { stage = END_DIALOGUE } + + AFTER_ENTER_W_ARDOUGNE -> npcl(FacialExpression.ASKING, " What are you up to?").also { stage++ } + AFTER_ENTER_W_ARDOUGNE + 1 -> playerl(FacialExpression.HALF_GUILTY, "Nothing.").also { stage++ } + AFTER_ENTER_W_ARDOUGNE + 2 -> npcl(FacialExpression.SUSPICIOUS, "I don't trust you.").also { stage++ } + AFTER_ENTER_W_ARDOUGNE + 3 -> playerl(FacialExpression.NEUTRAL, "You don't have to.").also { stage++ } + AFTER_ENTER_W_ARDOUGNE + 4 -> npcl(FacialExpression.SUSPICIOUS, "If I find you attempting to cross the wall I'll make sure you never return.").also { stage = END_DIALOGUE } + + } + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_718) + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerGuardDialogue.kt similarity index 96% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerGuardDialogue.kt index 778b5f947..529554cdb 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/quest/elena/HeadMournerDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerGuardDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.quest.elena +package content.region.kandarin.ardougne.quest.plaguecity.dialogue.mourners +import content.data.Quests import core.api.getQuestStage import core.api.setQuestStage import core.game.dialogue.DialogueFile @@ -8,12 +9,11 @@ import core.game.node.entity.npc.NPC import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.NPCs -import content.data.Quests @Initializable -class HeadMournerDialogue : DialogueFile() { +class MournerGuardDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { - npc = NPC(NPCs.HEAD_MOURNER_716) + npc = NPC(NPCs.MOURNER_717) when (getQuestStage(player!!, Quests.PLAGUE_CITY)) { in 8..10 -> when (stage) { @@ -38,8 +38,8 @@ class HeadMournerDialogue : DialogueFile() { 2 -> options("But I think a kidnap victim is in here.", "I fear not a mere plague.", "Thanks for the warning.").also { stage++ } 3 -> when (buttonID) { 1 -> playerl(FacialExpression.FRIENDLY, "But I think a kidnap victim is in here.").also { stage = 5 } - 2 -> playerl(FacialExpression.FRIENDLY, "I fear not a mere plague.").also { stage = 4 } - 3 -> playerl(FacialExpression.FRIENDLY, "Thanks for the warning.").also { stage = END_DIALOGUE } + 2 -> playerl(FacialExpression.FRIENDLY, "I fear not a mere plague.").also { stage = 5 } + 3 -> playerl(FacialExpression.FRIENDLY, "Thanks for the warning.").also { stage = 4 } } 4 -> playerl(FacialExpression.FRIENDLY, "Thanks for the warning.").also { stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt new file mode 100644 index 000000000..671b7d38b --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt @@ -0,0 +1,184 @@ +package content.region.kandarin.ardougne.quest.plaguecity.dialogue.mourners + +import content.data.Quests +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.global.action.DoorActionHandler +import core.game.interaction.QueueStrength +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.world.map.Location +import core.game.world.map.RegionManager +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +/** + * These are the mourners guarding the kidnap building + */ +@Initializable +class MournerKidnapDialogue(player: Player? = null) :DialoguePlugin(player) { + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, MournerKidnapDialogueFile(), npc) + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_3216) + } +} + +/** + * Most of the work is in the dialogue file so the player can access this by trying to enter the room + */ +class MournerKidnapDialogueFile : DialogueFile(){ + + companion object { + const val KIDNAP = 10 + const val FEAR = 30 + const val CLEARANCE = 40 + + var closeMourner : NPC? = null + var farMourner : NPC? = null + + val eDoor: Location = Location.create(2540, 3273, 0) + val wDoor: Location = Location.create(2533, 3273, 0) + + var east = false + + } + override fun handle(componentID: Int, buttonID: Int) { + // Figure out who we are. It needs to be this since we can enter this dialogue from a door + // Do this for the first time regardless of where we are + if (stage == 0) { + RegionManager.getLocalNpcs(player!!, 2).forEach { + if (it.id == NPCs.MOURNER_3216) { + closeMourner = it + resetFace(closeMourner!!) + face(closeMourner!!, player!!) + face(player!!, closeMourner!!) + } + } + + east = player!!.location.x > 2537 + } + if (hasAnItem(player!!, Items.WARRANT_1503).exists()){ + when (stage){ + 0 -> npcl( + FacialExpression.NEUTRAL, + " I'd stand away from there. That black cross means that house has been touched by the plague." + ).also { stage++ } + + 1 -> playerl(FacialExpression.FRIENDLY, " I have a warrant from Bravek to enter here.").also { stage++ } + 2 -> npcl(FacialExpression.HALF_WORRIED, " This is highly irregular. Please wait...").also { stage++ } + 3 -> { + // Look further for the other one + RegionManager.getLocalNpcs(player!!, 10).forEach { + if (it.id == NPCs.MOURNER_3216 && it != closeMourner){ + farMourner = it + resetFace(farMourner!!) + } + } + + // I don't know why the queue has to be on this mourner to get both talking + val mournerQueue = if (east) farMourner else closeMourner + + queueScript(mournerQueue!!, 1, QueueStrength.WEAK) { animStage: Int -> + when(animStage){ + 0 -> { + end() + forceWalk(player!!, if (east) eDoor else wDoor, "smart") + face(closeMourner!!, farMourner!!) + // Legit typo + sendChat(closeMourner!!, "Hay... I got someone here with a warrant from Bravek, what should we do?") + // Immediately set the quest stage in case the player clicks again + if (getQuestStage(player!!, Quests.PLAGUE_CITY) < 17){ + setQuestStage(player!!, Quests.PLAGUE_CITY, 17) + } + return@queueScript delayScript(mournerQueue, 1) + } + 3 -> { + face(farMourner!!, closeMourner!! ) + sendChat(farMourner!!, "Well you can't let them in...") + return@queueScript delayScript(mournerQueue, 1) + } + 5 -> { + resetFace(player!!) + return@queueScript delayScript(mournerQueue, 1) + } + 6 -> { + // only walk the player if they have not walked themselves through + if (player!!.location.y > 3272) + DoorActionHandler.handleAutowalkDoor(player, getScenery (if (east) eDoor else wDoor)) + sendDialogue(player!!, "You wait until the mourner's back is turned and sneak into the building.").also { stage = END_DIALOGUE} + resetFace(closeMourner!!) + resetFace(farMourner!!) + return@queueScript delayScript(mournerQueue, 1) + } + 10 -> { + // Face north again + face(closeMourner!!, Location.create(closeMourner!!.location.x, 3275, 0)) + face(farMourner!!, Location.create(farMourner!!.location.x, 3275, 0)) + return@queueScript stopExecuting(mournerQueue) + } + } + return@queueScript delayScript(mournerQueue, 1) + } + + } + + } + } + else { + + when (stage) { + 0 -> npcl( + FacialExpression.NEUTRAL, + " I'd stand away from there. That black cross means that house has been touched by the plague." + ).also { stage = if (getQuestStage(player!!, Quests.PLAGUE_CITY) == 11) stage + 1 else END_DIALOGUE } + + 1 -> showTopics( + Topic("But I think a kidnap victim is in here.", KIDNAP), + Topic("I fear not a mere plague.", FEAR), + Topic("Thanks for the warning.", END_DIALOGUE), + ) + + KIDNAP -> npcl( + FacialExpression.NEUTRAL, + "Sounds unlikely, even kidnappers wouldn't go in there. Even if someone is in there, they're probably dead by now." + ).also { stage++ } + + KIDNAP + 1 -> showTopics( + Topic("Good point.", END_DIALOGUE), + Topic("I want to check anyway.", KIDNAP + 2) + ) + + KIDNAP + 2 -> npcl(FacialExpression.NEUTRAL, "You don't have clearance to go in there.").also { + stage = CLEARANCE + } + + FEAR -> npcl( + FacialExpression.NEUTRAL, + " That's irrelevant. You don't have clearance to go in there." + ).also { stage = CLEARANCE } + + CLEARANCE -> playerl(FacialExpression.ASKING, " How do I get clearance?").also { stage++ } + CLEARANCE + 1 -> npcl( + FacialExpression.NEUTRAL, + " Well you'd need to apply to the head mourner, or I suppose Bravek the city warder." + ).also { stage++ } + + CLEARANCE + 2 -> npcl(FacialExpression.NEUTRAL, " I wouldn't get your hopes up though.").also { + stage = END_DIALOGUE + setQuestStage(player!!, Quests.PLAGUE_CITY, 12) + } + } + } + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/MournerUtilities.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/MournerUtilities.kt new file mode 100644 index 000000000..461a15a54 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/MournerUtilities.kt @@ -0,0 +1,57 @@ +package content.region.kandarin.ardougne.westardougne + +import core.api.EquipmentSlot +import core.api.allInEquipment +import core.api.getItemFromEquipment +import core.api.inEquipment +import core.game.node.entity.player.Player +import org.rs09.consts.Items + +object MournerUtilities { + + const val NO_GEAR = 0 + const val JUST_MASK = 1 + const val JUST_GEAR = 2 + const val EXTRA_GEAR = 3 + + /** + * Check if the player is wearing just mourner gear + * @return 0 incomplete gear 1 mask only 2 complete gear only 3 complete gear with extras + */ + fun wearingMournerGear(player: Player): Int { + // Check that the play has all of these items + if (inEquipment(player, Items.GAS_MASK_1506)) { + // We have a mask + if (!allInEquipment( + player, Items.MOURNER_TOP_6065, Items.MOURNER_TROUSERS_6067, + Items.MOURNER_BOOTS_6069, Items.MOURNER_GLOVES_6068, Items.MOURNER_CLOAK_6070 + ) + ) { + // We have only a mask + return JUST_MASK + } + else { + // Check if we have other gear + + // These use up slots 0, 1, 4, 7, 9, 10. Check the others are empty + val mournerSlots = arrayOf( + EquipmentSlot.HEAD, EquipmentSlot.CAPE, EquipmentSlot.CHEST, + EquipmentSlot.LEGS, EquipmentSlot.HANDS, EquipmentSlot.FEET + ) + for (slot in EquipmentSlot.values()) { + // Skip the slots that we know have the gear equipped + if (mournerSlots.contains(slot)) continue + if (getItemFromEquipment(player, slot) != null) { + return EXTRA_GEAR + } + } + return JUST_GEAR + } + + } + else { + // We don't even have a mask + return NO_GEAR + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CarlaDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CarlaDialogue.kt similarity index 98% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CarlaDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CarlaDialogue.kt index 8e1ea65e5..a3431f603 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/CarlaDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CarlaDialogue.kt @@ -1,4 +1,4 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue +package content.region.kandarin.ardougne.westardougne.dialogue import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ChildDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ChildDialogue.kt similarity index 64% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ChildDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ChildDialogue.kt index 96cbd880d..210d0ee8d 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/ChildDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ChildDialogue.kt @@ -1,5 +1,6 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue +package content.region.kandarin.ardougne.westardougne.dialogue +import content.region.kandarin.ardougne.westardougne.MournerUtilities import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression import core.game.node.entity.npc.NPC @@ -18,9 +19,8 @@ class ChildDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun handle(interfaceId: Int, buttonId: Int): Boolean { - when (stage) { - 0 -> npcl(FacialExpression.FRIENDLY, "I'm not allowed to speak with strangers.").also { stage = END_DIALOGUE } - } + val noun = if (MournerUtilities.wearingMournerGear(player) > MournerUtilities.JUST_MASK) "mourners" else "strangers" + npcl(FacialExpression.CHILD_NORMAL, "I'm not allowed to speak with $noun.").also { stage = END_DIALOGUE } return true } @@ -29,7 +29,7 @@ class ChildDialogue(player: Player? = null) : DialoguePlugin(player) { } override fun getIds(): IntArray { - return intArrayOf(NPCs.CHILD_6339, NPCs.CHILD_6345, NPCs.CHILD_356) + return intArrayOf(NPCs.CHILD_356, NPCs.CHILD_355) } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CivilianDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CivilianDialogue.kt new file mode 100644 index 000000000..dcf6f73fa --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/CivilianDialogue.kt @@ -0,0 +1,181 @@ +package content.region.kandarin.ardougne.westardougne.dialogue + +import content.region.kandarin.ardougne.westardougne.MournerUtilities +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + + +val cats = intArrayOf( + Items.PET_CAT_1561, + Items.PET_CAT_1562, + Items.PET_CAT_1563, + Items.PET_CAT_1564, + Items.PET_CAT_1565, + Items.PET_CAT_1566, + Items.OVERGROWN_CAT_1567, + Items.OVERGROWN_CAT_1568, + Items.OVERGROWN_CAT_1569, + Items.OVERGROWN_CAT_1570, + Items.OVERGROWN_CAT_1571, + Items.OVERGROWN_CAT_1572, + // todo implement these cats then uncomment this + // otherwise you get an exception which just steals your cat for no runes + // Items.LAZY_CAT_6549, + // Items.LAZY_CAT_6550, + // Items.LAZY_CAT_6551, + // Items.LAZY_CAT_6552, + // Items.LAZY_CAT_6553, + // Items.LAZY_CAT_6554, + // Items.WILY_CAT_6555, + // Items.WILY_CAT_6556, + // Items.WILY_CAT_6557, + // Items.WILY_CAT_6558, + // Items.WILY_CAT_6559, + // Items.WILY_CAT_6560, +) + +@Initializable +class CivilianDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object { + // Any of these + + + const val DIAG1 = 10 + const val DIAG2 = 20 + const val DIAG3 = 30 + + const val NO_CAT = 40 + const val BUY_CATS = 50 + const val REJECT_DEAL = 80 + const val WITCH_CAT = 90 + + const val MOURNER = 100 + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + if (MournerUtilities.wearingMournerGear(player) > MournerUtilities.JUST_MASK){ + playerl(FacialExpression.NEUTRAL, "Hello.").also { stage = MOURNER } + } + else { + when (npc.id) { + NPCs.CIVILIAN_785 -> playerl(FacialExpression.NEUTRAL, "Hello there.").also { stage = DIAG1 } + NPCs.CIVILIAN_786 -> playerl(FacialExpression.NEUTRAL, "Hi there.").also { stage = DIAG2 } + NPCs.CIVILIAN_787 -> player(FacialExpression.NEUTRAL, "Hello there.").also { stage = DIAG3 } + } + } + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when (stage) { + DIAG1 -> npcl(FacialExpression.HALF_GUILTY, "Oh hello, I'm sorry, I'm a bit worn out.").also { stage++ } + DIAG1 + 1 -> playerl(FacialExpression.NEUTRAL, "Busy day?").also { stage++ } + DIAG1 + 2 -> npcl(FacialExpression.HALF_GUILTY, "Oh, It's those mice! They're everywhere! " + + "What I really need is a cat. But they're hard to come by nowadays.").also { + stage = checkCat() + } + + DIAG2 -> npcl(FacialExpression.NEUTRAL, "Good day to you traveller.").also { stage++ } + DIAG2 + 1 -> playerl(FacialExpression.NEUTRAL, "What are you up to?").also { stage++ } + DIAG2 + 2 -> npcl(FacialExpression.NEUTRAL, "Chasing mice as usual! It's all I seem to do nowadays.").also { stage++ } + DIAG2 + 3 -> playerl(FacialExpression.NEUTRAL, "You must waste a lot of time?").also { stage++ } + DIAG2 + 4 -> npcl(FacialExpression.HALF_WORRIED, "Yes, but what can you do? It's not like there's many cats around here!").also{ stage = checkCat() + } + + DIAG3 -> npcl(FacialExpression.HALF_WORRIED, "I'm a bit busy to talk right now, sorry.").also { stage++ } + DIAG3 + 1 -> playerl(FacialExpression.NEUTRAL, "Why? What are you doing?").also { stage++ } + DIAG3 + 2 -> npcl(FacialExpression.HALF_WORRIED, "Trying to kill these mice! What I really need is a cat!").also { stage = checkCat() } + + NO_CAT -> playerl(FacialExpression.HALF_WORRIED, "No, you're right, you don't see many around.").also { stage = END_DIALOGUE } + + BUY_CATS -> showTopics( + Topic("I have a cat that I could sell.", BUY_CATS + 1), + Topic("Nope, they're not easy to get hold of.", END_DIALOGUE) + ) + // intentional whitespace typo + BUY_CATS + 1 -> npcl(FacialExpression.ASKING, "You don't say, is that it ?").also { stage++ } + BUY_CATS + 2 -> playerl(FacialExpression.HAPPY, "Say hello to a real mouse killer!").also { stage++ } + BUY_CATS + 3 -> npcl(FacialExpression.HALF_ASKING, "Hmmm, not bad, not bad at all. Looks like it's a lively one.").also { stage++ } + BUY_CATS + 4 -> playerl(FacialExpression.HALF_GUILTY, "Erm...kind of...").also { stage++ } + BUY_CATS + 5 -> npcl(FacialExpression.FRIENDLY, "I don't have much in the way of money. I do have these!").also { stage++ } + BUY_CATS + 6 -> sendDialogue("The peasant shows you a sack of Death Runes.").also { stage++ } + BUY_CATS + 7 -> npcl(FacialExpression.ASKING, "The dwarves bring them from the mine for us. Tell you what, I'll give you 100 Death Runes for the cat.").also { stage++ } + BUY_CATS + 8 -> showTopics( + Topic("Nope, I'm not parting for that.", REJECT_DEAL), + Topic("Ok then, you've got a deal.", BUY_CATS+9) + ) + BUY_CATS + 9 -> { + npcl(FacialExpression.HAPPY, "Great! Hand over the cat and I'll give you the runes.").also { + stage = END_DIALOGUE + for (cat in cats) { + if (removeItem(player, cat)){ + player.familiarManager.removeDetails(cat) + addItem(player, Items.DEATH_RUNE_560, 100) + break + } + } + } + } + + REJECT_DEAL -> npcl(FacialExpression.HALF_GUILTY, "Well, I'm not giving you anymore!").also { stage = END_DIALOGUE } + + WITCH_CAT -> playerl(FacialExpression.HAPPY, "I have a cat...look!").also { stage++ } + WITCH_CAT + 1 -> npcl(FacialExpression.HALF_WORRIED, "Hmmm...doesn't look like it's seen daylight in years. That's not going to catch any mice!").also { stage = END_DIALOGUE } + + + MOURNER -> npcl(FacialExpression.ANGRY, "If you Mourners really wanna help, why don't you do something about these mice?!").also { stage = END_DIALOGUE } + } + return true + } + + private fun checkCat(): Int { + return if (anyInInventory(player, *cats)) BUY_CATS + else if (inInventory(player, Items.WITCHS_CAT_1491)) WITCH_CAT + else NO_CAT + + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.CIVILIAN_785, NPCs.CIVILIAN_786, NPCs.CIVILIAN_787) + } +} + + +class CatTrade : InteractionListener{ + override fun defineListeners() { + + class CatTradeDialogue : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + when (stage){ + 0 -> sendDialogue(player!!, "You hand over the cat. You are given 100 Death Runes.").also { stage++ } + 1 -> npcl(FacialExpression.HAPPY, "Great, thanks for that!").also { stage++ } + 2 -> playerl(FacialExpression.NEUTRAL, "That's ok, take care.").also { stage = END_DIALOGUE } + } + } + } + onUseWith(IntType.NPC, cats, NPCs.CIVILIAN_785, NPCs.CIVILIAN_786, NPCs.CIVILIAN_787){ player, used, with -> + if(removeItem(player, used)){ + val dialogue = CatTradeDialogue() + // Remove the cat + player.familiarManager.removeDetails(used.id) + addItem(player, Items.DEATH_RUNE_560, 100) + openDialogue(player, dialogue, with as NPC) + } + + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/HeadMournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/HeadMournerDialogue.kt new file mode 100644 index 000000000..65671e952 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/HeadMournerDialogue.kt @@ -0,0 +1,115 @@ +package content.region.kandarin.ardougne.westardougne.dialogue + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCity +import content.region.kandarin.ardougne.westardougne.MournerUtilities +import core.api.* +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.IfTopic +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.NPCs +import kotlin.properties.Delegates + +@Initializable +class HeadMournerDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object { + const val CLEARANCE = 40 + const val WHATS_A_MOURNER = 10 + const val NO_PLAGUE = 20 + const val ELENA = 30 + + const val CRAZY = 50 + const val KIDNAP = 60 + const val MASK = 70 + + var mourningGear by Delegates.notNull() + + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + mourningGear = MournerUtilities.wearingMournerGear(player) + if(mourningGear < MournerUtilities.JUST_GEAR){ + npcl(FacialExpression.ANGRY, "How did you get into West Ardougne? " + + "Ah well you'll have to stay, can't risk you spreading the plague outside.").also { stage++ } + } + else{ + npcl(FacialExpression.NEUTRAL, "Ahh... A new recruit.").also { stage++ } + } + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(mourningGear){ + MournerUtilities.NO_GEAR, MournerUtilities.JUST_MASK -> when(stage){ + START_DIALOGUE + 1 -> showTopics( + IfTopic("I need clearance to enter a plague house.", CLEARANCE, + !isQuestComplete(player, Quests.PLAGUE_CITY) && (getQuestStage(player, Quests.PLAGUE_CITY) > 11)), + Topic("So what's a mourner?", WHATS_A_MOURNER), + Topic("I haven't got the plague though. ", NO_PLAGUE), + IfTopic("I'm looking for a woman named Elena.", ELENA, !isQuestComplete(player, Quests.PLAGUE_CITY)) + ) + + CLEARANCE -> npcl(FacialExpression.DISGUSTED, "You must be nuts, absolutely not!").also { stage++ } + CLEARANCE + 1 -> showTopics( + Topic("There's a kidnap victim inside!", KIDNAP), + Topic("I've got a gas mask though...", MASK), + Topic("Yes, I'm utterly crazy.", CRAZY) + ) + + KIDNAP -> npcl(FacialExpression.FRIENDLY, "Well they're as good as dead then, no point in trying to save them.").also { stage = END_DIALOGUE } + + MASK -> npcl(FacialExpression.FRIENDLY, "It's not regulation. Anyway you're not properly trained to deal with the plague.").also { stage++ } + MASK + 1 -> playerl(FacialExpression.FRIENDLY, "How do I get trained?").also { stage++ } + MASK + 2 -> npcl(FacialExpression.FRIENDLY, "It requires a strict 18 months of training.").also { stage++ } + MASK + 3 -> playerl(FacialExpression.FRIENDLY, "I don't have that sort of time.").also { stage = END_DIALOGUE } + + CRAZY -> npcl(FacialExpression.FRIENDLY, "You're wasting my time, I have a lot of work to do!").also { stage = END_DIALOGUE } + + WHATS_A_MOURNER -> npcl(FacialExpression.NEUTRAL, + "We're working for King Lathas of East Ardougne trying to contain the accursed plague sweeping West Ardougne." + + " We also do our best to ease these people's suffering.").also { stage++ } + WHATS_A_MOURNER + 1 -> npcl(FacialExpression.NEUTRAL, "We're nicknamed mourners because we spend a lot of" + + " time at plague victim funerals, no-one else is allowed to risk the funerals." + + " It's a demanding job, and we get little thanks from the people here.").also { stage = END_DIALOGUE } + + NO_PLAGUE -> npcl(FacialExpression.ANNOYED, "Can't risk you being a carrier. That protective clothing you have isn't regulation issue. It won't meet safety standards.").also { stage = END_DIALOGUE } + + ELENA -> npcl( + FacialExpression.NEUTRAL, + "Ah yes, I've heard of her. A healer I believe. She must be mad coming over here voluntarily." + ).also { stage++ } + + ELENA + 1 -> npcl( + FacialExpression.SAD, + "I hear rumours she has probably caught the plague now. Very tragic, a stupid waste of life." + ).also { stage = END_DIALOGUE } + + } + + MournerUtilities.JUST_GEAR, MournerUtilities.EXTRA_GEAR -> when(stage){ + START_DIALOGUE+1 ->playerl(FacialExpression.ASKING, " How do you know I'm new?").also { stage++ } + START_DIALOGUE+2 -> npcl(FacialExpression.NEUTRAL, "Because all the old members of the guard know to report to the real Head Mourner, not me.").also { if (mourningGear == MournerUtilities.EXTRA_GEAR) stage++ else stage+=2 } + START_DIALOGUE+3 -> npcl(FacialExpression.ANNOYED, "Also, none of the old timers use non-regulation gear.").also { stage++ } + START_DIALOGUE+4 -> playerl(FacialExpression.ASKING, " You're not the real overseer here?").also { stage++ } + START_DIALOGUE+5 -> npcl(FacialExpression.NEUTRAL, "No, I am just a front man, our true head is far too busy to deal with the requests of the citizens, so I conduct the day to day business here.").also { stage++ } + START_DIALOGUE+6 -> npcl(FacialExpression.NEUTRAL, "You should go and report in" + if(mourningGear == MournerUtilities.EXTRA_GEAR) ", I would lose the non-regulation gear as well if I were you." else "." ).also { stage++ } + START_DIALOGUE+7 -> playerl(FacialExpression.FRIENDLY, "Okay, thanks.").also { stage = END_DIALOGUE } + } + } + return true + } + + + override fun getIds(): IntArray { + return intArrayOf(NPCs.HEAD_MOURNER_716) + } + +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ManWomanDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ManWomanDialogue.kt new file mode 100644 index 000000000..a86698f3d --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/ManWomanDialogue.kt @@ -0,0 +1,81 @@ +package content.region.kandarin.ardougne.westardougne.dialogue + +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.RandomFunction +import org.rs09.consts.NPCs + +@Initializable +class ManWomanDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object { + const val DIAG1 = 10 + const val DIAG2 = 20 + const val DIAG3 = 30 + const val DIAG4 = 40 + const val DIAG5 = 50 + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC + val path = RandomFunction.random(1, 6) + val msg = when(path){ + 1,5 -> "Good day." + 2 -> "Hi there." + 3, 4 -> "Hello, how's it going?" + else -> "Hello" + } + + playerl(FacialExpression.FRIENDLY, msg).also { stage = path * 10 } + + return true + } + + override fun handle(componentID: Int, buttonID: Int): Boolean { + when (stage){ + DIAG1 -> npcl(FacialExpression.HALF_ASKING, "An outsider! Can you get me out of this hell hole?").also { stage++ } + DIAG1 + 1 -> playerl(FacialExpression.SAD, "Sorry, that's not what I'm here to do.").also { stage = END_DIALOGUE } + + DIAG2 -> npcl(FacialExpression.ANNOYED, "Go away. People from the outside shut us in like animals. I have nothing to say to you.").also { stage = END_DIALOGUE } + + DIAG3 -> npcl(FacialExpression.SAD, "Life is tough.").also { stage++ } + DIAG3 + 1 -> showTopics( + Topic("Yes, living in a plague city must be hard.", DIAG3 + 2), + Topic("I'm sorry to hear that.", DIAG3 + 3), + Topic("I'm looking for a lady called Elena.", DIAG3 + 4) + ) + DIAG3 + 2 -> npcl(FacialExpression.HALF_GUILTY, "Plague? Pah, that's no excuse for the treatment we've received. It's obvious pretty quickly if someone has the plague. I'm thinking about making a break for it. I'm perfectly healthy, not gonna infect anyone.").also { stage = END_DIALOGUE } + DIAG3 + 3 -> npcl(FacialExpression.SAD, "Well, aint much either you or me can do about it.").also { stage = END_DIALOGUE } + DIAG3 + 4 -> npcl(FacialExpression.NEUTRAL, "I've not heard of her. Old Jethick knows a lot of people, maybe he'll know where you can find her.").also { stage = END_DIALOGUE } + + DIAG4 -> npcl(FacialExpression.ANNOYED, "Bah, those mourners... they're meant to be helping us, but I think they're doing more harm here than good. They won't even let me send a letter out to my family.").also{ stage++} + DIAG4 + 1 -> showTopics( + Topic("Have you seen a lady called Elena around here?", DIAG4 + 2), + Topic("You should stand up to them more.", DIAG4 + 3) + ) + DIAG4 + 2 -> npcl(FacialExpression.SAD, "Yes, I've seen her. Very helpful person. Not for the last few days though... I thought maybe she'd gone home.").also { stage = END_DIALOGUE } + DIAG4 + 3 -> npcl(FacialExpression.HALF_GUILTY, " Oh I'm not one to cause a fuss.").also { stage = END_DIALOGUE } + + DIAG5 -> npcl(FacialExpression.ANGRY, "We don't have good days here anymore. Curse King Tyras.").also { stage++ } + DIAG5 + 1 -> showTopics( + Topic("Oh ok, bad day then.", END_DIALOGUE), + Topic("Why, what has he done?", DIAG5 + 2), + Topic("I'm looking for a woman called Elena.", DIAG5 + 3) + ) + DIAG5 + 2 -> npcl(FacialExpression.ANGRY, "His army curses our city with this plague then wanders off again, leaving us to clear up the pieces.").also { stage = END_DIALOGUE } + DIAG5 + 3 -> npcl(FacialExpression.NEUTRAL, "Not heard of her.").also { stage = END_DIALOGUE } + } + return true + } + + override fun getIds(): IntArray { + + return intArrayOf(NPCs.MAN_728, NPCs.MAN_729, NPCs.MAN_351, + NPCs.WOMAN_352, NPCs.WOMAN_353, NPCs.WOMAN_354, NPCs.WOMAN_360, NPCs.WOMAN_361, NPCs.WOMAN_362, NPCs.WOMAN_363) + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/MournerDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/MournerDialogue.kt new file mode 100644 index 000000000..da0ef56ae --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/MournerDialogue.kt @@ -0,0 +1,114 @@ +package content.region.kandarin.ardougne.westardougne.dialogue + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCity +import content.region.kandarin.ardougne.westardougne.MournerUtilities.EXTRA_GEAR +import content.region.kandarin.ardougne.westardougne.MournerUtilities.JUST_GEAR +import content.region.kandarin.ardougne.westardougne.MournerUtilities.JUST_MASK +import content.region.kandarin.ardougne.westardougne.MournerUtilities.NO_GEAR +import content.region.kandarin.ardougne.westardougne.MournerUtilities.wearingMournerGear +import core.api.getQuestStage +import core.game.dialogue.* +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +@Initializable +class MournerDialogue(player: Player? = null) : DialoguePlugin(player) { + + companion object{ + const val WHATS_A_MOURNER = 10 + const val NO_PLAGUE = 20 + const val ELENA = 30 + + const val CONVO_1 = 40 + const val CONVO_2 = 50 + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when(wearingMournerGear(player)){ + NO_GEAR, JUST_MASK -> { + if (npc.id == NPCs.MOURNER_717) { + when (stage) { + 0 -> npcl( + FacialExpression.HALF_ASKING, + "Hmmm, how did you get over here? You're not one of this rabble. Ah well, you'll have to stay. Can't risk you going back now." + ).also { stage++ } + + 1 -> showTopics( + Topic("So what's a mourner?", WHATS_A_MOURNER), + Topic("I haven't got the plague though... ", NO_PLAGUE), + IfTopic( + "I'm looking for a woman named Elena.", + ELENA, + getQuestStage(player, Quests.PLAGUE_CITY) in (6..98) + ) + ) + + WHATS_A_MOURNER -> npcl( + FacialExpression.NEUTRAL, + "We're working for King Lathas of East Ardougne trying to contain the accursed plague sweeping West Ardougne." + + " We also do our best to ease these people's suffering." + ).also { stage++ } + + WHATS_A_MOURNER + 1 -> npcl( + FacialExpression.NEUTRAL, "We're nicknamed mourners because we spend a lot of" + + " time at plague victim funerals, no-one else is allowed to risk the funerals." + + " It's a demanding job, and we get little thanks from the people here." + ).also { stage = END_DIALOGUE } + + ELENA -> npcl( + FacialExpression.NEUTRAL, + "Ah yes, I've heard of her. A healer I believe. She must be mad coming over here voluntarily." + ).also { stage++ } + + ELENA + 1 -> npcl( + FacialExpression.SAD, + "I hear rumours she has probably caught the plague now. Very tragic, a stupid waste of life." + ).also { stage = END_DIALOGUE } + + NO_PLAGUE -> npcl( + FacialExpression.ANNOYED, + "Can't risk you being a carrier. That protective clothing you have isn't regulation issue. It won't meet safety standards." + ).also { stage = END_DIALOGUE } + } + } + else{ + npcl(FacialExpression.ANNOYED, "Stand back citizen, do not approach me.").also { stage = END_DIALOGUE } + } + + } + JUST_GEAR -> { + when(stage){ + 0 -> playerl(FacialExpression.NEUTRAL, "Hello.").also { + stage = if((0..1).random() > 0) CONVO_1 else CONVO_2 + } + + CONVO_1 -> npcl(FacialExpression.NEUTRAL, "Good day. Are you in need of assistance?").also { stage++ } + CONVO_1 + 1 -> playerl(FacialExpression.NEUTRAL, " Yes, but I don't think you can help.").also { stage++ } + CONVO_1 + 2 -> npcl(FacialExpression.NEUTRAL, " You will be surprised at how much help the brute force of the Guard can be.").also { stage++ } + CONVO_1 + 3 -> playerl(FacialExpression.NEUTRAL, " Well I'll be sure to ask if I'm in need of some muscle.").also { stage = END_DIALOGUE } + + CONVO_2 -> npcl(FacialExpression.ANNOYED, " Good day. Are you in need of assistance?").also { stage++ } + CONVO_2 + 1 -> playerl(FacialExpression.NEUTRAL, " No, I just wanted to talk to a friendly face.").also { stage++ } + CONVO_2 + 2 -> npcl(FacialExpression.ANGRY, " Do I look friendly to you? I really must work on my scowl more.").also { stage = END_DIALOGUE } + } + + } + EXTRA_GEAR -> { + when(stage){ + 0 -> npcl(FacialExpression.ANNOYED, "You should know better than to wear non-regulation gear.").also { stage++ } + 1 -> playerl(FacialExpression.HALF_GUILTY, "Sorry, I'm new around here.").also { stage++ } + 2 -> npcl(FacialExpression.ANNOYED, "Well, you know the drill - lose the gear, I will let it pass this time.").also { stage = END_DIALOGUE } + } + } + } + + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOURNER_717, NPCs.MOURNER_348, NPCs.MOURNER_347, NPCs.MOURNER_371, NPCs.MOURNER_369) + } +} diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/NurseSarahDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/NurseSarahDialogue.kt similarity index 87% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/NurseSarahDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/NurseSarahDialogue.kt index d628c9cef..fd7fbcd9b 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/NurseSarahDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/NurseSarahDialogue.kt @@ -1,4 +1,4 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue +package content.region.kandarin.ardougne.westardougne.dialogue import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression @@ -20,7 +20,7 @@ class NurseSarahDialogue(player: Player? = null) : DialoguePlugin(player) { override fun handle(interfaceId: Int, buttonId: Int): Boolean { when (stage) { 0 -> npcl(FacialExpression.FRIENDLY, "Hello my dear, how are you feeling?").also { stage++ } - 1 -> playerl(FacialExpression.FRIENDLY, "Hello my dear, how are you feeling?").also { stage++ } + 1 -> playerl(FacialExpression.FRIENDLY, "I'm ok thanks.").also { stage++ } 2 -> npcl(FacialExpression.FRIENDLY, "Well in that case I'd better get back to work. Take care.").also { stage++ } 3 -> playerl(FacialExpression.FRIENDLY, "You too.").also { stage = END_DIALOGUE } } diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/PriestDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/PriestDialogue.kt similarity index 94% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/PriestDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/PriestDialogue.kt index 6e035d659..472884667 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/PriestDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/PriestDialogue.kt @@ -1,4 +1,4 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue +package content.region.kandarin.ardougne.westardougne.dialogue import core.game.dialogue.DialoguePlugin import core.game.dialogue.FacialExpression diff --git a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/RecruiterDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/RecruiterDialogue.kt similarity index 95% rename from Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/RecruiterDialogue.kt rename to Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/RecruiterDialogue.kt index 672414c02..3e53af8c2 100644 --- a/Server/src/main/content/region/kandarin/ardougne/plaguecity/dialogue/RecruiterDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/dialogue/RecruiterDialogue.kt @@ -1,4 +1,4 @@ -package content.region.kandarin.ardougne.plaguecity.dialogue +package content.region.kandarin.ardougne.westardougne.dialogue import core.api.sendNPCDialogue import core.game.dialogue.DialoguePlugin diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt new file mode 100644 index 000000000..b76f5ac83 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt @@ -0,0 +1,32 @@ +package content.region.kandarin.ardougne.westardougne.handlers + +import content.data.Quests +import core.api.* +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.world.map.Location +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery + +class MainGatesListener : InteractionListener { + + override fun defineListeners() { + on(intArrayOf(Scenery.ARDOUGNE_WALL_DOOR_9738, Scenery.ARDOUGNE_WALL_DOOR_9330), IntType.SCENERY, "open") { player, node -> + if (isQuestComplete(player, Quests.BIOHAZARD)) { + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } else if(inBorders(player, 2556, 3298, 2557, 3301)){ + lock(player,2) + sendMessage(player, "You pull on the large wooden doors...") + queueScript(player,2){ + sendMessage(player, "...but they will not open.") + return@queueScript stopExecuting(player) + } + } else { + face(player, Location.create(2559, 3302, 0)) + sendNPCDialogue(player, NPCs.MOURNER_2349, "Oi! What are you doing? Get away from there!") + } + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MournerHQDoors.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MournerHQDoors.kt new file mode 100644 index 000000000..2c540b027 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MournerHQDoors.kt @@ -0,0 +1,66 @@ +package content.region.kandarin.ardougne.westardougne.handlers + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCity +// import core.api.hasAnItem +import core.api.isQuestComplete +import core.api.openDialogue +import core.api.teleport +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.world.map.Location +import core.tools.END_DIALOGUE +import core.tools.START_DIALOGUE +import org.rs09.consts.NPCs +// import org.rs09.consts.Items +import org.rs09.consts.Scenery + +class MournerHQDoors : InteractionListener { + + override fun defineListeners() { + class MournerHQDialogue : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + npc = NPC(NPCs.MOURNER_347) + // todo check only the mourner gear is equipped + when (stage){ + START_DIALOGUE -> npcl(FacialExpression.ANNOYED, "Who are you? Go away!").also { stage = END_DIALOGUE } + // Wearing extra gear + /* + Mourner: You should know better than to wear non-regulation gear. + Player: Sorry, I'm new around here. + Mourner: Well, you know the drill - lose the gear, I will let it pass this time. + */ + } + + } + } + + // Front door + on(Scenery.DOOR_2036, IntType.SCENERY, "open"){ player, node-> + //todo after Mourning's End I is implemented make this check for wearing mourner gear + if(isQuestComplete(player, Quests.PLAGUE_CITY)){ + DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) + } + else{ + openDialogue(player, MournerHQDialogue()) + } + return@on true + } + + on(Scenery.TRAPDOOR_8783, IntType.SCENERY, "open"){ player, _-> + // https://youtu.be/P-ns2kyvIGs?si=_DfI-V8KCyNoRtss&t=560 + //todo after Mourning's End II is implemented make this check for a New Key 6104 + // if(hasAnItem(player, Items.NEW_KEY_6104).exists()){ + teleport(player, Location.create(2044,4649, 0)) + //} + //else{ + // sendMessage(player, "The trapdoor appears locked") + //} + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/SarahsBox.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/SarahsBox.kt new file mode 100644 index 000000000..191c4dca5 --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/SarahsBox.kt @@ -0,0 +1,38 @@ +package content.region.kandarin.ardougne.westardougne.handlers + +import content.data.Quests +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCity +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.item.Item +import org.rs09.consts.Items +import org.rs09.consts.Scenery + +class SarahsBox : InteractionListener { + override fun defineListeners() { + + on(Scenery.BOX_2062, IntType.SCENERY, "open") { _, node -> + val box = node as core.game.node.scenery.Scenery + replaceScenery(box, Scenery.BOX_2063, -1) + return@on true + } + + on(Scenery.BOX_2063, IntType.SCENERY, "search"){ player, _ -> + if(isQuestComplete(player, Quests.PLAGUE_CITY)){ + if(hasSpaceFor(player, Item(Items.DOCTORS_GOWN_430)) && !hasAnItem(player, Items.DOCTORS_GOWN_430).exists()){ + sendMessage(player, "You find a medical gown in the box.") + addItem(player, Items.DOCTORS_GOWN_430) + return@on true + } + } + sendMessage(player, "You search the box but find nothing") + return@on true + } + + on(Scenery.BOX_2063, IntType.SCENERY, "close") { _, node -> + replaceScenery(node.asScenery(), Scenery.BOX_2062, -1) + return@on true + } + } +} diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/WearMaskListener.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/WearMaskListener.kt new file mode 100644 index 000000000..7ed43f74e --- /dev/null +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/WearMaskListener.kt @@ -0,0 +1,42 @@ +package content.region.kandarin.ardougne.westardougne.handlers + +import content.data.Quests +import core.api.inBorders +import core.api.isQuestComplete +import core.api.openDialogue +import core.api.sendDialogue +import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression +import core.game.interaction.InteractionListener +import core.tools.END_DIALOGUE +import org.rs09.consts.Items + +class WearMaskListener : InteractionListener { + override fun defineListeners() { + onUnequip(Items.GAS_MASK_1506){ player, _ -> + if (isQuestComplete(player, Quests.BIOHAZARD)){ + return@onUnequip true + } + else{ + if( + inBorders(player, 2511, 3266, 2556, 3334) || + inBorders(player, 2464, 3281, 2511, 3334) || + inBorders(player, 2461, 3281,2463, 3322) || + inBorders(player, 2435, 3307, 2463, 3322) + ){ + openDialogue(player, MaskChat()) + return@onUnequip false + } + return@onUnequip true + } + } + } +} + +class MaskChat : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + playerl(FacialExpression.WORRIED, "I should probably keep the gas mask on whilst I'm in West Ardougne.").also { stage = END_DIALOGUE } + } + +} + diff --git a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt index 26daeac81..71471bf43 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TreeGnomeVillageListeners.kt @@ -93,17 +93,25 @@ class TreeGnomeVillageListeners : InteractionListener { return@on true } on(closedChest, IntType.SCENERY, "open"){ player, node -> - SceneryBuilder.replace(node.asScenery(), Scenery(openedChest, node.location, node.asScenery().rotation),10) + replaceScenery(node.asScenery(), openedChest, -1) val upperGuard: NPC = RegionManager.getNpc(player.location, NPCs.KHAZARD_COMMANDER_478, 6) ?: return@on true upperGuard.sendChat("Oi. You! Get out of there.") upperGuard.attack(player) return@on true } on(openedChest, IntType.SCENERY, "search"){ player, _ -> - if(!inInventory(player,Items.ORB_OF_PROTECTION_587)){ - sendDialogue(player,"You search the chest. Inside you find the gnomes' stolen orb of protection.") - addItemOrDrop(player,Items.ORB_OF_PROTECTION_587) + if (getQuestStage(player, Quests.TREE_GNOME_VILLAGE) >= 31) { + if (!hasAnItem(player, Items.ORB_OF_PROTECTION_587).exists()) { + sendDialogue(player, "You search the chest. Inside you find the gnomes' stolen orb of protection.") + addItemOrDrop(player, Items.ORB_OF_PROTECTION_587) + return@on true + } } + sendMessage(player, "You search the chest but find nothing.") + return@on false + } + on(openedChest, IntType.SCENERY, "close"){ _, node -> + replaceScenery(node.asScenery(), closedChest, -1) return@on true } on(strongholdDoor, IntType.SCENERY, "open"){ player, node -> @@ -119,9 +127,7 @@ class TreeGnomeVillageListeners : InteractionListener { } fun squeezeThrough(player: Player){ - val squeezeAnim = Animation.create(3844) - - var dest = if (player.location.y >= 3161) + val dest = if (player.location.y >= 3161) player.location.transform(Direction.SOUTH, 1) else player.location.transform(Direction.NORTH, 1) diff --git a/Server/src/main/core/ServerConstants.kt b/Server/src/main/core/ServerConstants.kt index 55a0eca1d..26923a269 100644 --- a/Server/src/main/core/ServerConstants.kt +++ b/Server/src/main/core/ServerConstants.kt @@ -18,7 +18,7 @@ class ServerConstants { var NOAUTH_DEFAULT_ADMIN: Boolean = true @JvmField - var CURRENT_SAVEFILE_VERSION = 2 + var CURRENT_SAVEFILE_VERSION = 3 @JvmField var DAILY_ACCOUNT_LIMIT = 3 diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index ec322b555..8bb326fe5 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -195,6 +195,18 @@ fun inEquipment(player: Player, id: Int, amount: Int = 1): Boolean { return amountInEquipment(player, id) >= amount } +/** + * Check if any item is in a player's inventory + * @param player the player + * @param ids the set of item ids to check + * @return true if the player has at least one of the items in their inventory, false if none are present + */ +fun anyInInventory(player: Player, vararg ids: Int): Boolean { + return ids.any{ id -> + inInventory(player, id) + } +} + /** * Check if an item exists in a player's equipment or inventory * @param player the player whose equipment to check @@ -1702,9 +1714,10 @@ fun closeAllInterfaces(player: Player) { * @param player the player to send the dialogue to * @param msg the message to send. * @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY + * @param hide should the continue button be hidden? */ -fun sendPlayerDialogue(player: Player, msg: String, expr: core.game.dialogue.FacialExpression = core.game.dialogue.FacialExpression.FRIENDLY) { - player.dialogueInterpreter.sendDialogues(player, expr, *splitLines(msg)) +fun sendPlayerDialogue(player: Player, msg: String, expr: core.game.dialogue.FacialExpression = core.game.dialogue.FacialExpression.FRIENDLY, hide: Boolean = false) { + player.dialogueInterpreter.sendDialogues(player, expr, hide, *splitLines(msg)) } /** @@ -1723,9 +1736,11 @@ fun sendPlayerOnInterface(player: Player, iface: Int, child: Int) { * @param npc the ID of the NPC to use for the chathead * @param msg the message to send. * @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY + * @param hide should the continue button be hidden? */ -fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: core.game.dialogue.FacialExpression = core.game.dialogue.FacialExpression.FRIENDLY) { - player.dialogueInterpreter.sendDialogues(npc, expr, *splitLines(msg)) +fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: core.game.dialogue.FacialExpression = core.game.dialogue.FacialExpression.FRIENDLY, + hide: Boolean = false) { + player.dialogueInterpreter.sendDialogues(npc, expr, hide, *splitLines(msg)) } /** diff --git a/Server/src/main/core/game/activity/Cutscene.kt b/Server/src/main/core/game/activity/Cutscene.kt index 2cf25e068..5cf9584ec 100644 --- a/Server/src/main/core/game/activity/Cutscene.kt +++ b/Server/src/main/core/game/activity/Cutscene.kt @@ -122,11 +122,12 @@ abstract class Cutscene(val player: Player) { * @param expression the FacialExpression the NPC should use * @param message the message to send * @param onContinue (optional) a method that runs when the dialogue is "continued." Increments the cutscene stage by default. + * @param hide Should the continue button be hidden? */ - fun dialogueUpdate(npcId: Int, expression: core.game.dialogue.FacialExpression, message: String, onContinue: () -> Unit = {incrementStage()}) + fun dialogueUpdate(npcId: Int, expression: core.game.dialogue.FacialExpression, message: String, onContinue: () -> Unit = {incrementStage()}, hide: Boolean = false) { logCutscene("Sending NPC dialogue update.") - sendNPCDialogue(player, npcId, message, expression) + sendNPCDialogue(player, npcId, message, expression, hide) player.dialogueInterpreter.addAction { _,_ -> onContinue.invoke() } } diff --git a/Server/src/main/core/game/dialogue/DialogueInterpreter.java b/Server/src/main/core/game/dialogue/DialogueInterpreter.java index ae6c16977..b37a610db 100644 --- a/Server/src/main/core/game/dialogue/DialogueInterpreter.java +++ b/Server/src/main/core/game/dialogue/DialogueInterpreter.java @@ -434,7 +434,7 @@ public final class DialogueInterpreter { * @return The chatbox component. */ public Component sendDialogues(Entity entity, int expression, String... messages) { - return sendDialogues(entity instanceof Player ? -1 : ((NPC) entity).getShownNPC(player).getId(), expression, messages); + return sendDialogues(entity instanceof Player ? -1 : ((NPC) entity).getShownNPC(player).getId(), expression, false, messages); } /** @@ -442,12 +442,11 @@ public final class DialogueInterpreter { * @param npcId The npc id. * @param expression The entity's facial expression. * @param messages The messages. - * @param hide the continue. + * @param hide should the continue button be hidden? * @return The chatbox component. */ public Component sendDialogues(int npcId, FacialExpression expression, boolean hide, String... messages) { - sendDialogues(npcId, expression == null ? -1 : expression.getAnimationId(), messages); - return player.getInterfaceManager().getChatbox(); + return sendDialogues(npcId, expression == null ? -1 : expression.getAnimationId(), hide, messages); } /** @@ -458,34 +457,18 @@ public final class DialogueInterpreter { * @return The chatbox component. */ public Component sendDialogues(Entity entity, FacialExpression expression, boolean hide, String... messages) { - sendDialogues(entity, expression, messages); - player.getPacketDispatch().sendInterfaceConfig(player.getInterfaceManager().getChatbox().getId(), 3, hide); - return player.getInterfaceManager().getChatbox(); + return sendDialogues(entity.getId(), expression == null ? -1 : expression.getAnimationId(), hide, messages); } /** * Send dialogues based on the amount of specified messages. * @param expression The entity's facial expression. * @param messages The messages. - * @param hide the continue. + * @param hide should the continue button be hidden? * @return The chatbox component. */ public Component sendDialogues(Entity entity, int expression, boolean hide, String... messages) { - sendDialogues(entity, expression, messages); - player.getPacketDispatch().sendInterfaceConfig(player.getInterfaceManager().getChatbox().getId(), 3, hide); - return player.getInterfaceManager().getChatbox(); - } - - /** - * Send dialogues based on the amount of specified messages. - * @param expression The entity's facial expression. - * @param messages The messages. - * @return The chatbox component. - */ - public Component sendDialogues(int npcId, int expression, boolean hide, String... messages) { - sendDialogues(npcId, expression, messages); - player.getPacketDispatch().sendInterfaceConfig(player.getInterfaceManager().getChatbox().getId(), 3, hide); - return player.getInterfaceManager().getChatbox(); + return sendDialogues(entity.getId(), expression, hide, messages); } /** @@ -496,7 +479,7 @@ public final class DialogueInterpreter { * @return The chatbox component. */ public Component sendDialogues(int npcId, FacialExpression expression, String... messages) { - return sendDialogues(npcId, expression == null ? -1 : expression.getAnimationId(), messages); + return sendDialogues(npcId, expression == null ? -1 : expression.getAnimationId(),false, messages); } static Pattern GENDERED_SUBSTITUTION = Pattern.compile("@g\\[([^,]*),([^\\]]*)\\]"); @@ -512,7 +495,6 @@ public final class DialogueInterpreter { m.appendTail(sb); return sb.toString(); } - /** * Send dialogues based on the amount of specified messages. * @param npcId The npc id. @@ -521,18 +503,31 @@ public final class DialogueInterpreter { * @return The chatbox component. */ public Component sendDialogues(int npcId, int expression, String... messages) { + return sendDialogues(npcId, expression, false, messages); + } + + /** + * Send dialogues based on the amount of specified messages. + * @param npcId The npc id. + * @param expression The entity's facial expression. + * @param messages The messages. + * @param hide should the continue button be hidden? + * @return The chatbox component. + */ + public Component sendDialogues(int npcId, int expression, boolean hide, String... messages) { if (messages.length < 1 || messages.length > 4) { System.err.println("Invalid amount of messages: " + messages.length); return null; } boolean npc = npcId > -1; int interfaceId = (npc ? 240 : 63) + messages.length; + interfaceId += hide ? 4 : 0; if (expression == -1) { expression = FacialExpression.HALF_GUILTY.getAnimationId(); } player.getPacketDispatch().sendAnimationInterface(expression, interfaceId, 2); + player.getPacketDispatch().sendItemOnInterface(-1, 1, interfaceId, 1); if (npc) { - player.getPacketDispatch().sendItemOnInterface(-1, 1, interfaceId, 1); player.getPacketDispatch().sendNpcOnInterface(npcId, interfaceId, 2); player.getPacketDispatch().sendString(NPCDefinition.forId(npcId).getName(), interfaceId, 3); } else { @@ -540,7 +535,7 @@ public final class DialogueInterpreter { player.getPacketDispatch().sendString(player.getUsername(), interfaceId, 3); } for (int i = 0; i < messages.length; i++) { - player.getPacketDispatch().sendString(doSubstitutions(player, messages[i].toString()), interfaceId, (i + 4)); + player.getPacketDispatch().sendString(doSubstitutions(player, messages[i]), interfaceId, (i + 4)); } player.getInterfaceManager().openChatbox(interfaceId); player.getPacketDispatch().sendInterfaceConfig(player.getInterfaceManager().getChatbox().getId(), 3, false); diff --git a/Server/src/main/core/game/global/action/EquipHandler.kt b/Server/src/main/core/game/global/action/EquipHandler.kt index bab80e779..29299e238 100644 --- a/Server/src/main/core/game/global/action/EquipHandler.kt +++ b/Server/src/main/core/game/global/action/EquipHandler.kt @@ -33,11 +33,19 @@ class EquipHandler : InteractionListener { fun handleEquip(player: Player, node: Node) { val item = node.asItem() + val itemEquipmentSlot = item.definition.getConfiguration(ItemConfigParser.EQUIP_SLOT, -1) - if (item == null || player.inventory[item.slot] != item || item.name.toLowerCase().contains("goblin mail")) { + val currentEquippedItem = player.equipment[itemEquipmentSlot] + if (item == null || currentEquippedItem == item || item.name.toLowerCase().contains("goblin mail")) { return } + if(currentEquippedItem != null){ + if(!InteractionListeners.run(currentEquippedItem.id, player, currentEquippedItem, false)){ + return + } + } + val equipStateListener = item.definition.getConfiguration>("equipment", null) if (equipStateListener != null) { val bool = equipStateListener.fireEvent("equip", player, item) @@ -45,7 +53,7 @@ class EquipHandler : InteractionListener { return } } - if (!InteractionListeners.run(node.id, player, node, true)) { + if (!InteractionListeners.run(node.id, player, item, true)) { return } @@ -70,7 +78,6 @@ class EquipHandler : InteractionListener { playAudio(player, item.definition.getConfiguration(ItemConfigParser.EQUIP_AUDIO, 2244)) if (player.properties.autocastSpell != null) { - val itemEquipmentSlot = item.definition.getConfiguration(ItemConfigParser.EQUIP_SLOT, -1) if (itemEquipmentSlot == EquipmentContainer.SLOT_WEAPON) { player.properties.autocastSpell = null diff --git a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt index 3220e5ea2..fe26b8b8f 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt @@ -1,12 +1,15 @@ package core.game.node.entity.player.info.login +import content.data.Quests import content.global.skill.summoning.pet.Pets +import content.region.kandarin.ardougne.quest.plaguecity.PlagueCity import core.ServerConstants import core.api.* import core.game.node.entity.player.Player import core.game.node.item.Item +import core.tools.Log import org.rs09.consts.Items -import content.data.Quests +import org.rs09.consts.Vars /** * Runs one-time save-version-related hooks. @@ -16,6 +19,7 @@ import content.data.Quests class SaveVersionHooks : LoginListener { override fun login(player: Player) { if (player.version < ServerConstants.CURRENT_SAVEFILE_VERSION) { + log(this::class.java, Log.FINE, "Upgrading ${player.name} from ${player.version} to ${ServerConstants.CURRENT_SAVEFILE_VERSION}") if (player.version < 1) { // GL !1811 // Give out crafting hoods if the player bought any crafting capes when the hoods were not obtainable @@ -69,6 +73,15 @@ class SaveVersionHooks : LoginListener { } } + if (player.version < 3) { + // Damage control on Plague city. There are a few varbits that should have been set for spawning + when (getQuestStage(player, Quests.PLAGUE_CITY)){ + in 6..98 -> setVarbit(player, Vars.VARBIT_QUEST_PLAGUE_CITY_EDMOND_TUNNELS, 1) // Edmond is in the tunnel + in 99..100 ->setVarbit(player, Vars.VARBIT_QUEST_PLAGUE_CITY_RESCUE_ELENA, 1) // Elena is free + } + } + + // Finish up player.version = ServerConstants.CURRENT_SAVEFILE_VERSION } } diff --git a/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java b/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java index 08adc715b..53dd6819e 100644 --- a/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java +++ b/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java @@ -202,7 +202,12 @@ public final class PacketDispatch { * @param childId The child id. */ public void sendPlayerOnInterface(int interfaceId, int childId) { - PacketRepository.send(DisplayModel.class, new DisplayModelContext(player, interfaceId, childId)); + // fixme right now for iface 68-71 the player is massive + // The zoom for the other windows is 2150 + // for these 4 individuals it should be 796 but dmc.setZoom doesn't work + DisplayModelContext dmc = new DisplayModelContext(player, interfaceId, childId); + dmc.setZoom(796); // this appears to do nothing + PacketRepository.send(DisplayModel.class, dmc); } /** diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 1c22818df..b959495bd 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -73,6 +73,16 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ AnmaCutscene(player).start() } + define("setsaveversion", Privilege.ADMIN) { player, args -> + try{ + player.version = args[1].toInt() + notify(player, "Setting save version to ${player.version}") + } + catch (nfe: NumberFormatException){ + reject(player, "Save versions can only be an integer") + } + } + /** * Prints player's current location */ From 2d1a626df0f1e9ea1c642eb52ed1a0b898e37650 Mon Sep 17 00:00:00 2001 From: Player Name Date: Sun, 16 Feb 2025 10:23:21 +0000 Subject: [PATCH 229/306] Zamorak robe top and bottom now count as Zamorak god items Zamorak robe top and bottom now allowed into Entrana Implemented the right-click take-boat options for the monks of Entrana Fixed some silly typos in the Monk-of-Entrana dialogue Removed unused god item definitions --- .../dialogue/MonkOfEntranaDialogue.java | 14 +++-- .../misc/entrana/handlers/EntranaListeners.kt | 56 +++++++++++++++++++ Server/src/main/core/api/ContentAPI.kt | 4 +- Server/src/main/core/api/God.kt | 10 +--- .../core/cache/def/impl/ItemDefinition.java | 4 +- 5 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 Server/src/main/content/region/misc/entrana/handlers/EntranaListeners.kt diff --git a/Server/src/main/content/region/asgarnia/portsarim/dialogue/MonkOfEntranaDialogue.java b/Server/src/main/content/region/asgarnia/portsarim/dialogue/MonkOfEntranaDialogue.java index 884ce1c00..e8c921159 100644 --- a/Server/src/main/content/region/asgarnia/portsarim/dialogue/MonkOfEntranaDialogue.java +++ b/Server/src/main/content/region/asgarnia/portsarim/dialogue/MonkOfEntranaDialogue.java @@ -41,6 +41,11 @@ public final class MonkOfEntranaDialogue extends DialoguePlugin { return new MonkOfEntranaDialogue(player); } + public void sail(Player player, Ships ship) { + ship.sail(player); + playJingle(player, 172); + } + @Override public boolean open(Object... args) { npc = (NPC) args[0]; @@ -98,7 +103,7 @@ public final class MonkOfEntranaDialogue extends DialoguePlugin { stage = 25; break; case 23: - interpreter.sendDialogues(npc, null, "Do not try and decieve us again. Come back when you", "have liad down your Zamorakian instruments of death."); + interpreter.sendDialogues(npc, null, "Do not try to deceive us again. Come back when you", "have laid down your Zamorakian instruments of death."); stage = 24; break; case 24: @@ -106,8 +111,7 @@ public final class MonkOfEntranaDialogue extends DialoguePlugin { break; case 25: end(); - Ships.PORT_SARIM_TO_ENTRANA.sail(player); - playJingle(player, 172); + sail(player, Ships.PORT_SARIM_TO_ENTRANA); if (!player.getAchievementDiaryManager().getDiary(DiaryType.FALADOR).isComplete(0, 14)) { player.getAchievementDiaryManager().getDiary(DiaryType.FALADOR).updateTask(player, 0, 14, true); } @@ -133,9 +137,7 @@ public final class MonkOfEntranaDialogue extends DialoguePlugin { stage = 511; break; case 511: - end(); - Ships.ENTRANA_TO_PORT_SARIM.sail(player); - playJingle(player, 172); + sail(player, Ships.ENTRANA_TO_PORT_SARIM); break; case 520: end(); diff --git a/Server/src/main/content/region/misc/entrana/handlers/EntranaListeners.kt b/Server/src/main/content/region/misc/entrana/handlers/EntranaListeners.kt new file mode 100644 index 000000000..105321131 --- /dev/null +++ b/Server/src/main/content/region/misc/entrana/handlers/EntranaListeners.kt @@ -0,0 +1,56 @@ +package content.region.misc.entrana.handlers + +import content.global.travel.ship.Ships +import core.api.* +import core.cache.def.impl.ItemDefinition +import core.game.dialogue.DialogueFile +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.diary.DiaryType +import core.tools.END_DIALOGUE +import org.rs09.consts.NPCs + +/** + * Listeners for the Entrana monks' fast-travel option + * @author Player Name + */ + +fun sail(player: Player?, ship: Ships) { + ship.sail(player) + playJingle(player!!, 172) +} + +class EntranaListeners : InteractionListener { + override fun defineListeners() { + for (npc in arrayOf(NPCs.MONK_OF_ENTRANA_2730, NPCs.MONK_OF_ENTRANA_658, NPCs.MONK_OF_ENTRANA_2731)) { + on(npc, IntType.NPC, "take-boat") { player, _ -> + sail(player, Ships.ENTRANA_TO_PORT_SARIM) + return@on true + } + } + + for (npc in arrayOf(NPCs.MONK_OF_ENTRANA_2728, NPCs.MONK_OF_ENTRANA_657, NPCs.MONK_OF_ENTRANA_2729)) { + on(npc, IntType.NPC, "take-boat") { player, _ -> + if (!ItemDefinition.canEnterEntrana(player)) { + openDialogue(player, object : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + this.npc = NPC(npc) + when (stage) { + 0 -> npc("NO WEAPONS OR ARMOUR are permitted on holy", "Entrana AT ALL. We will not allow you to travel there", "in breach of mighty Saradomin's edict.").also { stage++ } + 1 -> npc("Do not try to deceive us again. Come back when you", "have laid down your Zamorakian instruments of death.").also { stage = END_DIALOGUE } + } + } + }) + return@on true + } + sail(player, Ships.PORT_SARIM_TO_ENTRANA) + if (!player.achievementDiaryManager.getDiary(DiaryType.FALADOR).isComplete(0, 14)) { + player.achievementDiaryManager.getDiary(DiaryType.FALADOR).updateTask(player, 0, 14, true) + } + return@on true + } + } + } +} diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 8bb326fe5..0f1bae085 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -1731,7 +1731,7 @@ fun sendPlayerOnInterface(player: Player, iface: Int, child: Int) { } /** - * Sends a dialogue that uses the player's chathead. + * Sends a dialogue that uses the npc's chathead. * @param player the player to send the dialogue to * @param npc the ID of the NPC to use for the chathead * @param msg the message to send. @@ -1744,7 +1744,7 @@ fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: core.game.dialo } /** - * Sends a dialogue that uses the player's chathead. + * Sends a dialogue that uses the npc's chathead. * @param player the player to send the dialogue to * @param npc the ID of the NPC to use for the chathead * @param expr the FacialExpression to use. An enum exists for these called FacialExpression. diff --git a/Server/src/main/core/api/God.kt b/Server/src/main/core/api/God.kt index 58c880a97..c2e16c32d 100644 --- a/Server/src/main/core/api/God.kt +++ b/Server/src/main/core/api/God.kt @@ -88,6 +88,8 @@ enum class God(vararg val validItems: Int) { Items.ZAMORAK_STAFF_2417, Items.ZAMORAK_STOLE_10474, Items.ZAMORAK_SYMBOL_8056, + Items.ZAMORAK_ROBE_1033, + Items.ZAMORAK_ROBE_1035, ), GUTHIX( Items.STEEL_HERALDIC_HELM_8692, @@ -118,12 +120,6 @@ enum class God(vararg val validItems: Int) { Items.GUTHIX_ROBE_TOP_10788, Items.GUTHIX_STAFF_2416, Items.GUTHIX_STOLE_10472, - Items.GUTHIX_SYMBOL_8057 - ), - ZAROS( - Items.ANCIENT_STAFF_13406, - Items.ANCIENT_STAFF_4675, - Items.ANCIENT_MACE_11061, - Items.ANCIENT_BOOK_7633, + Items.GUTHIX_SYMBOL_8057, ) } diff --git a/Server/src/main/core/cache/def/impl/ItemDefinition.java b/Server/src/main/core/cache/def/impl/ItemDefinition.java index 88ba3712d..6935833f6 100644 --- a/Server/src/main/core/cache/def/impl/ItemDefinition.java +++ b/Server/src/main/core/cache/def/impl/ItemDefinition.java @@ -661,7 +661,9 @@ public class ItemDefinition extends Definition { Items.HAM_CLOAK_4304, Items.HAM_LOGO_4306, Items.GLOVES_4308, - Items.BOOTS_4310 + Items.BOOTS_4310, + Items.ZAMORAK_ROBE_1033, + Items.ZAMORAK_ROBE_1035 )); private static final HashSet entranaBannedItems = new HashSet(Arrays.asList( /**Items.BUTTERFLY_NET_10010, easing the restriction until barehanded implementation**/ From b6560c0e3f55c83f0d9ff2ab0034a1bd1f2ede6b Mon Sep 17 00:00:00 2001 From: GregF Date: Sun, 16 Feb 2025 10:42:27 +0000 Subject: [PATCH 230/306] Implemented Mogre miniquest --- Server/data/configs/drop_tables.json | 326 ++++++++---------- Server/data/configs/npc_configs.json | 26 ++ Server/data/configs/npc_spawns.json | 4 + .../handlers/scenery/FieldPickingPlugin.java | 2 +- .../skill/slayer/FishingExplosivePlugin.java | 228 ------------ .../content/global/skill/slayer/Master.java | 2 +- .../content/global/skill/slayer/MogreNPC.kt | 33 ++ .../falador/diary/FaladorAchievementDiary.kt | 3 + .../MudSkipperPointListeners.kt | 151 ++++++++ .../dialogue/SkippyDialogue.kt | 267 ++++++++++++++ 10 files changed, 629 insertions(+), 413 deletions(-) delete mode 100644 Server/src/main/content/global/skill/slayer/FishingExplosivePlugin.java create mode 100644 Server/src/main/content/global/skill/slayer/MogreNPC.kt create mode 100644 Server/src/main/content/region/asgarnia/mudskipperpoint/MudSkipperPointListeners.kt create mode 100644 Server/src/main/content/region/asgarnia/mudskipperpoint/dialogue/SkippyDialogue.kt diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index c0f25df89..00bceefe8 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -5858,205 +5858,165 @@ "charm": [ { "minAmount": "1", - "weight": "100.0", - "id": "12158", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "12159", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "12160", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "12163", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5600.0", + "weight": "1000.0", "id": "0", "maxAmount": "1" } ], + "tertiary": [ + { + "minAmount": "1", + "weight": "4986.5", + "id": "0", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "12.5", + "id": "10976", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "1.0", + "id": "10977", + "maxAmount": "1" + } + ], "ids": "114", "description": "", "main": [ { "minAmount": "1", - "weight": "50.0", - "id": "7844", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "10977", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "10976", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5323", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5298", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5281", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5301", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5280", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5294", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5297", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5104", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5100", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5106", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "12176", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5293", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5296", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5311", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5105", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "25.0", - "id": "5292", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "5295", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "5303", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "5302", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "5321", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "5299", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "5.0", - "id": "31", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "100.0", - "id": "0", - "maxAmount": "1" - }, - { - "minAmount": "1", - "weight": "3.0", + "weight": "39.0625", "id": "6666", "maxAmount": "1" }, { "minAmount": "1", - "weight": "3.0", + "weight": "78.125", "id": "6665", "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "13.0", + "id": "14422", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "13.0", + "id": "14430", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "345", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "327", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "371", + "maxAmount": "1" + }, + { + "minAmount": "2", + "weight": "156.25", + "id": "372", + "maxAmount": "5" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "359", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "360", + "maxAmount": "3" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "383", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "349", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "331", + "maxAmount": "1" + }, + { + "minAmount": "5", + "weight": "156.25", + "id": "313", + "maxAmount": "15" + }, + { + "minAmount": "1", + "weight": "156.25", + "id": "1511", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "1383", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "78.125", + "id": "407", + "maxAmount": "1" + }, + { + "minAmount": "4", + "weight": "78.125", + "id": "402", + "maxAmount": "8" + }, + { + "minAmount": "5", + "weight": "4.0", + "id": "555", + "maxAmount": "18" + }, + { + "minAmount": "3", + "weight": "78.125", + "id": "6664", + "maxAmount": "6" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "401", + "maxAmount": "1" + }, + { + "minAmount": "1", + "weight": "39.0625", + "id": "6667", + "maxAmount": "1" } ] }, diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 5e11828b8..71d194eab 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -72145,6 +72145,7 @@ { "examine": "A sea bird.", "name": "Gull", + "water_npc": "true", "id": "2726" }, { @@ -87866,5 +87867,30 @@ "name": "Elena", "id": "335", "examine": "She doesn't look too happy." + }, + { + "examine": "Use 1344 to change me", + "name": "Skippy Varbit", + "id": "2795" + }, + { + "examine": "He looks angry and smells drunk.", + "name": "Skippy", + "id": "2796" + }, + { + "name": "Skippy", + "id": "2797", + "examine": "Skippy, just looking a little 'tender'." + }, + { + "name": "Skippy", + "id": "2798", + "examine": "He seems a lot less angry and smells a great deal fresher." + }, + { + "name": "Skippy", + "id": "2799", + "examine": "He seems a bit confused." } ] \ No newline at end of file diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index e2534a0b6..8899eea83 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -6255,6 +6255,10 @@ "npc_id": "2794", "loc_data": "{2606,3100,0,0,0}-" }, + { + "npc_id": "2795", + "loc_data": "{2979,3197,0,1,0}-" + }, { "npc_id": "2796", "loc_data": "{3096,3108,0,0,6}-" diff --git a/Server/src/main/content/global/handlers/scenery/FieldPickingPlugin.java b/Server/src/main/content/global/handlers/scenery/FieldPickingPlugin.java index 307c09b20..1d0fa5c07 100644 --- a/Server/src/main/content/global/handlers/scenery/FieldPickingPlugin.java +++ b/Server/src/main/content/global/handlers/scenery/FieldPickingPlugin.java @@ -72,7 +72,7 @@ public final class FieldPickingPlugin extends OptionHandler { player.dispatch(new ResourceProducedEvent(reward.getId(), reward.getAmount(), node, -1)); if (plant.name().startsWith("NETTLES") && (player.getEquipment().get(EquipmentContainer.SLOT_HANDS) == null || player.getEquipment().get(EquipmentContainer.SLOT_HANDS) != null && !player.getEquipment().get(EquipmentContainer.SLOT_HANDS).getName().contains("glove"))) { player.getPacketDispatch().sendMessage("You have been stung by the nettles!"); - player.getImpactHandler().manualHit(player, 2, HitsplatType.POISON); + player.getImpactHandler().manualHit(player, 6, HitsplatType.POISON); return true; } if (plant.respawn != -1 && plant != PickingPlant.FLAX) { diff --git a/Server/src/main/content/global/skill/slayer/FishingExplosivePlugin.java b/Server/src/main/content/global/skill/slayer/FishingExplosivePlugin.java deleted file mode 100644 index 196a4c62d..000000000 --- a/Server/src/main/content/global/skill/slayer/FishingExplosivePlugin.java +++ /dev/null @@ -1,228 +0,0 @@ -package content.global.skill.slayer; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.NodeUsageEvent; -import core.game.interaction.OptionHandler; -import core.game.interaction.UseWithHandler; -import core.game.node.Node; -import core.game.node.entity.Entity; -import core.game.node.entity.combat.CombatStyle; -import core.game.node.entity.combat.ImpactHandler.HitsplatType; -import core.game.node.entity.impl.Projectile; -import core.game.node.entity.npc.AbstractNPC; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.HintIconManager; -import core.game.node.entity.player.link.diary.DiaryType; -import core.game.node.item.Item; -import core.game.node.scenery.Scenery; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; -import core.game.world.map.Direction; -import core.game.world.map.Location; -import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; -import core.plugin.Initializable; -import core.plugin.Plugin; -import core.tools.RandomFunction; - -/** - * Represents the plugin used to handle the fishing expolosive on a omnious - * fishing spot. - * @author 'Vexia - */ -@Initializable -public final class FishingExplosivePlugin extends OptionHandler { - - /** - * Represents the ominous fishing spot ids. - */ - private final static int[] IDS = new int[] { 10087, 10088, 10089 }; - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (int id : IDS) { - SceneryDefinition.forId(id).getHandlers().put("option:lure", this); - SceneryDefinition.forId(id).getHandlers().put("option:bait", this); - } - new FishingExplosiveHandler().newInstance(arg); - new MogreNPC().newInstance(arg); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - player.getPacketDispatch().sendMessage("Something seems to have scared all the fishes away..."); - return true; - } - - @Override - public Location getDestination(Node node, Node n) { - return node.getLocation(); - } - - /** - * Represents the handler for the fishing expolsive on a fishing spot. - * @author 'Vexia - * @version 1.0 - */ - public static final class FishingExplosiveHandler extends UseWithHandler { - - /** - * Represents the throwing animation. - */ - private static final Animation ANIMATION = new Animation(385); - - /** - * Represents the splashing graphics. - */ - private static final Graphics SPLASH_GRAPHIC = new Graphics(68); - - /** - * Represents the npc mogre id. - */ - private static final int MOGRE_ID = 114; - - /** - * Represents the messages used to send for the mogres. - */ - private static final String[] MESSAGES = new String[] { "Da boom-boom kill all da fishies!", "I smack you good!", "Smash stupid human!", "Tasty human!", "Human hit me on the head!", "I get you!", "Human scare all da fishies!" }; - - /** - * Constructs a new {@code FishingExplosiveHandler} {@code Object}. - */ - public FishingExplosiveHandler() { - super(6664, 12633); - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (int i : IDS) { - addHandler(i, OBJECT_TYPE, this); - } - return this; - } - - @Override - public boolean handle(final NodeUsageEvent event) { - final Player player = event.getPlayer(); - if (player.getAttributes().containsKey("hasMogre")) { - player.getDialogueInterpreter().sendDialogues(player, null, "Sinister as that fishing spot is, why would I want to", "explode it?"); - return true; - } - if (!player.getInventory().remove(new Item(event.getUsedItem().getId(), 1))) { - return true; - } - final int delay = (int) (2 + (player.getLocation().getDistance(event.getUsedWith().getLocation())) * 0.5); - player.animate(ANIMATION); - player.getPacketDispatch().sendMessage("You hurl the shuddering vial into the water..."); - sendProjectile(player, (Scenery) event.getUsedWith()); - GameWorld.getPulser().submit(new Pulse(delay, player) { - @Override - public boolean pulse() { - Direction dir = event.getUsedWith().getDirection(); - NPC mogre = NPC.create(MOGRE_ID, event.getUsedWith().getLocation().transform(dir.getStepX() << 1, dir.getStepY() << 1, 0)); - mogre.init(); - mogre.moveStep(); - mogre.setRespawn(false); - mogre.getProperties().getCombatPulse().attack(player); - mogre.setAttribute("player", player); - mogre.sendChat(MESSAGES[RandomFunction.random(MESSAGES.length)]); - HintIconManager.registerHintIcon(player, mogre); - if (event.getUsedItem().getId() == 12633) { - mogre.getImpactHandler().manualHit(player, 15, HitsplatType.NORMAL); - } - player.setAttribute("hasMogre", true); - mogre.graphics(SPLASH_GRAPHIC); - player.getPacketDispatch().sendMessage("...and a Mogre appears!"); - return true; - } - }); - return true; - } - - /** - * Method used to send the fishign explosive projectile. - * @param player the player. - * @param object the object. - */ - private void sendProjectile(final Player player, final Scenery object) { - Projectile p = Projectile.create(player, null, 49, 30, 20, 30, Projectile.getSpeed(player, object.getLocation())); - p.setEndLocation(object.getLocation()); - p.send(); - } - - @Override - public Location getDestination(Player player, Node with) { - return player.getLocation(); - } - } - - /** - * Represents a mogre npc. - * @author 'Vexia - * @version 1.0 - */ - public final class MogreNPC extends AbstractNPC { - - /** - * Constructs a new {@code MogreNPC} {@code Object}. - * @param id the id. - * @param location the location. - */ - public MogreNPC(int id, Location location) { - super(id, location, true); - } - - /** - * Constructs a new {@code MogreNPC} {@code Object}. - */ - public MogreNPC() { - super(0, null); - } - - @Override - public void tick() { - super.tick(); - final Player pl = getAttribute("player", null); - if (pl == null || pl.getLocation().getDistance(getLocation()) > 15) { - clear(); - } - } - - @Override - public void clear() { - super.clear(); - final Player pl = getAttribute("player", null); - if (pl != null) { - pl.removeAttribute("hasMogre"); - } - } - - @Override - public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { - final Player pl = getAttribute("player", null); - return pl != null && pl == entity && super.isAttackable(entity, style, message); - } - - @Override - public void finalizeDeath(final Entity killer) { - super.finalizeDeath(killer); - if (killer instanceof Player) { - final Player player = killer.asPlayer(); - player.getAchievementDiaryManager().finishTask(player,DiaryType.FALADOR, 2, 7); - } - } - - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new MogreNPC(id, location); - } - - @Override - public int[] getIds() { - return new int[] { 114 }; - } - - } -} diff --git a/Server/src/main/content/global/skill/slayer/Master.java b/Server/src/main/content/global/skill/slayer/Master.java index ad728467c..aad0fa5e4 100644 --- a/Server/src/main/content/global/skill/slayer/Master.java +++ b/Server/src/main/content/global/skill/slayer/Master.java @@ -106,7 +106,7 @@ public enum Master { // new Task(Tasks.KILLERWATTS,6), new Task(Tasks.KURASKS,7), new Task(Tasks.LESSER_DEMONS,7), - //new Task(Tasks.MOGRES,7), + new Task(Tasks.MOGRES,7), // new Task(Tasks.MOLANISKS,7), new Task(Tasks.MOSS_GIANTS,7), new Task(Tasks.OGRES,7), diff --git a/Server/src/main/content/global/skill/slayer/MogreNPC.kt b/Server/src/main/content/global/skill/slayer/MogreNPC.kt new file mode 100644 index 000000000..c1f5fce49 --- /dev/null +++ b/Server/src/main/content/global/skill/slayer/MogreNPC.kt @@ -0,0 +1,33 @@ +package content.global.skill.slayer + +import core.game.node.entity.Entity +import core.game.node.entity.npc.AbstractNPC +import core.game.world.map.Location +import org.rs09.consts.NPCs + +/** + * Represents a mogre npc. + * @author 'Vexia + * @author gregf36665 + * @version 2.0 + */ +class MogreNPC : AbstractNPC(NPCs.MOGRE_114, null) { + + override fun tick() { + super.tick() + val victim = properties.combatPulse.getVictim() + if (victim != null) { + if (victim.location.getDistance(getLocation()) > 15) { + clear() + } + } + } + + override fun construct(id: Int, location: Location?, vararg objects: Any?): AbstractNPC { + return MogreNPC() + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.MOGRE_114) + } +} diff --git a/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt b/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt index 7d9d2f483..4831afd9c 100644 --- a/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt +++ b/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt @@ -212,6 +212,9 @@ class FaladorAchievementDiary : DiaryEventHookBase(DiaryType.FALADOR) { ) } } + if (event.npc.id == NPCs.MOGRE_114){ + finishTask(player, DiaryLevel.HARD, HardTasks.MUDSKIPPER_POINT_KILL_MOGRE) + } } override fun onItemPurchasedFromShop(player: Player, event: ItemShopPurchaseEvent) { diff --git a/Server/src/main/content/region/asgarnia/mudskipperpoint/MudSkipperPointListeners.kt b/Server/src/main/content/region/asgarnia/mudskipperpoint/MudSkipperPointListeners.kt new file mode 100644 index 000000000..eed56b4bf --- /dev/null +++ b/Server/src/main/content/region/asgarnia/mudskipperpoint/MudSkipperPointListeners.kt @@ -0,0 +1,151 @@ +package content.region.asgarnia.mudskipperpoint + +import content.global.skill.slayer.MogreNPC +import content.region.asgarnia.mudskipperpoint.dialogue.SkippyBootDialogue +import content.region.asgarnia.mudskipperpoint.dialogue.SkippyBucketDialogue +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.impl.Projectile +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.plugin.Initializable +import core.tools.RandomFunction +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery +import org.rs09.consts.Vars + +@Initializable +class MudSkipperPointListeners : InteractionListener { + + companion object { + private val MESSAGES = arrayOf( + "Da boom-boom kill all da fishies!", + "I smack you good!", + "Smash stupid human!", + "Tasty human!", + "Human hit me on the head!", + "I get you!", + "Human scare all da fishies!" + ) + + private val FISHING_SPOTS = intArrayOf( + Scenery.OMINOUS_FISHING_SPOT_10087, + Scenery.OMINOUS_FISHING_SPOT_10088, + Scenery.OMINOUS_FISHING_SPOT_10089 + ) + } + + private fun handleExplosives(player: Player, explosives: Item, target: Location): Boolean{ + // Check if the player has unlocked the ability to summon Mogres + if (getVarbit(player, Vars.VARBIT_MINI_QUEST_MOGRE) != SkippyBucketDialogue.DONE_QUEST){ + sendDialogueLines(player, "Sinister as that fishing spot is, why would I want to", "explode it?") + return false + } + val distance = player.location.getDistance(target) + if (distance < 5){ + //too close + sendPlayerDialogue(player, "If this thing explodes, I think I should stand a liiiiitle further away.") + return false + } + if (distance > 14){ + // too far + sendPlayerDialogue(player, "I can't throw that far.") + return false + } + removeItem(player, explosives.id) + animate(player, Animation(385)) // Throw the vial + sendMessage(player, "You hurl the shuddering vial into the water...") + val projectile = Projectile.create(player, null, 49, 30, 20, 30, Projectile.getSpeed(player, target.location)) + projectile.endLocation = target.location + projectile.send() + + val delay = (2+ distance * 0.5).toInt() + queueScript(player, delay){ + val mogre = MogreNPC() + val xOffset = (player.location.x - target.location.x) % 2 + val yOffset = (player.location.y - target.location.y) % 2 + mogre.location = Location.create(target.location.x + xOffset, target.location.y + yOffset) + mogre.init() + mogre.moveStep() + mogre.isRespawn = false + mogre.attack(player) + registerHintIcon(player, mogre) + mogre.sendChat(MESSAGES[RandomFunction.random(MESSAGES.size)]) + if (explosives.id == Items.SUPER_FISHING_EXPLOSIVE_12633){ + impact(mogre, 15) + } + mogre.graphics(Graphics(68)) + sendMessage(player, "...and a Mogre appears!") + return@queueScript stopExecuting(player) + } + return true + } + + private fun soberSkippy(player: Player): Boolean { + if (getVarbit(player, Vars.VARBIT_MINI_QUEST_MOGRE) > SkippyBucketDialogue.DRUNK){ + sendDialogue(player, "I think he's sober enough. And I don't want to use another bucket of water.") + return false + } + else{ + if (hasAnItem(player, Items.BUCKET_OF_WATER_1929).exists()) { + openDialogue(player, SkippyBucketDialogue()) + return true + } + else{ + sendDialogue(player, "You know, I could shock him out of it if I could find some cold water...") + return false + } + } + } + + override fun defineListeners() { + + onUseWith(IntType.SCENERY, Items.FISHING_EXPLOSIVE_6664, *FISHING_SPOTS) { player, used, with -> + handleExplosives(player, used.asItem(), with.location) + } + + onUseWith(IntType.SCENERY, Items.SUPER_FISHING_EXPLOSIVE_12633, *FISHING_SPOTS) { player, used, with -> + handleExplosives(player, used.asItem(), with.location) + } + + on(FISHING_SPOTS, IntType.SCENERY, "Lure", "Bait") { player, _ -> + sendMessage(player, "Something seems to have scared all the fishes away...") + return@on true + } + + on(Scenery.SIGNPOST_10090, IntType.SCENERY, "read") { player, _ -> + setInterfaceText(player, "Mudskipper Point.", 220, 2) + setInterfaceText(player, "WARNING! BEWARE OF THE MUDSKIPPERS!", 220, 4) + openInterface(player, 220) + return@on true + } + + // For some reason the 2795 wrapper does not work for sober-up + on(intArrayOf(NPCs.SKIPPY_2796, NPCs.SKIPPY_2797, NPCs.SKIPPY_2798, NPCs.SKIPPY_2799), + IntType.NPC, "sober-up") { player, _ -> + return@on soberSkippy(player) + } + + onUseWith(IntType.NPC, Items.BUCKET_OF_WATER_1929, NPCs.SKIPPY_2795) { player, _, _ -> + return@onUseWith soberSkippy(player) + } + + onUseWith(IntType.NPC, Items.FORLORN_BOOT_6663, NPCs.SKIPPY_2795){ player, _, _ -> + openDialogue(player, SkippyBootDialogue()) + return@onUseWith true + } + } + + override fun defineDestinationOverrides() { + + // Don't run towards the fishing spots when trying to lure or bait or throw explosives + setDest(IntType.SCENERY, FISHING_SPOTS, "Lure", "Bait", "use"){ entity, _ -> + return@setDest entity.location + } + } +} diff --git a/Server/src/main/content/region/asgarnia/mudskipperpoint/dialogue/SkippyDialogue.kt b/Server/src/main/content/region/asgarnia/mudskipperpoint/dialogue/SkippyDialogue.kt new file mode 100644 index 000000000..2106d6856 --- /dev/null +++ b/Server/src/main/content/region/asgarnia/mudskipperpoint/dialogue/SkippyDialogue.kt @@ -0,0 +1,267 @@ +package content.region.asgarnia.mudskipperpoint.dialogue + +import content.data.Quests +import core.api.* +import core.game.dialogue.DialogueFile +import core.game.dialogue.DialoguePlugin +import core.game.dialogue.FacialExpression +import core.game.dialogue.Topic +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import core.tools.RandomFunction +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Vars + + +@Initializable +class SkippyDialogue(player: Player? = null) : DialoguePlugin(player) { + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, SkippyBucketDialogue(0, getVarbit(player, Vars.VARBIT_MINI_QUEST_MOGRE))) + return true + } + + + override fun getIds(): IntArray { + return intArrayOf(NPCs.SKIPPY_2795) + } + +} + + +class SkippyBucketDialogue(override var stage: Int = 0, val questStage: Int = 0) : DialogueFile() { + + companion object{ + // Skippy will progress through these stages as you help him + const val DRUNK = 0 + const val TENDER = 1 + const val HUNGOVER = 2 + const val DONE_QUEST = 3 + + // Dialogue branches + const val THROW_WATER = 10 + const val DRUNK_RAMBLING = 30 + const val CRAZY_PEOPLE = 40 + const val WHO_ARE_THEY = 50 + // Tea state + const val LEARN_RECIPE = 170 + const val PLAGUE_CITY_RECIPE = 180 + const val NO_TEA = 190 + // Hangover cure state + const val CURE = 220 + const val NO_CURE = 250 + const val RECIPE = 260 + const val NAME_ORIGIN = 270 + + const val ALL_DONE = 300 + } + + override fun handle(componentID: Int, buttonID: Int) { + npc = NPC(NPCs.SKIPPY_2796) + when (questStage){ + DRUNK -> when (stage) { + 0 -> if(hasAnItem(player!!, Items.BUCKET_OF_WATER_1929).exists()){ + playerl(FacialExpression.THINKING, "Well, I could dump this bucket of water over him. That would sober him up a little.").also { stage = THROW_WATER } + } + else { + playerl(FacialExpression.ASKING, "Are you all right? You seem a little...incoherent.").also { stage = DRUNK_RAMBLING } + } + THROW_WATER -> showTopics( + Topic("Throw the water!", THROW_WATER+ 1, true), + Topic("I think I'll leave it for now.", END_DIALOGUE) + ) + THROW_WATER + 1 -> playerl(FacialExpression.NEUTRAL, "Hey, Skippy!").also { stage++ } + THROW_WATER + 2 -> npcl(FacialExpression.DRUNK, "What?").also { + stage = END_DIALOGUE + queueScript(player!!, 1){ animationStage : Int -> + when(animationStage){ + 1 -> { + // todo get the right animation + animate(player!!, 2283) + removeItem(player!!, Items.BUCKET_OF_WATER_1929) + addItem(player!!, Items.BUCKET_1925) + setVarbit(player!!, Vars.VARBIT_MINI_QUEST_MOGRE, TENDER, true) + return@queueScript delayScript(player!!, 1) + } + 2 -> { + openDialogue(player!!, SkippyBucketDialogue(THROW_WATER + 4)) + return@queueScript delayScript(player!!, 1) + } + 3 -> return@queueScript stopExecuting(player!!) + else -> return@queueScript delayScript(player!!, 1) + } + } } + THROW_WATER + 4 -> npcl(FacialExpression.ANGRY, "Ahhhhhhhhhhgh! That's cold! Are you trying to kill me?").also { stage++ } + THROW_WATER + 5 -> playerl(FacialExpression.NEUTRAL, "Nope. Just sober you up. Memory coming back yet?").also { stage++ } + THROW_WATER + 6 -> npcl(FacialExpression.ANGRY, "No. But I could do with a bowl of tea to warm myself up a bit. Go grab me one and we'll talk.").also { stage++ } + THROW_WATER + 7 -> playerl(FacialExpression.ASKING, "Any particular type of tea?").also { stage++ } + THROW_WATER + 8 -> npcl(FacialExpression.ANGRY, "Nettle for preference. Just make sure it's hot.").also { stage++ } + THROW_WATER + 9 -> npcl(FacialExpression.ANGRY, "And don't throw it at me!").also { stage++ } + THROW_WATER + 10 -> playerl(FacialExpression.HALF_GUILTY, "What's your problem? You're all clean now.").also { stage = END_DIALOGUE } + + + DRUNK_RAMBLING -> npcl(FacialExpression.DRUNK, "Inc'hearnt? Inc'herant! You...you...with yer fancy book- lernin' words. You'd be more than inc'herant if youd seen...").also { stage++ } + DRUNK_RAMBLING + 1 -> npcl(FacialExpression.DRUNK, "(Dramatic pause)").also { stage++ } + DRUNK_RAMBLING + 2 -> npcl(FacialExpression.DRUNK, "THEM!").also { stage++ } + DRUNK_RAMBLING + 3 -> showTopics( + Topic("I'm sure I would as well.", CRAZY_PEOPLE), + Topic("Who are (Dramatic pause) THEY?", WHO_ARE_THEY, true) + ) + + CRAZY_PEOPLE -> playerl(FacialExpression.NEUTRAL, "I'm going over here to talk to non-crazy people now.").also { stage++ } + CRAZY_PEOPLE + 1 -> npcl(FacialExpression.DRUNK, "Yeah? Yeah? Well when THEY come floppin' into your house and eat your furniture you'll be sorry!").also { stage = END_DIALOGUE } + + WHO_ARE_THEY -> playerl(FacialExpression.NEUTRAL, "Who are").also { stage++ } + WHO_ARE_THEY + 1 -> playerl(FacialExpression.NEUTRAL, "(Dramatic pause)").also { stage++ } + WHO_ARE_THEY + 2 -> playerl(FacialExpression.NEUTRAL, "THEY?").also { stage++ } + WHO_ARE_THEY + 3 -> npcl(FacialExpression.DRUNK, "They! Those bloodthirsty, flesh-tearing devils! They are the reason I'm out here every day hurlin' bottles into the sea!").also { stage++ } + WHO_ARE_THEY + 4 -> npcl(FacialExpression.DRUNK, "They are the reason I've lost everything, except the horrifying memory of what THEY look like...").also { stage++ } + WHO_ARE_THEY + 5 -> playerl(FacialExpression.ASKING, "And what do THEY look like?").also { stage++ } + WHO_ARE_THEY + 6 -> npcl(FacialExpression.DRUNK, "Mudskippers!").also { stage++ } + WHO_ARE_THEY + 7 -> playerl(FacialExpression.ASKING, "Mudskippers?").also { stage++ } + WHO_ARE_THEY + 8 -> npcl(FacialExpression.DRUNK, "Aye, Mudskippers! Those ferocious, ravening, evil, beady-eyed terrors of the deep!").also { stage++ } + WHO_ARE_THEY + 9 -> playerl(FacialExpression.SUSPICIOUS, "I...see...").also{ stage++ } + WHO_ARE_THEY + 10 -> npcl(FacialExpression.DRUNK, " I was ambushed by them way back, see. They got the drop on me...I can't remember where, somewhere around here though.").also { stage++ } + WHO_ARE_THEY + 11 -> playerl(FacialExpression.ASKING, "These would be the mudskippers, right?").also{ stage++ } + WHO_ARE_THEY + 12 -> npcl(FacialExpression.DRUNK, "Aye! The mudskippers! Huge they were! Ten feet of glistening, muddy flesh floppin' towards me with white foam flying from their gnashing fangs!").also { stage++ } + WHO_ARE_THEY + 13 -> npcl(FacialExpression.DRUNK, "I fought them up and down the beach, with the tide rising and more of them leaping towards me with cutlasses drawn!").also { stage++ } + WHO_ARE_THEY + 14 -> playerl(FacialExpression.HALF_GUILTY, "This is fascinating, but I have to be...").also{ stage++ } + WHO_ARE_THEY + 15 -> npcl(FacialExpression.DRUNK, "Shut yer' word-hole and listen! I can't remember all the details, as I'm sure they must have hit me quite hard, but the last thing I remember before it all went black...").also { stage++ } + WHO_ARE_THEY + 16 -> npcl(FacialExpression.DRUNK, "...was one of those devils rearing over me, its eyes glowin' red with the fires of hell!").also { stage++ } + WHO_ARE_THEY + 17 -> playerl(FacialExpression.ROLLING_EYES, "Fires of hell...right. I believe you.").also { stage++ } + WHO_ARE_THEY + 18 -> npcl(FacialExpression.DRUNK, "No you don't! You think I'm crazy, like all the rest! Well, if I'm crazy, how did I get these?").also { stage++ } + WHO_ARE_THEY + 19 -> playerl(FacialExpression.ASKING, "Get what?").also { stage++ } + WHO_ARE_THEY + 20 -> sendDialogue(player!!, "Skippy shows you what appears to be massive bite scars on his legs. You're no expert, but they look like... giant mudskipper bites!").also { stage++ } + WHO_ARE_THEY + 21 -> playerl(FacialExpression.ASKING, "Giant mudskipper bites! Where did you get those?").also { stage++ } + WHO_ARE_THEY + 22 -> npcl(FacialExpression.DRUNK, "I can't remember... I've been drinking to forget the horror, and all I seem to have forgotten is where it all happened...").also { stage++ } + WHO_ARE_THEY + 23 -> playerl(FacialExpression.THINKING, "Hmmm...I suppose if I sober you up you may well start to recall.").also{ stage++ } + WHO_ARE_THEY + 24 -> npcl(FacialExpression.DRUNK, "You'll have a job. I've been drinking this for a week.").also { stage++ } + WHO_ARE_THEY + 25 -> playerl(FacialExpression.ASKING, "'Captain Braindeath's Extra Strength Rum/Drain Cleaner. Now 50% more debilitating'?").also { stage++ } + WHO_ARE_THEY + 26 -> npcl(FacialExpression.DRUNK, "It's the extra sheep tranquilizers that gives it that added kick!").also { stage++ } + WHO_ARE_THEY + 27 -> playerl(FacialExpression.NEUTRAL, "Stay here and I'll be right back. Try not to move. Or go near any open flames.").also { stage = END_DIALOGUE } + } + + TENDER -> when(stage){ + 0 -> playerl(FacialExpression.HAPPY, "Hey, Skippy!").also { stage++ } + 1 -> npcl(FacialExpression.PANICKED, "Gaah! Don't drench me again!").also { stage++ } + 2 -> playerl(FacialExpression.HALF_GUILTY, "Hey! I only did that once! Try not to be such a big baby!").also { stage++ } + 3 -> npcl(FacialExpression.HALF_THINKING, "So what are you here for then?").also { stage = if (hasAnItem(player!!, Items.NETTLE_TEA_4239).exists()) 4 else NO_TEA } + 4 -> playerl(FacialExpression.HAPPY, "I've come to give you your tea.").also { stage++ } + 5 -> npcl(FacialExpression.HAPPY, "Excellent! I was thinking I was going to freeze out here!").also { stage++ } + 6 -> sendItemDialogue(player!!, Items.NETTLE_TEA_4239, "Skippy drinks the tea and clutches his forehead in pain.").also { + stage++ + removeItem(player!!, Items.NETTLE_TEA_4239) + setVarbit(player!!, Vars.VARBIT_MINI_QUEST_MOGRE, HUNGOVER, true) + } + 7 -> npcl(FacialExpression.ANNOYED, "Ohhhhh...").also { stage++ } + 8 -> playerl(FacialExpression.ASKING, "What? What's wrong?").also { stage++ } + 9 -> npcl(FacialExpression.ANNOYED, "Not so loud...I think I have a hangover...").also { stage++ } + 10 -> playerl(FacialExpression.HALF_WORRIED, "Great...Well, I doubt you can remember anything through a hangover. What a waste of nettle tea...").also { stage++ } + 11 -> npcl(FacialExpression.FURIOUS, "Hey! A little sympathy here?").also { stage++ } + 12 -> npcl(FacialExpression.ANNOYED, "Owwowwoww... must remember not to shout...").also { stage++ } + 13 -> npcl(FacialExpression.ASKING, "Look, I do know a hangover cure. If you can get me a bucket of the stuff I think I'll be okay.").also { stage = if(getQuestStage(player!!, Quests.PLAGUE_CITY) >= 14 ) PLAGUE_CITY_RECIPE else LEARN_RECIPE } + + PLAGUE_CITY_RECIPE -> playerl(FacialExpression.HALF_THINKING, "Wait... is this cure a bucket of chocolate milk and snape grass?").also { stage++ } + PLAGUE_CITY_RECIPE + 1 -> npcl(FacialExpression.HAPPY, "Yes! That's the stuff!").also { stage++ } + PLAGUE_CITY_RECIPE + 2 -> playerl(FacialExpression.HALF_THINKING, "Ahhh. Yes, I've made some of that stuff before. I should be able to get you some, no problem.").also { stage = END_DIALOGUE } + + LEARN_RECIPE -> playerl(FacialExpression.ASKING, "So what is it you need?").also { stage++ } + LEARN_RECIPE + 1 -> npcl(FacialExpression.NEUTRAL, "A bucket of milk with chocolate ground into it, with a handful of snape grass thrown in on top.").also { stage++ } + LEARN_RECIPE + 2 -> playerl(FacialExpression.ASKING, "What? Run that past me again?").also { stage ++ } + LEARN_RECIPE + 3 -> npcl(FacialExpression.NEUTRAL, "Take a bucket of milk, a bar of chocolate and some snape grass.").also { stage++ } + LEARN_RECIPE + 4 -> npcl(FacialExpression.NEUTRAL, "Grind the chocolate with a mortar and pestle.").also { stage++ } + LEARN_RECIPE + 5 -> npcl(FacialExpression.NEUTRAL, "Add the chocolate powder to the milk, then add the snape grass.").also { stage++ } + LEARN_RECIPE + 6 -> npcl(FacialExpression.NEUTRAL, "Then bring it here and I will drink it.").also { stage++ } + LEARN_RECIPE + 7 -> npcl(FacialExpression.NEUTRAL, "The end, and we all live happily ever after. Got it?").also { stage = END_DIALOGUE } + + NO_TEA -> playerl(FacialExpression.HALF_GUILTY, "No real reason. I just thought I would check up on you is all.").also { stage++ } + NO_TEA + 1 -> npcl(FacialExpression.ANGRY, "Well, I'm still wet, still cold and still waiting on that nettle tea.").also { stage = END_DIALOGUE } + } + HUNGOVER -> when(stage){ + 0 -> playerl(FacialExpression.HAPPY, "Hey, Skippy!").also{ stage++ } + 1 -> npcl(FacialExpression.ANNOYED, "Egad! Don't you know not to shout around a guy with a hangover?").also { stage++ } + 2 -> npcl(FacialExpression.HALF_GUILTY, "Ahhhhhg...No more shouting for me...").also { stage++ } + 3 -> npcl(FacialExpression.ASKING, "What is it anyway?").also { stage = if (hasAnItem(player!!, Items.HANGOVER_CURE_1504).exists()) CURE else NO_CURE } + + CURE -> playerl(FacialExpression.HAPPY, "Well Skippy, you will no doubt be glad to hear that I got you your hangover cure!").also { stage++ } + CURE + 1 ->npcl(FacialExpression.HAPPY, "Gimme!").also { stage++ } + CURE + 2 -> sendDialogue(player!!, "Skippy chugs the hangover cure... very impressive.").also { + removeItem(player!!, Items.HANGOVER_CURE_1504) + stage++ + setVarbit(player!!, 1344, DONE_QUEST, true) + } + CURE + 3 -> npcl(FacialExpression.HAPPY, "Ahhhhhhhhhhhhhhh...").also { stage ++ } + CURE + 4 -> npcl(FacialExpression.HAPPY, "Much better...").also { stage ++ } + CURE + 5 -> playerl(FacialExpression.ASKING, "Feeling better?").also { stage ++ } + CURE + 6 -> npcl(FacialExpression.HAPPY, "Considerably.").also { stage ++ } + CURE + 7 -> playerl(FacialExpression.ASKING, "Then tell me where the mudskippers are!").also { stage++ } + CURE + 8 -> npcl(FacialExpression.NEUTRAL, "I wish you wouldn't go looking for them. Those vicious killers will tear you apart.").also { stage ++ } + CURE + 9 -> npcl(FacialExpression.HALF_THINKING, "It's all becoming clear to me now...").also { stage ++ } + CURE + 10 -> npcl(FacialExpression.HAPPY, "I was fishing using a Fishing Explosive...").also { stage ++ } + CURE + 11 -> playerl(FacialExpression.ASKING, "A Fishing Explosive?").also { stage++ } + CURE + 12 -> npcl(FacialExpression.NEUTRAL, "Well, Slayer Masters sell these highly volatile potions for killing underwater creatures.").also { stage ++ } + CURE + 13 -> npcl(FacialExpression.NEUTRAL, "If you don't feel like lobbing a net about all day you can use them to fish with...").also { stage ++ } + CURE + 14 -> npcl(FacialExpression.NEUTRAL, "But this time I was startled by what I thought was a giant mudskipper.").also { stage ++ } + CURE + 15 -> npcl(FacialExpression.NEUTRAL, "What it was, in fact, was a...").also { stage ++ } + CURE + 16 -> npcl(FacialExpression.NEUTRAL, "Dramatic Pause...").also { stage ++ } + CURE + 17 -> npcl(FacialExpression.PANICKED, "A Mogre!").also { stage ++ } + CURE + 18 -> playerl(FacialExpression.ASKING, "What exactly is a Mogre?").also { stage++ } + CURE + 19 -> npcl(FacialExpression.NEUTRAL, "A Mogre is a type of Ogre that spends most of its time underwater.").also { stage ++ } + CURE + 20 -> npcl(FacialExpression.NEUTRAL, "They hunt giant mudskippers by wearing their skins and swimming close until they can attack them.").also { stage ++ } + CURE + 21 -> npcl(FacialExpression.NEUTRAL, "When I used the Fishing Explosive I scared off all the fish, and so the Mogre got out of the water to express its extreme displeasure.").also { stage ++ } + CURE + 22 -> npcl(FacialExpression.NEUTRAL, "With an iron mace.").also { stage ++ } + CURE + 23 -> playerl(FacialExpression.ASKING, "I take it the head injury is responsible for the staggering and yelling?").also { stage++ } + CURE + 24 -> npcl(FacialExpression.NEUTRAL, "No, no.").also { stage ++ } + CURE + 25 -> npcl(FacialExpression.NEUTRAL, "My addiction to almost-lethal alcohol did that.").also { stage ++ } + CURE + 26 -> npcl(FacialExpression.NEUTRAL, "But if you are set on finding these Mogres just head south from here until you find Mudskipper Point.").also { stage ++ } + CURE + 27 -> playerl(FacialExpression.ASKING, "The mudskipper-eating monsters are to be found at Mudskipper point?").also { stage++ } + CURE + 28 -> playerl(FacialExpression.ROLLING_EYES, "Shock!").also { stage++ } + CURE + 29 -> playerl(FacialExpression.NEUTRAL, "Thanks. I'll be careful.").also { stage = END_DIALOGUE } + + NO_CURE -> playerl(FacialExpression.HALF_GUILTY, "I just came back to ask you something.").also { stage++ } + NO_CURE + 1 -> npcl(FacialExpression.ANNOYED, "What?").also { stage++ } + NO_CURE + 2 -> showTopics( + Topic("How do I make that hangover cure again?", RECIPE), + Topic("Why do they call you 'Skippy'?", NAME_ORIGIN) + ) + + RECIPE -> npcl(FacialExpression.ANGRY, "Give me strength...Here's what you do. Pay attention!").also { stage++ } + RECIPE + 1 -> npcl(FacialExpression.ANGRY, "You take a bucket of milk, a bar of chocolate and some snape grass.").also { stage++ } + RECIPE + 2 -> npcl(FacialExpression.ANGRY, "Grind the chocolate with a pestle and mortar.").also { stage++ } + RECIPE + 3 -> npcl(FacialExpression.ANGRY, "Add the chocolate powder to the milk, then add the snape grass.").also { stage++ } + RECIPE + 4 -> npcl(FacialExpression.ANGRY, "Then bring it here and I will drink it.").also { stage++ } + RECIPE + 5 -> npcl(FacialExpression.ANGRY, "Are you likely to remember that or should I go get some crayons and draw you a picture?").also { stage++ } + RECIPE + 6 -> playerl(FacialExpression.ANGRY, "Hey! I remember it now, ok! See you in a bit.").also { stage = END_DIALOGUE } + + NAME_ORIGIN -> npcl(FacialExpression.THINKING, "I think it may have something to do with my near- constant raving about mudskippers.").also { stage++ } + NAME_ORIGIN + 1 -> npcl(FacialExpression.THINKING, "That or it's something to do with that time with the dress and the field full of daisies...").also { stage = END_DIALOGUE } + } + DONE_QUEST -> when(stage){ + 0 -> playerl(FacialExpression.NEUTRAL, "Hey, Skippy.").also { stage++ } + 1 -> npcl(FacialExpression.HAPPY, "Hey you!").also { stage++ } + 2 -> playerl(FacialExpression.ASKING, "How do I annoy the Mogres again?").also { stage++ } + 3 -> npcl(FacialExpression.HAPPY, "Go south to Mudskipper Point and lob a Fishing Explosive into the sea. You can grab them from the Slayer masters.").also { stage++ } + 4 -> playerl(FacialExpression.ASKING, "Thanks! So, what are you going to do now?").also { stage++ } + 5 -> npcl(FacialExpression.HAPPY, "Well, I was planning on continuing my hobby of wandering up and down this bit of coastline, bellowing random threats and throwing bottles.").also { stage++ } + 6 -> npcl(FacialExpression.ASKING, "And you?").also { stage++ } + 7 -> playerl(FacialExpression.NEUTRAL, "I was planning on wandering up and down the landscape, bugging people to see if they had mindblowingly dangerous quests for me to undertake.").also { stage++ } + 8 -> npcl(FacialExpression.HAPPY, "Well, good luck with that!").also { stage++ } + 9 -> playerl(FacialExpression.HAPPY, "You too!").also { stage++ } + 10 -> npcl(FacialExpression.ROLLING_EYES, "Weirdo...").also { stage++ } + 11 -> playerl(FacialExpression.ROLLING_EYES, "Loony..").also { stage = END_DIALOGUE } + } + } + } +} + +class SkippyBootDialogue: DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + npc = NPC(NPCs.SKIPPY_2796) + val expression = if (getVarbit(player!!, Vars.VARBIT_MINI_QUEST_MOGRE) > SkippyBucketDialogue.DRUNK) FacialExpression.ROLLING_EYES else FacialExpression.DRUNK + npcl(expression, "Thanks! Now I have two right boots!").also { stage = END_DIALOGUE } + } + +} From e25780a4c5aa1aeb9a4161d7ca6bdead4a379e97 Mon Sep 17 00:00:00 2001 From: Ryan <2804894-ryannathans@users.noreply.gitlab.com> Date: Sun, 16 Feb 2025 11:10:18 +0000 Subject: [PATCH 231/306] Fixed player status SQLite conversion breaking on usernames with spaces --- Server/src/main/core/api/utils/PlayerStatsCounter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/core/api/utils/PlayerStatsCounter.kt b/Server/src/main/core/api/utils/PlayerStatsCounter.kt index 15808360b..3337c3de7 100644 --- a/Server/src/main/core/api/utils/PlayerStatsCounter.kt +++ b/Server/src/main/core/api/utils/PlayerStatsCounter.kt @@ -58,7 +58,7 @@ class PlayerStatsCounter( "Porting kill counters for player $progress/$totalPlayers" ) if (player is String) { - val playerUid = resolveUIDFromPlayerUsername(player) + val playerUid = resolveUIDFromPlayerUsername(player.replace(" ", "_")) log( PlayerStatsCounter::class.java, Log.INFO, @@ -91,7 +91,7 @@ class PlayerStatsCounter( "Porting rare drops for player $progress/$totalPlayers" ) if (player is String) { - val playerUid = resolveUIDFromPlayerUsername(player) + val playerUid = resolveUIDFromPlayerUsername(player.replace(" ", "_")) log( PlayerStatsCounter::class.java, Log.INFO, From 9eedfc23363b007857d38df524b74dbe4f2fdf25 Mon Sep 17 00:00:00 2001 From: GregF Date: Mon, 17 Feb 2025 10:37:28 +0000 Subject: [PATCH 232/306] Added some new regions --- Server/data/configs/xteas.json | 1324 +---------------- .../core/game/system/config/XteaParser.kt | 10 +- .../core/net/packet/out/UpdateSceneGraph.java | 3 - 3 files changed, 77 insertions(+), 1260 deletions(-) diff --git a/Server/data/configs/xteas.json b/Server/data/configs/xteas.json index 69528883f..5b8de21a7 100644 --- a/Server/data/configs/xteas.json +++ b/Server/data/configs/xteas.json @@ -1,17 +1,5 @@ { "xteas": [ - { - "regionId": "6230", - "keys": "0,0,0,0" - }, - { - "regionId": "6231", - "keys": "0,0,0,0" - }, - { - "regionId": "6232", - "keys": "0,0,0,0" - }, { "regionId": "6234", "keys": "-1591922206,-1429764510,-1087339341,1592935185" @@ -28,18 +16,6 @@ "regionId": "6483", "keys": "14881828,-6662814,58238456,146761213" }, - { - "regionId": "6484", - "keys": "0,0,0,0" - }, - { - "regionId": "6485", - "keys": "0,0,0,0" - }, - { - "regionId": "6486", - "keys": "0,0,0,0" - }, { "regionId": "6487", "keys": "-844708758,693908396,-1724237422,-2131620302" @@ -64,50 +40,10 @@ "regionId": "6726", "keys": "-3492110,65044555,1450623668,-483811536" }, - { - "regionId": "6732", - "keys": "0,0,0,0" - }, - { - "regionId": "6733", - "keys": "0,0,0,0" - }, - { - "regionId": "6734", - "keys": "0,0,0,0" - }, - { - "regionId": "6735", - "keys": "0,0,0,0" - }, - { - "regionId": "6736", - "keys": "0,0,0,0" - }, - { - "regionId": "6737", - "keys": "0,0,0,0" - }, - { - "regionId": "6738", - "keys": "0,0,0,0" - }, - { - "regionId": "6739", - "keys": "0,0,0,0" - }, - { - "regionId": "6740", - "keys": "0,0,0,0" - }, { "regionId": "6741", "keys": "-1634995791,710519356,-47126463,-1180416882" }, - { - "regionId": "6742", - "keys": "0,0,0,0" - }, { "regionId": "6743", "keys": "-1239303400,-1604922847,-1532369005,982307785" @@ -120,38 +56,14 @@ "regionId": "6745", "keys": "365190378,-1767339898,2011432030,276148826" }, - { - "regionId": "6746", - "keys": "0,0,0,0" - }, - { - "regionId": "6979", - "keys": "0,0,0,0" - }, - { - "regionId": "6980", - "keys": "0,0,0,0" - }, - { - "regionId": "6981", - "keys": "0,0,0,0" - }, { "regionId": "6985", "keys": "1193572731,-1288765743,-386862979,351599890" }, - { - "regionId": "6988", - "keys": "0,0,0,0" - }, { "regionId": "6989", "keys": "-891749173,-113432144,-1228601828,695082558" }, - { - "regionId": "6990", - "keys": "0,0,0,0" - }, { "regionId": "6991", "keys": "-1448188175,626198836,1985989165,-1062391664" @@ -172,46 +84,14 @@ "regionId": "6995", "keys": "-1227889203,-199624313,2143494494,531356102" }, - { - "regionId": "6996", - "keys": "0,0,0,0" - }, - { - "regionId": "6997", - "keys": "0,0,0,0" - }, - { - "regionId": "6998", - "keys": "0,0,0,0" - }, - { - "regionId": "6999", - "keys": "0,0,0,0" - }, - { - "regionId": "7000", - "keys": "0,0,0,0" - }, { "regionId": "7001", "keys": "170738852,2045755396,-1580637869,-1933392334" }, - { - "regionId": "7002", - "keys": "0,0,0,0" - }, - { - "regionId": "7235", - "keys": "0,0,0,0" - }, { "regionId": "7236", "keys": "570290255,-1513898184,-1269691884,782850050" }, - { - "regionId": "7237", - "keys": "0,0,0,0" - }, { "regionId": "7238", "keys": "-853120516,1697831503,-12188711,770411534" @@ -220,14 +100,6 @@ "regionId": "7244", "keys": "796665731,1335649913,758227393,585095755" }, - { - "regionId": "7245", - "keys": "0,0,0,0" - }, - { - "regionId": "7246", - "keys": "0,0,0,0" - }, { "regionId": "7247", "keys": "-122734679,-1029771956,1633683499,846700218" @@ -244,30 +116,10 @@ "regionId": "7250", "keys": "497663526,-1258315657,-785166329,-999527877" }, - { - "regionId": "7251", - "keys": "0,0,0,0" - }, - { - "regionId": "7252", - "keys": "0,0,0,0" - }, - { - "regionId": "7490", - "keys": "0,0,0,0" - }, - { - "regionId": "7491", - "keys": "0,0,0,0" - }, { "regionId": "7492", "keys": "417150556,1135530200,2139696777,-742314409" }, - { - "regionId": "7493", - "keys": "0,0,0,0" - }, { "regionId": "7494", "keys": "-1653750072,103282771,384178856,1122166637" @@ -276,14 +128,6 @@ "regionId": "7496", "keys": "-1890766195,-149577199,919306397,-954784877" }, - { - "regionId": "7497", - "keys": "0,0,0,0" - }, - { - "regionId": "7498", - "keys": "0,0,0,0" - }, { "regionId": "7499", "keys": "-2007696984,-1215288615,-1572330641,-2125382604" @@ -312,10 +156,6 @@ "regionId": "7505", "keys": "-1177354806,-1864641630,23736540,750869235" }, - { - "regionId": "7506", - "keys": "0,0,0,0" - }, { "regionId": "7507", "keys": "-1476331852,1093075535,-2003580146,734573751" @@ -332,6 +172,10 @@ "regionId": "7510", "keys": "2073894230,-553352720,274325814,-1461052837" }, + { + "regionId": "7511", + "keys": "14881828,-6662814,58238456,146761213" + }, { "regionId": "7513", "keys": "1066375195,548376104,-1771348528,1096433429" @@ -340,10 +184,6 @@ "regionId": "7745", "keys": "1212560091,-662504525,-1213494614,-1245629284" }, - { - "regionId": "7747", - "keys": "0,0,0,0" - }, { "regionId": "7748", "keys": "-850453392,-249468744,1635462867,100471784" @@ -352,10 +192,6 @@ "regionId": "7749", "keys": "369356966,-1038198212,282112206,802717032" }, - { - "regionId": "7750", - "keys": "0,0,0,0" - }, { "regionId": "7752", "keys": "1894158557,20416613,-1434347651,-1209846311" @@ -392,46 +228,14 @@ "regionId": "7760", "keys": "2042192998,743878512,-1804236758,-1160501924" }, - { - "regionId": "7761", - "keys": "0,0,0,0" - }, - { - "regionId": "7762", - "keys": "0,0,0,0" - }, { "regionId": "7763", "keys": "14881828,-6662814,58238456,146761213" }, - { - "regionId": "7764", - "keys": "0,0,0,0" - }, - { - "regionId": "7765", - "keys": "0,0,0,0" - }, { "regionId": "7769", "keys": "560280774,910095015,871073102,263015376" }, - { - "regionId": "7995", - "keys": "0,0,0,0" - }, - { - "regionId": "7996", - "keys": "0,0,0,0" - }, - { - "regionId": "7997", - "keys": "0,0,0,0" - }, - { - "regionId": "7998", - "keys": "0,0,0,0" - }, { "regionId": "8001", "keys": "690512367,1578449236,-1443501555,546253393" @@ -440,10 +244,6 @@ "regionId": "8002", "keys": "1597309277,469931771,1619035792,663887748" }, - { - "regionId": "8003", - "keys": "0,0,0,0" - }, { "regionId": "8004", "keys": "609107948,-755432209,-723012522,1175820911" @@ -488,26 +288,14 @@ "regionId": "8015", "keys": "305015825,-634097708,865786116,-1850059578" }, - { - "regionId": "8016", - "keys": "0,0,0,0" - }, { "regionId": "8017", "keys": "959968310,-363819769,-1402232275,-1678358818" }, - { - "regionId": "8018", - "keys": "0,0,0,0" - }, { "regionId": "8019", "keys": "-1512999074,1064201012,2143076355,-1937376726" }, - { - "regionId": "8020", - "keys": "-955989323,1284433026,690014510,2145912092" - }, { "regionId": "8021", "keys": "-297039986,-1011877372,-1763869337,-900998253" @@ -528,6 +316,14 @@ "regionId": "8241", "keys": "-320813650,-1654452876,-352291520,-290946896" }, + { + "regionId": "8242", + "keys": "347990635,-1017326068,-1600504696,1565374916" + }, + { + "regionId": "8243", + "keys": "-107199068,-843304946,910528064,-626516712" + }, { "regionId": "8251", "keys": "1142567601,1650263019,49659607,-899246535" @@ -580,10 +376,6 @@ "regionId": "8267", "keys": "-474856962,-1295973639,789657650,-1769058462" }, - { - "regionId": "8268", - "keys": "0,0,0,0" - }, { "regionId": "8269", "keys": "-497435078,2028988145,486156819,-1178938803" @@ -604,22 +396,6 @@ "regionId": "8273", "keys": "978831670,664328414,1943273766,-1823800887" }, - { - "regionId": "8274", - "keys": "0,0,0,0" - }, - { - "regionId": "8275", - "keys": "0,0,0,0" - }, - { - "regionId": "8276", - "keys": "0,0,0,0" - }, - { - "regionId": "8277", - "keys": "0,0,0,0" - }, { "regionId": "8280", "keys": "-1615836970,1947387796,2141672540,-333423400" @@ -644,10 +420,6 @@ "regionId": "8499", "keys": "1158999293,2131770333,-861122128,1149793504" }, - { - "regionId": "8500", - "keys": "0,0,0,0" - }, { "regionId": "8506", "keys": "-1227747958,1491928866,1293676120,2065870654" @@ -724,30 +496,14 @@ "regionId": "8530", "keys": "-1466808210,962381183,-1581244207,-457271917" }, - { - "regionId": "8531", - "keys": "0,0,0,0" - }, { "regionId": "8532", "keys": "1553260654,1996107908,-2124357970,1441816370" }, - { - "regionId": "8533", - "keys": "0,0,0,0" - }, { "regionId": "8534", "keys": "1712031920,299813553,484205392,-939092911" }, - { - "regionId": "8545", - "keys": "1322297584,105544016,-1148309508,-574484176" - }, - { - "regionId": "8751", - "keys": "0,0,0,0" - }, { "regionId": "8752", "keys": "238354066,1687454525,1494747147,1911377137" @@ -764,22 +520,6 @@ "regionId": "8755", "keys": "-1165798584,772244190,-402783978,541755309" }, - { - "regionId": "8756", - "keys": "0,0,0,0" - }, - { - "regionId": "8757", - "keys": "0,0,0,0" - }, - { - "regionId": "8759", - "keys": "0,0,0,0" - }, - { - "regionId": "8760", - "keys": "0,0,0,0" - }, { "regionId": "8761", "keys": "1760753095,-1427813077,266675077,-255782653" @@ -804,6 +544,14 @@ "regionId": "8766", "keys": "1244410566,-1397143615,-1848205088,-1435723900" }, + { + "regionId": "8767", + "keys": "-368125809,-1805271492,-400403765,697149536" + }, + { + "regionId": "8768", + "keys": "-517024281,-1363386333,227729042,-1950025355" + }, { "regionId": "8769", "keys": "2044453226,-2064473213,1306128347,784973817" @@ -840,10 +588,6 @@ "regionId": "8779", "keys": "-1680845199,-1149954104,-1177525481,-576614197" }, - { - "regionId": "8780", - "keys": "0,0,0,0" - }, { "regionId": "8781", "keys": "-2133721491,843228961,1706232103,-934369964" @@ -864,34 +608,14 @@ "regionId": "8785", "keys": "1543774040,-487517297,-1630373503,102220753" }, - { - "regionId": "8786", - "keys": "0,0,0,0" - }, { "regionId": "8787", "keys": "1791798624,-1711313280,166719404,-1487207913" }, - { - "regionId": "8788", - "keys": "0,0,0,0" - }, - { - "regionId": "8789", - "keys": "0,0,0,0" - }, { "regionId": "8790", "keys": "230755787,-1139640838,-21592892,49661984" }, - { - "regionId": "9006", - "keys": "0,0,0,0" - }, - { - "regionId": "9007", - "keys": "0,0,0,0" - }, { "regionId": "9008", "keys": "2084752401,-1394447522,2084945842,1474596929" @@ -912,18 +636,6 @@ "regionId": "9012", "keys": "1204696185,-486414605,-1016110497,134649113" }, - { - "regionId": "9013", - "keys": "0,0,0,0" - }, - { - "regionId": "9014", - "keys": "0,0,0,0" - }, - { - "regionId": "9015", - "keys": "0,0,0,0" - }, { "regionId": "9016", "keys": "-1274221467,730617286,-1448054569,427043430" @@ -948,6 +660,14 @@ "regionId": "9021", "keys": "-665917952,-432697139,-602494723,-2097936281" }, + { + "regionId": "9022", + "keys": "1910381678,352194237,836248,347278834" + }, + { + "regionId": "9024", + "keys": "-785865296,-520648067,-1207176889,-441641818" + }, { "regionId": "9025", "keys": "1812159970,1795526437,1172074678,289074337" @@ -976,34 +696,10 @@ "regionId": "9035", "keys": "1525685385,1372975156,-2010144170,-1594192581" }, - { - "regionId": "9036", - "keys": "0,0,0,0" - }, - { - "regionId": "9037", - "keys": "0,0,0,0" - }, { "regionId": "9038", "keys": "-473165893,2110570897,-1726275929,806180444" }, - { - "regionId": "9040", - "keys": "0,0,0,0" - }, - { - "regionId": "9041", - "keys": "0,0,0,0" - }, - { - "regionId": "9042", - "keys": "0,0,0,0" - }, - { - "regionId": "9043", - "keys": "0,0,0,0" - }, { "regionId": "9044", "keys": "1541894861,-2145670115,-138793212,-921922364" @@ -1028,18 +724,6 @@ "regionId": "9050", "keys": "-1725663967,1678055280,1100896300,706957861" }, - { - "regionId": "9109", - "keys": "0,0,0,0" - }, - { - "regionId": "9110", - "keys": "0,0,0,0" - }, - { - "regionId": "9111", - "keys": "0,0,0,0" - }, { "regionId": "9113", "keys": "-570298090,-864625293,-668545435,8389096" @@ -1048,18 +732,6 @@ "regionId": "9114", "keys": "-962790446,-1706163576,82969599,310163719" }, - { - "regionId": "9120", - "keys": "0,0,0,0" - }, - { - "regionId": "9121", - "keys": "0,0,0,0" - }, - { - "regionId": "9122", - "keys": "0,0,0,0" - }, { "regionId": "9262", "keys": "-1327237404,-257519940,-1398355053,-970581711" @@ -1125,21 +797,21 @@ "keys": "272801923,1797149371,-131972865,1265002008" }, { - "regionId": "9283", - "keys": "0,0,0,0" + "regionId": "9278", + "keys": "-1782196006,1021278723,887209787,-1016997291" }, { - "regionId": "9284", - "keys": "0,0,0,0" + "regionId": "9279", + "keys": "-841578670,318269186,-353500843,-932268603" + }, + { + "regionId": "9280", + "keys": "727010382,181752242,1033156911,1262921484" }, { "regionId": "9285", "keys": "1742241898,-1564206342,-460725435,1614032789" }, - { - "regionId": "9286", - "keys": "0,0,0,0" - }, { "regionId": "9287", "keys": "-272431907,639665846,-1633276264,1645937141" @@ -1156,14 +828,6 @@ "regionId": "9290", "keys": "702687456,43635181,-1983533012,-319469910" }, - { - "regionId": "9291", - "keys": "0,0,0,0" - }, - { - "regionId": "9292", - "keys": "0,0,0,0" - }, { "regionId": "9293", "keys": "-810831340,-1857428683,-892017185,249052010" @@ -1176,30 +840,14 @@ "regionId": "9295", "keys": "224580924,-858933614,-432602901,-1433710083" }, - { - "regionId": "9296", - "keys": "0,0,0,0" - }, { "regionId": "9297", "keys": "-1667110403,-655319123,-2124588845,-262291671" }, - { - "regionId": "9298", - "keys": "0,0,0,0" - }, - { - "regionId": "9299", - "keys": "0,0,0,0" - }, { "regionId": "9300", "keys": "644587156,-605721698,681391959,1688865408" }, - { - "regionId": "9301", - "keys": "0,0,0,0" - }, { "regionId": "9304", "keys": "14881828,-6662814,58238456,146761213" @@ -1216,10 +864,6 @@ "regionId": "9362", "keys": "-253025041,376209206,1663580032,1115549308" }, - { - "regionId": "9363", - "keys": "0,0,0,0" - }, { "regionId": "9364", "keys": "1350964684,-1141243546,-158288919,1853454502" @@ -1232,10 +876,6 @@ "regionId": "9366", "keys": "-1691974727,-1591730841,1506117200,822346809" }, - { - "regionId": "9367", - "keys": "0,0,0,0" - }, { "regionId": "9368", "keys": "-911562498,-1433720091,257702084,1652121807" @@ -1256,30 +896,10 @@ "regionId": "9372", "keys": "1005996231,-569567890,-1578994771,-1136932414" }, - { - "regionId": "9376", - "keys": "0,0,0,0" - }, { "regionId": "9377", "keys": "-1671261866,-750153286,1731026368,-1501269926" }, - { - "regionId": "9378", - "keys": "0,0,0,0" - }, - { - "regionId": "9515", - "keys": "0,0,0,0" - }, - { - "regionId": "9516", - "keys": "0,0,0,0" - }, - { - "regionId": "9517", - "keys": "0,0,0,0" - }, { "regionId": "9518", "keys": "-557639005,398566091,-133936467,-850662847" @@ -1344,6 +964,14 @@ "regionId": "9533", "keys": "1393307887,646464303,-1582337843,2048412434" }, + { + "regionId": "9534", + "keys": "-2072244370,1114739695,-1096608867,-1932870993" + }, + { + "regionId": "9535", + "keys": "-1107428972,531677783,-1575581308,1343828898" + }, { "regionId": "9536", "keys": "679931979,-1660801436,-1184954844,-1006016912" @@ -1360,10 +988,6 @@ "regionId": "9541", "keys": "1352006827,1096305726,805420370,-1426885864" }, - { - "regionId": "9542", - "keys": "0,0,0,0" - }, { "regionId": "9543", "keys": "1852273964,-104833248,-2069080639,-188650169" @@ -1384,10 +1008,6 @@ "regionId": "9547", "keys": "-1998382641,30700550,1548517068,-855708219" }, - { - "regionId": "9548", - "keys": "0,0,0,0" - }, { "regionId": "9549", "keys": "-1648136735,1402264941,639592027,348907048" @@ -1408,22 +1028,10 @@ "regionId": "9553", "keys": "-1873675730,-1930195432,759400017,-1395479956" }, - { - "regionId": "9554", - "keys": "0,0,0,0" - }, - { - "regionId": "9555", - "keys": "0,0,0,0" - }, { "regionId": "9556", "keys": "-300312374,-1152515846,-863452271,-1500855067" }, - { - "regionId": "9557", - "keys": "0,0,0,0" - }, { "regionId": "9558", "keys": "1245928204,-1892089406,-1321168410,-1108146443" @@ -1440,10 +1048,6 @@ "regionId": "9562", "keys": "-1047298777,1197811918,663745433,-2098029011" }, - { - "regionId": "9619", - "keys": "0,0,0,0" - }, { "regionId": "9620", "keys": "1941157140,-1630547377,-1114648519,87057467" @@ -1472,18 +1076,6 @@ "regionId": "9626", "keys": "-1411729186,1049744836,-1608961973,-1681145313" }, - { - "regionId": "9627", - "keys": "0,0,0,0" - }, - { - "regionId": "9629", - "keys": "0,0,0,0" - }, - { - "regionId": "9630", - "keys": "0,0,0,0" - }, { "regionId": "9631", "keys": "1266963397,269916041,734658458,725243574" @@ -1492,18 +1084,6 @@ "regionId": "9632", "keys": "1023657558,-2001662423,-46679010,2064543607" }, - { - "regionId": "9633", - "keys": "0,0,0,0" - }, - { - "regionId": "9634", - "keys": "0,0,0,0" - }, - { - "regionId": "9771", - "keys": "0,0,0,0" - }, { "regionId": "9772", "keys": "-1742165439,-1273697376,2055229018,901215817" @@ -1576,6 +1156,10 @@ "regionId": "9789", "keys": "-620749099,528872615,1976629038,667155751" }, + { + "regionId": "9791", + "keys": "-2105683947,1913166182,-1697741730,-25818496" + }, { "regionId": "9792", "keys": "1500471532,1729075639,-304984137,1117230148" @@ -1584,10 +1168,6 @@ "regionId": "9794", "keys": "1788083183,2097372895,1633476682,-589223611" }, - { - "regionId": "9795", - "keys": "0,0,0,0" - }, { "regionId": "9796", "keys": "517509106,-2019799796,1066150754,-676371780" @@ -1596,10 +1176,6 @@ "regionId": "9797", "keys": "672333395,-284721288,262558790,-344798491" }, - { - "regionId": "9798", - "keys": "0,0,0,0" - }, { "regionId": "9799", "keys": "181886191,758691911,810524169,1456599388" @@ -1632,10 +1208,6 @@ "regionId": "9806", "keys": "368995667,940146211,957819918,-761335591" }, - { - "regionId": "9807", - "keys": "0,0,0,0" - }, { "regionId": "9808", "keys": "308766586,-214665927,-1255727041,-1034716346" @@ -1656,10 +1228,6 @@ "regionId": "9812", "keys": "50571970,-1762921782,-1667424270,524742325" }, - { - "regionId": "9813", - "keys": "0,0,0,0" - }, { "regionId": "9814", "keys": "-34428628,1940609264,-1638642159,-295486604" @@ -1704,38 +1272,14 @@ "regionId": "9883", "keys": "472234846,1198089044,500187071,239458328" }, - { - "regionId": "9884", - "keys": "0,0,0,0" - }, - { - "regionId": "9885", - "keys": "0,0,0,0" - }, { "regionId": "9886", "keys": "1515209815,-1457146379,-146402808,-1454274033" }, - { - "regionId": "9887", - "keys": "0,0,0,0" - }, - { - "regionId": "9888", - "keys": "0,0,0,0" - }, - { - "regionId": "9889", - "keys": "0,0,0,0" - }, { "regionId": "10027", "keys": "1491811841,1724263915,-1397066186,1733646819" }, - { - "regionId": "10028", - "keys": "0,0,0,0" - }, { "regionId": "10029", "keys": "203145796,-773666188,-569831878,-1510455793" @@ -1760,10 +1304,6 @@ "regionId": "10034", "keys": "-1435464304,-836439389,-788586899,1579582706" }, - { - "regionId": "10035", - "keys": "0,0,0,0" - }, { "regionId": "10036", "keys": "689954852,-1377739344,-847433475,-1883927289" @@ -1804,26 +1344,18 @@ "regionId": "10045", "keys": "-1429464298,1580360509,-1936477065,-337842786" }, + { + "regionId": "10046", + "keys": "1579643227,-1819574910,1035634488,-1469908551" + }, + { + "regionId": "10047", + "keys": "1248461784,913422340,-928862457,-1858877253" + }, { "regionId": "10048", "keys": "-1457016886,349941309,-400267403,-1711584223" }, - { - "regionId": "10051", - "keys": "0,0,0,0" - }, - { - "regionId": "10052", - "keys": "0,0,0,0" - }, - { - "regionId": "10053", - "keys": "0,0,0,0" - }, - { - "regionId": "10054", - "keys": "0,0,0,0" - }, { "regionId": "10055", "keys": "-813287484,-1417786621,-1794468339,578992617" @@ -1844,10 +1376,6 @@ "regionId": "10059", "keys": "1185163869,-1047826729,-1461057337,139139001" }, - { - "regionId": "10060", - "keys": "0,0,0,0" - }, { "regionId": "10061", "keys": "1683880127,1851133137,-567572662,-1477799312" @@ -1856,10 +1384,6 @@ "regionId": "10062", "keys": "2024717410,-1807032706,1106507805,1426160484" }, - { - "regionId": "10063", - "keys": "0,0,0,0" - }, { "regionId": "10064", "keys": "1978019309,1433546802,-1989346624,-1611361553" @@ -1872,10 +1396,6 @@ "regionId": "10066", "keys": "105954939,-1741244981,-1491777272,207112205" }, - { - "regionId": "10067", - "keys": "0,0,0,0" - }, { "regionId": "10068", "keys": "-452138979,-1929816521,364996963,-1315825295" @@ -1952,26 +1472,14 @@ "regionId": "10140", "keys": "-104825447,-1092637213,-105814713,-2129567531" }, - { - "regionId": "10141", - "keys": "0,0,0,0" - }, { "regionId": "10142", "keys": "1872120942,-765842959,449655176,-1168971827" }, - { - "regionId": "10143", - "keys": "0,0,0,0" - }, { "regionId": "10144", "keys": "265530509,2033515489,-2022406749,-591072091" }, - { - "regionId": "10145", - "keys": "0,0,0,0" - }, { "regionId": "10280", "keys": "-1245893544,-118079793,-1624599660,-626968532" @@ -1988,10 +1496,6 @@ "regionId": "10283", "keys": "-2133080221,1327669620,173304076,-151662318" }, - { - "regionId": "10284", - "keys": "0,0,0,0" - }, { "regionId": "10285", "keys": "-1317120534,1321149083,-1700628824,1028203235" @@ -2016,10 +1520,6 @@ "regionId": "10290", "keys": "-587752684,-318735232,336724431,-1931735346" }, - { - "regionId": "10291", - "keys": "0,0,0,0" - }, { "regionId": "10292", "keys": "933507835,1135929795,-1932059890,1492191263" @@ -2108,10 +1608,6 @@ "regionId": "10315", "keys": "-1034094191,1810212216,618808107,1905492210" }, - { - "regionId": "10316", - "keys": "0,0,0,0" - }, { "regionId": "10317", "keys": "216403117,1910251124,144162918,224240414" @@ -2120,14 +1616,6 @@ "regionId": "10318", "keys": "1053988597,-2121917140,1730755899,1549334321" }, - { - "regionId": "10319", - "keys": "0,0,0,0" - }, - { - "regionId": "10320", - "keys": "0,0,0,0" - }, { "regionId": "10321", "keys": "1996825886,-1552231723,1721080145,-869420516" @@ -2136,18 +1624,10 @@ "regionId": "10322", "keys": "1773602876,-1410394076,-239593243,148286798" }, - { - "regionId": "10323", - "keys": "0,0,0,0" - }, { "regionId": "10324", "keys": "-1670587478,-401532783,1705875521,995683837" }, - { - "regionId": "10325", - "keys": "0,0,0,0" - }, { "regionId": "10326", "keys": "-375687378,472100528,-288941184,523344380" @@ -2208,26 +1688,10 @@ "regionId": "10396", "keys": "-1878072140,1648991920,1054624070,333445417" }, - { - "regionId": "10397", - "keys": "0,0,0,0" - }, - { - "regionId": "10398", - "keys": "0,0,0,0" - }, - { - "regionId": "10399", - "keys": "0,0,0,0" - }, { "regionId": "10400", "keys": "-1656816922,1318311812,-811481661,1625916625" }, - { - "regionId": "10401", - "keys": "0,0,0,0" - }, { "regionId": "10536", "keys": "349537117,1202512092,-698870718,-2083455397" @@ -2272,10 +1736,6 @@ "regionId": "10546", "keys": "192659093,263441429,29086759,670094037" }, - { - "regionId": "10547", - "keys": "0,0,0,0" - }, { "regionId": "10548", "keys": "-1157394711,-1306553144,2105373539,798383108" @@ -2332,10 +1792,6 @@ "regionId": "10564", "keys": "1279522133,380240348,604239496,1759916207" }, - { - "regionId": "10565", - "keys": "0,0,0,0" - }, { "regionId": "10566", "keys": "221004409,1368318650,-1237341956,25411913" @@ -2364,10 +1820,6 @@ "regionId": "10572", "keys": "-1375061166,-1411427241,-294467489,-2106748278" }, - { - "regionId": "10573", - "keys": "0,0,0,0" - }, { "regionId": "10574", "keys": "-1609693854,991245740,148787249,-1011766477" @@ -2376,10 +1828,6 @@ "regionId": "10575", "keys": "434036980,-780702800,-1042242727,-354464628" }, - { - "regionId": "10576", - "keys": "0,0,0,0" - }, { "regionId": "10577", "keys": "824897954,-1807466644,2079017570,1299975025" @@ -2393,12 +1841,8 @@ "keys": "-123618550,684067223,486273630,-1103816964" }, { - "regionId": "10580", - "keys": "0,0,0,0" - }, - { - "regionId": "10637", - "keys": "0,0,0,0" + "regionId": "10583", + "keys": "14881828,-6662814,58238456,146761213" }, { "regionId": "10638", @@ -2448,10 +1892,6 @@ "regionId": "10650", "keys": "-908578223,-911827513,1137573080,-419444146" }, - { - "regionId": "10651", - "keys": "0,0,0,0" - }, { "regionId": "10652", "keys": "1580722385,609745227,1407021351,1098485033" @@ -2460,22 +1900,6 @@ "regionId": "10653", "keys": "570189753,-1700559836,2108215671,-701775893" }, - { - "regionId": "10654", - "keys": "0,0,0,0" - }, - { - "regionId": "10655", - "keys": "0,0,0,0" - }, - { - "regionId": "10656", - "keys": "0,0,0,0" - }, - { - "regionId": "10657", - "keys": "0,0,0,0" - }, { "regionId": "10792", "keys": "-125671574,254943715,1343095705,-1965171670" @@ -2516,10 +1940,6 @@ "regionId": "10801", "keys": "850125851,1199386038,-1494136472,-1487577933" }, - { - "regionId": "10802", - "keys": "0,0,0,0" - }, { "regionId": "10803", "keys": "-1028081880,964144306,174845257,1906118817" @@ -2572,6 +1992,10 @@ "regionId": "10815", "keys": "2102925673,1133406202,-1885710196,165240951" }, + { + "regionId": "10816", + "keys": "-1909517714,218137505,744896894,831968418" + }, { "regionId": "10819", "keys": "-904401587,-2054970579,55120674,-1889562804" @@ -2612,10 +2036,6 @@ "regionId": "10828", "keys": "1665018619,-1607107877,-1997272567,1342325223" }, - { - "regionId": "10829", - "keys": "0,0,0,0" - }, { "regionId": "10830", "keys": "-608096960,58771202,1174291927,-1613596249" @@ -2636,18 +2056,10 @@ "regionId": "10834", "keys": "-1640569486,-512141704,-1179536382,720004469" }, - { - "regionId": "10835", - "keys": "0,0,0,0" - }, { "regionId": "10836", "keys": "1637505449,619992365,-1935536269,-1526242295" }, - { - "regionId": "10837", - "keys": "0,0,0,0" - }, { "regionId": "10838", "keys": "1678881362,-952862831,-1804688659,-1247653912" @@ -2744,10 +2156,6 @@ "regionId": "10911", "keys": "948965123,-545528654,-459191491,-860302360" }, - { - "regionId": "10912", - "keys": "0,0,0,0" - }, { "regionId": "11049", "keys": "-621090199,-1004888612,-749707219,2052444337" @@ -2872,30 +2280,14 @@ "regionId": "11083", "keys": "1255503855,-674022312,-807132804,-1287799121" }, - { - "regionId": "11084", - "keys": "0,0,0,0" - }, { "regionId": "11085", "keys": "327229160,-1433790638,1944433240,234034136" }, - { - "regionId": "11086", - "keys": "0,0,0,0" - }, - { - "regionId": "11087", - "keys": "0,0,0,0" - }, { "regionId": "11088", "keys": "-1943123304,1713176080,-1524844090,-445387865" }, - { - "regionId": "11089", - "keys": "0,0,0,0" - }, { "regionId": "11090", "keys": "2089067081,828176382,-1112393031,-1452165920" @@ -2904,10 +2296,6 @@ "regionId": "11091", "keys": "977844365,-245927723,99303766,-735341354" }, - { - "regionId": "11092", - "keys": "0,0,0,0" - }, { "regionId": "11093", "keys": "-379710910,-2088433559,1180928189,-54938349" @@ -2972,14 +2360,6 @@ "regionId": "11158", "keys": "160361538,733169435,1244326761,1681727551" }, - { - "regionId": "11159", - "keys": "0,0,0,0" - }, - { - "regionId": "11160", - "keys": "0,0,0,0" - }, { "regionId": "11161", "keys": "-1713920755,1291269906,320754968,741637543" @@ -3008,10 +2388,6 @@ "regionId": "11167", "keys": "-1735216162,2141149053,57787230,-1263840909" }, - { - "regionId": "11168", - "keys": "0,0,0,0" - }, { "regionId": "11305", "keys": "-1429346525,-118378130,1002549662,1383588995" @@ -3088,10 +2464,6 @@ "regionId": "11323", "keys": "-1710808226,725482732,1863997544,5983834" }, - { - "regionId": "11324", - "keys": "0,0,0,0" - }, { "regionId": "11326", "keys": "1862093150,1696245244,1320714102,1241887579" @@ -3108,30 +2480,14 @@ "regionId": "11332", "keys": "-936631483,-1093055133,-161202591,-1476364681" }, - { - "regionId": "11333", - "keys": "0,0,0,0" - }, - { - "regionId": "11334", - "keys": "0,0,0,0" - }, { "regionId": "11335", "keys": "-133492081,-915358326,-714649892,-2093709476" }, - { - "regionId": "11338", - "keys": "0,0,0,0" - }, { "regionId": "11339", "keys": "140118336,-1920268877,-1967576060,-1437209189" }, - { - "regionId": "11340", - "keys": "0,0,0,0" - }, { "regionId": "11341", "keys": "-1219163353,-1635920416,-2124217842,-1318908036" @@ -3152,14 +2508,6 @@ "regionId": "11347", "keys": "-122396964,-1996200666,-585000602,-863390951" }, - { - "regionId": "11348", - "keys": "0,0,0,0" - }, - { - "regionId": "11349", - "keys": "0,0,0,0" - }, { "regionId": "11350", "keys": "-1365557009,-1350738529,-1074800707,-446118748" @@ -3184,22 +2532,10 @@ "regionId": "11356", "keys": "2033204014,1416145849,-1721330996,2134394884" }, - { - "regionId": "11405", - "keys": "0,0,0,0" - }, { "regionId": "11406", "keys": "375301159,353365492,-940259891,-223647771" }, - { - "regionId": "11407", - "keys": "0,0,0,0" - }, - { - "regionId": "11408", - "keys": "0,0,0,0" - }, { "regionId": "11409", "keys": "1937092760,-1545935537,29954084,-1081016062" @@ -3208,10 +2544,6 @@ "regionId": "11410", "keys": "1509299526,-892391942,1485831814,1255407038" }, - { - "regionId": "11411", - "keys": "0,0,0,0" - }, { "regionId": "11412", "keys": "-1379772393,621580805,-316850307,1026773740" @@ -3316,10 +2648,6 @@ "regionId": "11572", "keys": "892185929,686162443,1793819023,-992991976" }, - { - "regionId": "11573", - "keys": "0,0,0,0" - }, { "regionId": "11574", "keys": "-1406155502,13961326,1071473330,1528558089" @@ -3336,22 +2664,10 @@ "regionId": "11577", "keys": "1283493672,1550135524,-1621670256,769418438" }, - { - "regionId": "11578", - "keys": "0,0,0,0" - }, { "regionId": "11579", "keys": "-719996638,-1831948234,494156672,1684753309" }, - { - "regionId": "11580", - "keys": "0,0,0,0" - }, - { - "regionId": "11581", - "keys": "0,0,0,0" - }, { "regionId": "11582", "keys": "602331327,-1036793753,1702673112,-1107214996" @@ -3376,18 +2692,10 @@ "regionId": "11589", "keys": "39678032,469576041,-1878694956,-1720799345" }, - { - "regionId": "11590", - "keys": "0,0,0,0" - }, { "regionId": "11591", "keys": "1300749474,-912770362,-1665451776,480747745" }, - { - "regionId": "11592", - "keys": "0,0,0,0" - }, { "regionId": "11593", "keys": "14881828,-6662814,58238456,146761213" @@ -3400,26 +2708,14 @@ "regionId": "11595", "keys": "-1497259084,-1208341848,874209282,-1950133061" }, - { - "regionId": "11596", - "keys": "0,0,0,0" - }, { "regionId": "11597", "keys": "-824244627,-1750674106,-2032396270,-451550546" }, - { - "regionId": "11598", - "keys": "0,0,0,0" - }, { "regionId": "11599", "keys": "-1124938025,110281395,-1121479364,68953473" }, - { - "regionId": "11600", - "keys": "0,0,0,0" - }, { "regionId": "11601", "keys": "722657934,1495340205,-437272583,-1331954618" @@ -3432,10 +2728,6 @@ "regionId": "11603", "keys": "-254635141,-1757221941,-2072225761,-752948578" }, - { - "regionId": "11604", - "keys": "0,0,0,0" - }, { "regionId": "11605", "keys": "57037316,1119657363,2040370510,801474589" @@ -3444,10 +2736,6 @@ "regionId": "11606", "keys": "-1790275662,-1050505330,-1496410655,679769180" }, - { - "regionId": "11607", - "keys": "0,0,0,0" - }, { "regionId": "11608", "keys": "248039728,1861834308,1335200688,317723667" @@ -3456,10 +2744,6 @@ "regionId": "11609", "keys": "-1581925228,-215021003,-1695323698,-1853661356" }, - { - "regionId": "11610", - "keys": "0,0,0,0" - }, { "regionId": "11612", "keys": "-1751954695,954770889,-337304771,986015401" @@ -3564,14 +2848,6 @@ "regionId": "11824", "keys": "-1116727390,-659788658,307002260,354360287" }, - { - "regionId": "11825", - "keys": "0,0,0,0" - }, - { - "regionId": "11826", - "keys": "0,0,0,0" - }, { "regionId": "11827", "keys": "379001889,1835230493,1861106702,338991847" @@ -3632,42 +2908,10 @@ "regionId": "11844", "keys": "46502425,-1301719099,-1597781617,1434487073" }, - { - "regionId": "11845", - "keys": "0,0,0,0" - }, - { - "regionId": "11846", - "keys": "0,0,0,0" - }, - { - "regionId": "11847", - "keys": "0,0,0,0" - }, - { - "regionId": "11848", - "keys": "0,0,0,0" - }, - { - "regionId": "11849", - "keys": "0,0,0,0" - }, - { - "regionId": "11850", - "keys": "0,0,0,0" - }, { "regionId": "11851", "keys": "-516358140,791692293,-1663509747,1243508195" }, - { - "regionId": "11852", - "keys": "0,0,0,0" - }, - { - "regionId": "11853", - "keys": "0,0,0,0" - }, { "regionId": "11854", "keys": "311566497,-486013229,1351929142,744327317" @@ -3676,30 +2920,10 @@ "regionId": "11855", "keys": "770787544,-1305958539,670684335,208100825" }, - { - "regionId": "11856", - "keys": "0,0,0,0" - }, { "regionId": "11857", "keys": "150488681,419659968,-1871963555,1031596369" }, - { - "regionId": "11858", - "keys": "0,0,0,0" - }, - { - "regionId": "11859", - "keys": "0,0,0,0" - }, - { - "regionId": "11860", - "keys": "0,0,0,0" - }, - { - "regionId": "11861", - "keys": "0,0,0,0" - }, { "regionId": "11862", "keys": "2071521092,797384499,364423664,-1286422461" @@ -3744,10 +2968,6 @@ "regionId": "11926", "keys": "-501586879,235710413,-1122707717,-354940885" }, - { - "regionId": "11927", - "keys": "0,0,0,0" - }, { "regionId": "11928", "keys": "-445378710,-788377286,1363332226,627739779" @@ -3760,18 +2980,6 @@ "regionId": "11930", "keys": "1436132147,-902725534,590285278,2018675988" }, - { - "regionId": "11931", - "keys": "0,0,0,0" - }, - { - "regionId": "11932", - "keys": "0,0,0,0" - }, - { - "regionId": "11933", - "keys": "0,0,0,0" - }, { "regionId": "11934", "keys": "-854127330,1609124159,-999989310,-734721734" @@ -3780,22 +2988,10 @@ "regionId": "11935", "keys": "-1453725493,-1575973068,1979334907,1130399929" }, - { - "regionId": "11936", - "keys": "0,0,0,0" - }, { "regionId": "11937", "keys": "-1518927827,1819850502,-992647105,299958470" }, - { - "regionId": "11938", - "keys": "0,0,0,0" - }, - { - "regionId": "12073", - "keys": "-882281631,257910959,1642484329,-1342807140" - }, { "regionId": "12076", "keys": "193939514,-115011236,-1406304015,-1626342231" @@ -3876,26 +3072,10 @@ "regionId": "12097", "keys": "-862465947,2109948185,583246321,-850147469" }, - { - "regionId": "12098", - "keys": "0,0,0,0" - }, - { - "regionId": "12099", - "keys": "0,0,0,0" - }, { "regionId": "12100", "keys": "1852910519,712916664,1670787779,1294835477" }, - { - "regionId": "12101", - "keys": "0,0,0,0" - }, - { - "regionId": "12102", - "keys": "14881828,-6662814,58238456,146761213" - }, { "regionId": "12105", "keys": "1153497516,-449169462,-635419798,-1471828315" @@ -3924,10 +3104,6 @@ "regionId": "12111", "keys": "-746445771,1759120362,1253848335,1433199232" }, - { - "regionId": "12112", - "keys": "0,0,0,0" - }, { "regionId": "12113", "keys": "-1749952613,1569535680,1900425482,-1993748284" @@ -3936,10 +3112,6 @@ "regionId": "12115", "keys": "2146362785,1996258091,-613445101,539756591" }, - { - "regionId": "12116", - "keys": "0,0,0,0" - }, { "regionId": "12117", "keys": "-97063310,1962833557,-849078816,-1560293275" @@ -3976,10 +3148,6 @@ "regionId": "12182", "keys": "-499997333,1910872683,-234510566,-361238419" }, - { - "regionId": "12183", - "keys": "0,0,0,0" - }, { "regionId": "12184", "keys": "-1993918550,1977224805,-1048356116,-1578331413" @@ -3992,10 +3160,6 @@ "regionId": "12186", "keys": "-259674875,-949495016,1835821953,1740556829" }, - { - "regionId": "12187", - "keys": "0,0,0,0" - }, { "regionId": "12188", "keys": "22801476,-1237575758,2139201694,-163382547" @@ -4004,26 +3168,10 @@ "regionId": "12189", "keys": "-626419958,-861781849,-400257621,465575053" }, - { - "regionId": "12191", - "keys": "0,0,0,0" - }, - { - "regionId": "12192", - "keys": "0,0,0,0" - }, { "regionId": "12193", "keys": "1013552068,-364826455,4137749,729786125" }, - { - "regionId": "12194", - "keys": "0,0,0,0" - }, - { - "regionId": "12332", - "keys": "0,0,0,0" - }, { "regionId": "12333", "keys": "372281878,-809369100,-1989039261,-980074402" @@ -4112,54 +3260,18 @@ "regionId": "12356", "keys": "-1201681208,106398334,-2123418385,1010672418" }, - { - "regionId": "12362", - "keys": "0,0,0,0" - }, - { - "regionId": "12363", - "keys": "0,0,0,0" - }, - { - "regionId": "12364", - "keys": "0,0,0,0" - }, - { - "regionId": "12365", - "keys": "0,0,0,0" - }, - { - "regionId": "12366", - "keys": "0,0,0,0" - }, { "regionId": "12367", "keys": "-2006617355,-1390093250,-1950318553,1842364433" }, - { - "regionId": "12368", - "keys": "0,0,0,0" - }, { "regionId": "12369", "keys": "-891954120,1710352781,-1883639556,-1461026236" }, - { - "regionId": "12372", - "keys": "0,0,0,0" - }, - { - "regionId": "12373", - "keys": "0,0,0,0" - }, { "regionId": "12374", "keys": "1620519366,-1309341299,68411383,1308746010" }, - { - "regionId": "12375", - "keys": "0,0,0,0" - }, { "regionId": "12376", "keys": "1918934265,1530066885,-1991367516,1783839145" @@ -4204,38 +3316,10 @@ "regionId": "12442", "keys": "1883167946,191149821,-1270401415,-126025128" }, - { - "regionId": "12443", - "keys": "0,0,0,0" - }, { "regionId": "12444", "keys": "1576354846,-1768236409,821965805,-861456742" }, - { - "regionId": "12447", - "keys": "0,0,0,0" - }, - { - "regionId": "12448", - "keys": "0,0,0,0" - }, - { - "regionId": "12449", - "keys": "0,0,0,0" - }, - { - "regionId": "12450", - "keys": "0,0,0,0" - }, - { - "regionId": "12587", - "keys": "0,0,0,0" - }, - { - "regionId": "12588", - "keys": "0,0,0,0" - }, { "regionId": "12589", "keys": "1981659006,1591583400,1958084245,667979721" @@ -4324,10 +3408,6 @@ "regionId": "12614", "keys": "1621048325,1179863793,357058137,-1896311701" }, - { - "regionId": "12615", - "keys": "0,0,0,0" - }, { "regionId": "12616", "keys": "1951523008,-2131232747,-381301931,2007660709" @@ -4340,26 +3420,14 @@ "regionId": "12619", "keys": "1922733696,773456556,-1923866275,-1305839916" }, - { - "regionId": "12620", - "keys": "0,0,0,0" - }, { "regionId": "12621", "keys": "1619333755,-1869146576,77302288,-937694202" }, - { - "regionId": "12622", - "keys": "0,0,0,0" - }, { "regionId": "12623", "keys": "-369583241,545715110,-134871454,1404138108" }, - { - "regionId": "12624", - "keys": "0,0,0,0" - }, { "regionId": "12625", "keys": "-260562230,1208275247,436993278,30028881" @@ -4380,18 +3448,6 @@ "regionId": "12631", "keys": "693308333,-269450306,-924437218,309489139" }, - { - "regionId": "12632", - "keys": "0,0,0,0" - }, - { - "regionId": "12633", - "keys": "0,0,0,0" - }, - { - "regionId": "12634", - "keys": "0,0,0,0" - }, { "regionId": "12688", "keys": "1861636222,1638403446,-649444098,2131977195" @@ -4408,10 +3464,6 @@ "regionId": "12691", "keys": "-998717750,-178246764,973015517,-1732934591" }, - { - "regionId": "12692", - "keys": "0,0,0,0" - }, { "regionId": "12693", "keys": "1339198001,799729854,-750687990,1703141753" @@ -4420,10 +3472,6 @@ "regionId": "12694", "keys": "631068451,-510806123,2026757696,207332608" }, - { - "regionId": "12695", - "keys": "0,0,0,0" - }, { "regionId": "12696", "keys": "690970369,-466418236,-666391415,1091047140" @@ -4444,10 +3492,6 @@ "regionId": "12700", "keys": "-1802430094,1220107446,-1897971895,-1437873968" }, - { - "regionId": "12842", - "keys": "0,0,0,0" - }, { "regionId": "12843", "keys": "-203885401,22803731,234561826,140244374" @@ -4476,22 +3520,6 @@ "regionId": "12849", "keys": "183396243,-461663209,-212681663,-266126212" }, - { - "regionId": "12850", - "keys": "0,0,0,0" - }, - { - "regionId": "12851", - "keys": "0,0,0,0" - }, - { - "regionId": "12852", - "keys": "0,0,0,0" - }, - { - "regionId": "12853", - "keys": "0,0,0,0" - }, { "regionId": "12854", "keys": "-648789394,672092351,713515997,1153393095" @@ -4541,24 +3569,12 @@ "keys": "1462732309,395803116,803023666,-1139113006" }, { - "regionId": "12874", - "keys": "0,0,0,0" + "regionId": "12869", + "keys": "14881828,-6662814,58238456,146761213" }, { - "regionId": "12875", - "keys": "0,0,0,0" - }, - { - "regionId": "12876", - "keys": "0,0,0,0" - }, - { - "regionId": "12877", - "keys": "0,0,0,0" - }, - { - "regionId": "12878", - "keys": "0,0,0,0" + "regionId": "12870", + "keys": "14881828,-6662814,58238456,146761213" }, { "regionId": "12879", @@ -4636,10 +3652,6 @@ "regionId": "12956", "keys": "-1383918319,-1190517730,-1037058957,534994622" }, - { - "regionId": "13098", - "keys": "0,0,0,0" - }, { "regionId": "13099", "keys": "919393388,-1011543647,454982828,-809340931" @@ -4664,14 +3676,6 @@ "regionId": "13104", "keys": "-421493992,1381068261,1710426242,2142500778" }, - { - "regionId": "13105", - "keys": "0,0,0,0" - }, - { - "regionId": "13106", - "keys": "0,0,0,0" - }, { "regionId": "13107", "keys": "-1161498786,-880845643,1588242926,2124040528" @@ -4732,34 +3736,18 @@ "regionId": "13126", "keys": "1732039952,536833573,-81136437,1031070663" }, - { - "regionId": "13130", - "keys": "0,0,0,0" - }, { "regionId": "13131", "keys": "-1234145533,479347649,1835828804,1685593501" }, - { - "regionId": "13132", - "keys": "0,0,0,0" - }, { "regionId": "13133", "keys": "-1026003062,917176839,-84576515,-1037395862" }, - { - "regionId": "13134", - "keys": "0,0,0,0" - }, { "regionId": "13135", "keys": "425723212,580084357,1788364975,1608414630" }, - { - "regionId": "13136", - "keys": "0,0,0,0" - }, { "regionId": "13138", "keys": "14881828,-6662814,58238456,146761213" @@ -4800,10 +3788,6 @@ "regionId": "13203", "keys": "-1342258113,-2106603709,395365404,-973258459" }, - { - "regionId": "13204", - "keys": "0,0,0,0" - }, { "regionId": "13205", "keys": "1250202258,-2009534633,1981493488,10068968" @@ -4812,14 +3796,6 @@ "regionId": "13206", "keys": "1456157358,1036496685,-1478577110,-1039552689" }, - { - "regionId": "13207", - "keys": "0,0,0,0" - }, - { - "regionId": "13208", - "keys": "0,0,0,0" - }, { "regionId": "13209", "keys": "-441828435,-1834839387,-1652863357,1161715526" @@ -4928,30 +3904,10 @@ "regionId": "13387", "keys": "50769406,1445159687,1657343198,-1977600563" }, - { - "regionId": "13388", - "keys": "0,0,0,0" - }, - { - "regionId": "13389", - "keys": "0,0,0,0" - }, { "regionId": "13393", "keys": "14881828,-6662814,58238456,146761213" }, - { - "regionId": "13397", - "keys": "0,0,0,0" - }, - { - "regionId": "13398", - "keys": "0,0,0,0" - }, - { - "regionId": "13399", - "keys": "0,0,0,0" - }, { "regionId": "13456", "keys": "-476100316,-1682296770,133855524,112315923" @@ -4996,10 +3952,6 @@ "regionId": "13466", "keys": "-460228398,-76181685,2062962515,1167974062" }, - { - "regionId": "13467", - "keys": "0,0,0,0" - }, { "regionId": "13610", "keys": "-1259340500,2094890289,-1255134464,1578867778" @@ -5048,10 +4000,6 @@ "regionId": "13621", "keys": "-1291167236,-1205011126,-1949699235,1530879202" }, - { - "regionId": "13622", - "keys": "0,0,0,0" - }, { "regionId": "13623", "keys": "-1700397822,-1427942931,1638091118,438962861" @@ -5096,10 +4044,6 @@ "regionId": "13643", "keys": "1113875885,-236852397,193142585,-854043613" }, - { - "regionId": "13644", - "keys": "0,0,0,0" - }, { "regionId": "13650", "keys": "-1281992532,-252178835,-207196406,32900092" @@ -5112,10 +4056,6 @@ "regionId": "13713", "keys": "676853493,-1887443315,-998811191,1947183065" }, - { - "regionId": "13715", - "keys": "0,0,0,0" - }, { "regionId": "13716", "keys": "-913580283,340446282,893998558,589419388" @@ -5140,10 +4080,6 @@ "regionId": "13721", "keys": "-1188425330,1307846097,888707126,-1843934128" }, - { - "regionId": "13722", - "keys": "0,0,0,0" - }, { "regionId": "13723", "keys": "-310574621,110640497,1685108265,-1931806505" @@ -5160,18 +4096,6 @@ "regionId": "13868", "keys": "255205616,-1585903009,-1371243067,-264891948" }, - { - "regionId": "13869", - "keys": "0,0,0,0" - }, - { - "regionId": "13870", - "keys": "0,0,0,0" - }, - { - "regionId": "13871", - "keys": "0,0,0,0" - }, { "regionId": "13872", "keys": "-865041276,1374390842,-909885942,30088570" @@ -5196,10 +4120,6 @@ "regionId": "13877", "keys": "1498185652,2064367906,152992439,585271079" }, - { - "regionId": "13878", - "keys": "0,0,0,0" - }, { "regionId": "13879", "keys": "-2101514338,-1139447054,51825149,-512907347" @@ -5220,18 +4140,6 @@ "regionId": "13899", "keys": "-2117805741,-268051413,-733527930,471010998" }, - { - "regionId": "13900", - "keys": "0,0,0,0" - }, - { - "regionId": "13901", - "keys": "0,0,0,0" - }, - { - "regionId": "13902", - "keys": "0,0,0,0" - }, { "regionId": "13905", "keys": "14881828,-6662814,58238456,146761213" @@ -5240,18 +4148,10 @@ "regionId": "13968", "keys": "-620062336,-1110235330,-1095431209,-470716307" }, - { - "regionId": "13971", - "keys": "0,0,0,0" - }, { "regionId": "13972", "keys": "1266294685,1139088638,1514900183,-1389022839" }, - { - "regionId": "13973", - "keys": "0,0,0,0" - }, { "regionId": "13974", "keys": "1384510929,1857691725,-293821029,-1219099456" @@ -5280,10 +4180,6 @@ "regionId": "13980", "keys": "-12957944,-743456598,2041601862,618819565" }, - { - "regionId": "14127", - "keys": "0,0,0,0" - }, { "regionId": "14128", "keys": "1907787432,-241593923,1152767085,-541422403" @@ -5320,26 +4216,10 @@ "regionId": "14136", "keys": "-1104533465,1792124817,-1564247177,79706641" }, - { - "regionId": "14154", - "keys": "0,0,0,0" - }, - { - "regionId": "14155", - "keys": "0,0,0,0" - }, - { - "regionId": "14156", - "keys": "0,0,0,0" - }, { "regionId": "14157", "keys": "-852479713,1901063521,-1097484894,1013793379" }, - { - "regionId": "14158", - "keys": "0,0,0,0" - }, { "regionId": "14161", "keys": "14881828,-6662814,58238456,146761213" @@ -5348,18 +4228,6 @@ "regionId": "14167", "keys": "-1398455,-469478596,190482870,-1233173597" }, - { - "regionId": "14227", - "keys": "0,0,0,0" - }, - { - "regionId": "14228", - "keys": "0,0,0,0" - }, - { - "regionId": "14229", - "keys": "0,0,0,0" - }, { "regionId": "14230", "keys": "-453901412,-2074594443,-809419406,1774073603" @@ -5388,6 +4256,10 @@ "regionId": "14236", "keys": "816141215,-2114312227,1578950035,1471842311" }, + { + "regionId": "14380", + "keys": "1663518625,-107913441,-1625821936,330353351" + }, { "regionId": "14381", "keys": "-534048527,1614741928,-469012711,1064350100" @@ -5420,10 +4292,6 @@ "regionId": "14388", "keys": "2048238173,2003642395,1658667134,411519881" }, - { - "regionId": "14389", - "keys": "0,0,0,0" - }, { "regionId": "14390", "keys": "-1631704360,1281079278,-1549067757,-2034268623" @@ -5436,18 +4304,6 @@ "regionId": "14392", "keys": "993603906,-1477196579,593064486,166369140" }, - { - "regionId": "14412", - "keys": "0,0,0,0" - }, - { - "regionId": "14413", - "keys": "0,0,0,0" - }, - { - "regionId": "14414", - "keys": "0,0,0,0" - }, { "regionId": "14486", "keys": "-131982139,-1189975142,-1667401999,-1794787704" @@ -5456,14 +4312,6 @@ "regionId": "14487", "keys": "-330478679,11506767,395036194,-971774384" }, - { - "regionId": "14488", - "keys": "0,0,0,0" - }, - { - "regionId": "14489", - "keys": "0,0,0,0" - }, { "regionId": "14490", "keys": "1578682567,-1175551739,170259358,-1972709096" @@ -5476,6 +4324,10 @@ "regionId": "14492", "keys": "420310205,1004898846,889537686,13961361" }, + { + "regionId": "14636", + "keys": "-1554034534,-545576842,-416921234,1887723532" + }, { "regionId": "14637", "keys": "112774068,-1867270219,-442076728,-1436438131" @@ -5496,10 +4348,6 @@ "regionId": "14641", "keys": "-310201697,1724559662,90126688,-664432561" }, - { - "regionId": "14645", - "keys": "0,0,0,0" - }, { "regionId": "14646", "keys": "-2069357113,-2117603296,1620573021,-239596308" @@ -5512,10 +4360,6 @@ "regionId": "14648", "keys": "-1757352130,-1996516705,263017190,1647356258" }, - { - "regionId": "14745", - "keys": "0,0,0,0" - }, { "regionId": "14746", "keys": "2081288932,-143900986,-1978370486,-544919360" @@ -5548,10 +4392,6 @@ "regionId": "14896", "keys": "548765086,801664009,-1716752945,-1492954302" }, - { - "regionId": "14901", - "keys": "0,0,0,0" - }, { "regionId": "14902", "keys": "1158948283,-12013143,1242958376,-1265402384" @@ -5572,26 +4412,10 @@ "regionId": "14995", "keys": "958328498,239876404,608758325,933929091" }, - { - "regionId": "15001", - "keys": "0,0,0,0" - }, - { - "regionId": "15002", - "keys": "0,0,0,0" - }, - { - "regionId": "15003", - "keys": "0,0,0,0" - }, { "regionId": "15147", "keys": "-423978185,359589519,280220972,-1608470374" }, - { - "regionId": "15148", - "keys": "0,0,0,0" - }, { "regionId": "15149", "keys": "-1200628316,15132614,-465260385,-1525542932" diff --git a/Server/src/main/core/game/system/config/XteaParser.kt b/Server/src/main/core/game/system/config/XteaParser.kt index 6b7f81ad8..9eb4f569c 100644 --- a/Server/src/main/core/game/system/config/XteaParser.kt +++ b/Server/src/main/core/game/system/config/XteaParser.kt @@ -13,13 +13,9 @@ import kotlin.collections.HashMap class XteaParser { companion object{ val REGION_XTEA = HashMap() - val DEFAULT_REGION_KEYS = intArrayOf(14881828, -6662814, 58238456, 146761213) - fun getRegionXTEA(regionId: Int): IntArray? { //Uses the xtea's from the sql to unlock regions - - return REGION_XTEA[regionId] - - return DEFAULT_REGION_KEYS //This one grabs the keys from the SQL - // return DEFAULT_REGION_KEYS;//This one only uses the default keys at the top,{ 14881828, -6662814, 58238456, 146761213 }. Unsure why they chose these numbers. + private val DEFAULT_REGION_KEYS = intArrayOf(0, 0, 0, 0) + fun getRegionXTEA(regionId: Int): IntArray { //Uses the xtea's from the sql to unlock regions + return REGION_XTEA.getOrDefault(regionId, DEFAULT_REGION_KEYS) } } val parser = JSONParser() diff --git a/Server/src/main/core/net/packet/out/UpdateSceneGraph.java b/Server/src/main/core/net/packet/out/UpdateSceneGraph.java index 5601c6757..a93435b18 100644 --- a/Server/src/main/core/net/packet/out/UpdateSceneGraph.java +++ b/Server/src/main/core/net/packet/out/UpdateSceneGraph.java @@ -24,10 +24,7 @@ public final class UpdateSceneGraph implements OutgoingPacket for (int regionY = (player.getLocation().getRegionY() - 6) / 8; regionY <= ((player.getLocation().getRegionY() + 6) / 8); regionY++) { int[] keys = XteaParser.Companion.getRegionXTEA(regionX << 8 | regionY); for (int i = 0; i < 4; i++) { - if (keys != null) buffer.putIntB(keys[i]); - else - buffer.putIntB(0); } } } From df73f4a171fc4b8f25ce964afa2a04d97e5eb5f7 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Mon, 17 Feb 2025 10:40:27 +0000 Subject: [PATCH 233/306] Fixed child animations for the following NPCs: Boy (Witch's House quest) Kanel (Inside Gertrude house) Philop (Inside Gertrude house) Shilop (Gertrude's Cat quest) Wilough (Gertrude's Cat quest) --- .../recruitmentdrive/RecruitmentDrive.kt | 10 +-- .../quest/witchshouse/BoyDialoguePlugin.java | 26 ++++---- .../quest/seaslug/KennithDialogueFile.kt | 4 +- .../varrock/dialogue/KanelDialogue.java | 14 ++--- .../varrock/dialogue/PhilopDialogue.java | 15 +++-- .../varrock/dialogue/ShilopDialogue.java | 62 +++++++++---------- .../varrock/dialogue/WiloughDialogue.java | 62 +++++++++---------- .../varrock/quest/gertrude/GertrudesCat.java | 2 +- .../core/game/dialogue/FacialExpression.java | 26 +++++++- 9 files changed, 121 insertions(+), 100 deletions(-) diff --git a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt index f608fc923..709256772 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt +++ b/Server/src/main/content/region/asgarnia/falador/quest/recruitmentdrive/RecruitmentDrive.kt @@ -78,10 +78,12 @@ class RecruitmentDrive : Quest(Quests.RECRUITMENT_DRIVE, 103, 102, 1, 496, 0, 1, line(player, "Luckily, I was too smart to fall for any of their little tricks,", line++, true) line(player, "and passed the test with flying colours.", line++, true) } else if (stage >= 2) { - line(player, "I went to !!Falador Park??, and met a strange old man named", line++, false) - line(player, "!!Tiffy??.", line++, false) - line(player, "He sent me to a !!secret training ground??, where my wits", line++, false) - line(player, "were thoroughly tested.", line++, false) + // http://youtu.be/Otc7ATq3tik 4:17 - I guess this is why no one opens their quest log + line(player, "A man named !!Tiffy?? brought me !!here, to the secret training??", line++, false) + line(player, "!!grounds?? so that I could be tested for the job.", line++, false) + line++ + line(player, "I should !!work out?? what I am supposed to do to complete", line++, false) + line(player, "these rooms...", line++, false) } if (stage >= 4) { diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java index c4d254a64..2574498c4 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/BoyDialoguePlugin.java @@ -36,7 +36,7 @@ public class BoyDialoguePlugin extends DialoguePlugin { final Quest quest = player.getQuestRepository().getQuest(Quests.WITCHS_HOUSE); player.debug(quest.isStarted(player) + " " + quest.getStage(player) ); if (!quest.isStarted(player) && quest.getStage(player) < 10) { - player("Hello young man."); + player(FacialExpression.FRIENDLY, "Hello young man."); setStage(1); return true; } @@ -46,9 +46,9 @@ public class BoyDialoguePlugin extends DialoguePlugin { return true; } if (!player.getInventory().containsItem(BALL)) { - npc( FacialExpression.OLD_NORMAL, "Have you gotten my ball back yet?"); + npc( FacialExpression.CHILD_THINKING, "Have you gotten my ball back yet?"); } else { - player("Hi, I have got your ball back. It was MUCH harder", "than I thought it would be."); + player(FacialExpression.NEUTRAL, "Hi, I have got your ball back. It was MUCH harder", "than I thought it would be."); } setStage(11); return true; @@ -72,11 +72,11 @@ public class BoyDialoguePlugin extends DialoguePlugin { case 3: switch(buttonId) { case 1: - player("What's the matter?"); + player(FacialExpression.THINKING, "What's the matter?"); setStage(5); break; case 2: - player("Well if you're not going to answer then I'll go."); + player(FacialExpression.NEUTRAL, "Well if you're not going to answer then I'll go."); next(); break; } @@ -86,7 +86,7 @@ public class BoyDialoguePlugin extends DialoguePlugin { finish(); break; case 5: - npc(FacialExpression.OLD_NORMAL, "I've kicked my ball over that hedge, into that garden!", "The old lady who lives there is scary... She's locked the","ball in her wooden shed! Can you get my ball back for", "me please?"); + npc(FacialExpression.CHILD_SAD, "I've kicked my ball over that hedge, into that garden!", "The old lady who lives there is scary... She's locked the","ball in her wooden shed! Can you get my ball back for", "me please?"); next(); break; case 6: @@ -96,17 +96,17 @@ public class BoyDialoguePlugin extends DialoguePlugin { case 7: switch(buttonId) { case 1: - player("Ok, I'll see what I can do."); + player(FacialExpression.NEUTRAL, "Ok, I'll see what I can do."); setStage(10); break; case 2: - player("Get it back yourself."); + player(FacialExpression.NEUTRAL, "Get it back yourself."); next(); break; } break; case 8: - npc(FacialExpression.OLD_NORMAL, "You're a meany."); + npc(FacialExpression.CHILD_SAD, "You're a meany."); next(); break; case 9: @@ -114,13 +114,13 @@ public class BoyDialoguePlugin extends DialoguePlugin { finish(); break; case 10: - npc(FacialExpression.OLD_NORMAL, "Thanks mister!"); + npc(FacialExpression.CHILD_FRIENDLY, "Thanks mister!"); finish(); quest.start(player); break; case 11: if (!player.getInventory().containsItem(BALL)) { - player("Not yet."); + player(FacialExpression.NEUTRAL, "Not yet."); next(); } else { if (player.getInventory().remove(BALL)) @@ -129,11 +129,11 @@ public class BoyDialoguePlugin extends DialoguePlugin { } break; case 12: - npc(FacialExpression.OLD_NORMAL, "Well it's in the shed in that garden."); + npc(FacialExpression.CHILD_ANGRY, "Well it's in the shed in that garden."); finish(); break; case 13: - npc(FacialExpression.OLD_NORMAL, "Thank you so much!"); + npc(FacialExpression.CHILD_FRIENDLY, "Thank you so much!"); next(); break; case 14: diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt index dc4b76631..a12f2e9b8 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/KennithDialogueFile.kt @@ -30,9 +30,9 @@ class KennithDialogueFile : DialogueBuilderFile() { .playerl("Hello Kennith, are you okay?") .npcl(FacialExpression.CHILD_SAD, "No, I want my daddy.") .playerl("You'll be able to see him soon. First we need to get you back to land, come with me to the boat.") - .npcl(FacialExpression.CHILD_SHOCKED, "No!") + .npcl(FacialExpression.CHILD_SURPRISED, "No!") .playerl("What, why not?") - .npcl(FacialExpression.CHILD_SHOCKED, "I'm scared of those nasty sea slugs. I won't go near them.") + .npcl(FacialExpression.CHILD_SURPRISED, "I'm scared of those nasty sea slugs. I won't go near them.") .playerl("Okay, you wait here and I'll go figure another way to get you out.") .endWith() { df, player -> if(getQuestStage(player, Quests.SEA_SLUG) == 7) { diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/KanelDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/KanelDialogue.java index ce33e799b..4cf81e311 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/KanelDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/KanelDialogue.java @@ -7,13 +7,11 @@ import core.plugin.Initializable; import core.game.node.entity.player.Player; /** - * Represents the dialogue plugin used for kanel. - * @author 'Vexia - * @version 1.0 + * Kanel - Child in Gertrude's House */ @Initializable public final class KanelDialogue extends DialoguePlugin { - + // https://www.youtube.com/watch?v=ANI7DaRVEbg /** * Constructs a new {@code KanelDialogue} {@code Object}. */ @@ -39,7 +37,7 @@ public final class KanelDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there."); + interpreter.sendDialogues(player, FacialExpression.FRIENDLY, "Hello there."); stage = 0; return true; } @@ -49,15 +47,15 @@ public final class KanelDialogue extends DialoguePlugin { switch (stage) { case 0: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hel-lo?"); + interpreter.sendDialogues(npc, FacialExpression.CHILD_THINKING, "Hel-lo?"); stage = 1; break; case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Right. Goodbye."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Right. Goodbye."); stage = 2; break; case 2: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Bye?"); + interpreter.sendDialogues(npc, FacialExpression.CHILD_THINKING, "Bye?"); stage = 3; break; case 3: diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/PhilopDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/PhilopDialogue.java index 6d7afec28..9cf02f497 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/PhilopDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/PhilopDialogue.java @@ -7,12 +7,11 @@ import core.plugin.Initializable; import core.game.node.entity.player.Player; /** - * Handles the PhilopDialogue dialogue. - * @author 'Vexia + * Philop - Child in Gertrude's House */ @Initializable public class PhilopDialogue extends DialoguePlugin { - + // https://www.youtube.com/watch?v=ANI7DaRVEbg public PhilopDialogue() { } @@ -31,23 +30,23 @@ public class PhilopDialogue extends DialoguePlugin { switch (stage) { case 0: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Gwwrr!"); + interpreter.sendDialogues(npc, FacialExpression.CHILD_ANGRY, "Gwwrr!"); stage = 1; break; case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Err, hello there. What's that you have there?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Err, hello there. What's that you have there?"); stage = 2; break; case 2: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Gwwwrrr! Dwa-gon Gwwwwrrrr!"); + interpreter.sendDialogues(npc, FacialExpression.CHILD_ANGRY, "Gwwwrrr! Dwa-gon Gwwwwrrrr!"); stage = 3; break; case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Enjoy playing with your dragon, then."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Enjoy playing with your dragon, then."); stage = 4; break; case 4: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Gwwwrrr!"); + interpreter.sendDialogues(npc, FacialExpression.CHILD_ANGRY, "Gwwwrrr!"); stage = 5; break; case 5: diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java index ea1614e55..d17b6b329 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/ShilopDialogue.java @@ -59,22 +59,22 @@ public final class ShilopDialogue extends DialoguePlugin { final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (quest.getStage(player)) { case 0: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello again."); stage = 0; break; case 10: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there, I've been looking for you."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello there, I've been looking for you."); stage = 100; break; case 20: case 30: case 40: case 50: - interpreter.sendDialogues(player, null, "Where did you say you saw Fluffs?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Where did you say you saw Fluffs?"); stage = 130; break; default: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello again."); stage = 0; break; } @@ -86,23 +86,23 @@ public final class ShilopDialogue extends DialoguePlugin { final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 0: - interpreter.sendDialogues(id, FacialExpression.OLD_NORMAL, "You think you're tough do you?"); + interpreter.sendDialogues(id, FacialExpression.CHILD_ANGRY, "You think you're tough do you?"); stage = 1; break; case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Pardon?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Pardon?"); stage = 2; break; case 2: - interpreter.sendDialogues(id, FacialExpression.OLD_NORMAL, "I can beat anyone up!"); + interpreter.sendDialogues(id, FacialExpression.CHILD_ANGRY, "I can beat anyone up!"); stage = 3; break; case 3: - interpreter.sendDialogues(783, FacialExpression.OLD_NORMAL, "He can you know!"); + interpreter.sendDialogues(783, FacialExpression.CHILD_ANGRY, "He can you know!"); stage = 4; break; case 4: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Really?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Really?"); stage = 5; break; case 5: @@ -113,59 +113,59 @@ public final class ShilopDialogue extends DialoguePlugin { end(); break; case 100:// stage 10 - interpreter.sendDialogues(id, FacialExpression.OLD_NORMAL, "I didn't mean to take it! I just forgot to pay."); + interpreter.sendDialogues(id, FacialExpression.CHILD_SURPRISED, "I didn't mean to take it! I just forgot to pay."); stage = 101; break; case 101: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What? I'm trying to help your mum find Fluffs."); + interpreter.sendDialogues(player, FacialExpression.THINKING, "What? I'm trying to help your mum find Fluffs."); stage = 102; break; case 102: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "I might be able to help. Fluffs followed me to our secret", "play area and I haven't seen her since."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SIDE_EYE, "I might be able to help. Fluffs followed me to our secret", "play area and I haven't seen her since."); stage = 103; break; case 103: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Where is this play area?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Where is this play area?"); stage = 104; break; case 104: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "If I told you that, it wouldn't be a secret."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SIDE_EYE, "If I told you that, it wouldn't be a secret."); stage = 105; break; case 105: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What will make you tell me?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "What will make you tell me?"); stage = 106; break; case 106: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "Well...now you ask, I am a bit short on cash."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SUSPICIOUS, "Well...now you ask, I am a bit short on cash."); stage = 107; break; case 107: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How much?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "How much?"); stage = 108; break; case 108: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "10 coins."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SIDE_EYE, "10 coins."); stage = 109; break; case 109: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "10 coins?!"); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SURPRISED, "10 coins?!"); stage = 110; break; case 110: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "I'll handle this."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_NORMAL, "I'll handle this."); stage = 111; break; case 111: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "100 coins should cover it."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_FRIENDLY, "100 coins should cover it."); stage = 112; break; case 112: - interpreter.sendDialogues(player, null, "100 coins! Why should I pay you?"); + interpreter.sendDialogues(player, FacialExpression.ANGRY, "100 coins! Why should I pay you?"); stage = 113; break; case 113: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "You shouldn't, but we won't help otherwise. We never", "liked that cat anyway, so what do you say?"); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_NORMAL, "You shouldn't, but we won't help otherwise. We never", "liked that cat anyway, so what do you say?"); stage = 114; break; case 114: @@ -175,17 +175,17 @@ public final class ShilopDialogue extends DialoguePlugin { case 115: switch (buttonId) { case 1: - interpreter.sendDialogues(player, null, "I'm not paying you a penny."); + interpreter.sendDialogues(player, FacialExpression.ANGRY, "I'm not paying you a penny."); stage = 116; break; case 2: - interpreter.sendDialogues(player, null, "Okay then, I'll pay."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Okay then, I'll pay."); stage = 118; break; } break; case 116: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "Okay then, I'll find another way to make money."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SIDE_EYE, "Okay then, I'll find another way to make money."); stage = 117; break; case 117: @@ -207,26 +207,26 @@ public final class ShilopDialogue extends DialoguePlugin { quest.setStage(player, 20); break; case 119: - interpreter.sendDialogues(player, null, "There you go, now where did you see Fluffs?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "There you go, now where did you see Fluffs?"); stage = 120; break; case 120: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "We play at an abandoned lumber mill to the north east.", "Just beyond the Jolly Boar Inn. I saw Fluffs running", "around in there."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_NORMAL, "We play at an abandoned lumber mill to the north east.", "Just beyond the Jolly Boar Inn. I saw Fluffs running", "around in there."); stage = 121; break; case 121: - interpreter.sendDialogues(player, null, "Anything else?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Anything else?"); stage = 122; break; case 122: - interpreter.sendDialogues(id == 781 ? 783 : 781, null, "Well, you'll have to find the broken fence to get in. I'm", "sure you can manage that."); + interpreter.sendDialogues(id == 781 ? 783 : 781, FacialExpression.CHILD_SIDE_EYE, "Well, you'll have to find the broken fence to get in. I'm", "sure you can manage that."); stage = 123; break; case 123: end(); break; case 130: - interpreter.sendDialogues(id, null, "Weren't you listening? I saw the flea bag in the old", "lumber mill just north east of here. Just walk past the", "Jolly Boar Inn and you should find it."); + interpreter.sendDialogues(id, FacialExpression.CHILD_SIDE_EYE, "Weren't you listening? I saw the flea bag in the old", "lumber mill just north east of here. Just walk past the", "Jolly Boar Inn and you should find it."); stage = 131; break; case 131: diff --git a/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java b/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java index 61b1097c7..02deb3337 100644 --- a/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java +++ b/Server/src/main/content/region/misthalin/varrock/dialogue/WiloughDialogue.java @@ -59,22 +59,22 @@ public final class WiloughDialogue extends DialoguePlugin { final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (quest.getStage(player)) { case 0: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello again."); stage = 0; break; case 10: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there, I've been looking for you."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello there, I've been looking for you."); stage = 100; break; case 20: case 30: case 40: case 50: - interpreter.sendDialogues(player, null, "Where did you say you saw Fluffs?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Where did you say you saw Fluffs?"); stage = 130; break; default: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello again."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello again."); stage = 0; break; } @@ -86,23 +86,23 @@ public final class WiloughDialogue extends DialoguePlugin { final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT); switch (stage) { case 0: - interpreter.sendDialogues(id, FacialExpression.HALF_GUILTY, "You think you're tough do you?"); + interpreter.sendDialogues(id, FacialExpression.CHILD_ANGRY, "You think you're tough do you?"); stage = 1; break; case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Pardon?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Pardon?"); stage = 2; break; case 2: - interpreter.sendDialogues(id, FacialExpression.HALF_GUILTY, "I can beat anyone up!"); + interpreter.sendDialogues(id, FacialExpression.CHILD_ANGRY, "I can beat anyone up!"); stage = 3; break; case 3: - interpreter.sendDialogues(781, FacialExpression.HALF_GUILTY, "He can you know!"); + interpreter.sendDialogues(781, FacialExpression.CHILD_ANGRY, "He can you know!"); stage = 4; break; case 4: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Really?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Really?"); stage = 5; break; case 5: @@ -113,59 +113,59 @@ public final class WiloughDialogue extends DialoguePlugin { end(); break; case 100:// stage 10 - interpreter.sendDialogues(id, FacialExpression.HALF_GUILTY, "I didn't mean to take it! I just forgot to pay."); + interpreter.sendDialogues(id, FacialExpression.CHILD_SURPRISED, "I didn't mean to take it! I just forgot to pay."); stage = 101; break; case 101: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What? I'm trying to help your mum find Fluffs."); + interpreter.sendDialogues(player, FacialExpression.THINKING, "What? I'm trying to help your mum find Fluffs."); stage = 102; break; case 102: - interpreter.sendDialogues(id == 783 ? 781 : 783, null, "I might be able to help. Fluffs followed me to our secret", "play area and I haven't seen her since."); + interpreter.sendDialogues(id == 783 ? 781 : 783, FacialExpression.CHILD_SIDE_EYE, "Ohh...well, in that case I might be able to help. Fluffs", "followed me to my super secret hideout, I haven't seen", "her since. She's probably off eating small creatures", "somewhere."); stage = 103; break; case 103: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Where is this play area?"); + interpreter.sendDialogues(player, FacialExpression.THINKING, "Where is this secret hideout? I really need to find that", "cat for your mum."); stage = 104; break; case 104: - interpreter.sendDialogues(id == 783 ? 781 : 783, null, "If I told you that, it wouldn't be a secret."); + interpreter.sendDialogues(id == 783 ? 781 : 783, FacialExpression.CHILD_SIDE_EYE, "If I told you that, it wouldn't be a secret."); stage = 105; break; case 105: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What will make you tell me?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "What will make you tell me?"); stage = 106; break; case 106: - interpreter.sendDialogues(id == 783 ? 781 : 783, null, "Well...now you ask, I am a bit short on cash."); + interpreter.sendDialogues(id == 783 ? 781 : 783, FacialExpression.CHILD_SUSPICIOUS, "Well...now you ask, I am a bit short on cash."); stage = 107; break; case 107: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How much?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "How much?"); stage = 108; break; case 108: - interpreter.sendDialogues(id == 783 ? 781 : 783, null, "10 coins."); + interpreter.sendDialogues(id == 783 ? 781 : 783, FacialExpression.CHILD_SIDE_EYE, "10 coins."); stage = 109; break; case 109: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "10 coins?!"); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_SURPRISED, "10 coins?!"); stage = 110; break; case 110: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "I'll handle this."); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_NORMAL, "I'll handle this."); stage = 111; break; case 111: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "100 coins should cover it."); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_FRIENDLY, "100 coins should cover it."); stage = 112; break; case 112: - interpreter.sendDialogues(player, null, "100 coins! Why should I pay you?"); + interpreter.sendDialogues(player, FacialExpression.ANGRY, "100 coins! Why should I pay you?"); stage = 113; break; case 113: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "You shouldn't, but we won't help otherwise. We never", "liked that cat anyway, so what do you say?"); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_NORMAL, "You shouldn't, but we won't help otherwise. We never", "liked that cat anyway, so what do you say?"); stage = 114; break; case 114: @@ -175,17 +175,17 @@ public final class WiloughDialogue extends DialoguePlugin { case 115: switch (buttonId) { case 1: - interpreter.sendDialogues(player, null, "I'm not paying you a penny."); + interpreter.sendDialogues(player, FacialExpression.ANGRY, "I'm not paying you a penny."); stage = 116; break; case 2: - interpreter.sendDialogues(player, null, "Okay then, I'll pay."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Okay then, I'll pay."); stage = 118; break; } break; case 116: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "Okay then, I'll find another way to make money."); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_SIDE_EYE, "Okay then, I'll find another way to make money."); stage = 117; break; case 117: @@ -206,26 +206,26 @@ public final class WiloughDialogue extends DialoguePlugin { } break; case 119: - interpreter.sendDialogues(player, null, "There you go, now where did you see Fluffs?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "There you go, now where did you see Fluffs?"); stage = 120; break; case 120: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "We play at an abandoned lumber mill to the north east.", "Just beyond the Jolly Boar Inn. I saw Fluffs running", "around in there."); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_NORMAL, "We play at an abandoned lumber mill to the north east.", "Just beyond the Jolly Boar Inn. I saw Fluffs running", "around in there."); stage = 121; break; case 121: - interpreter.sendDialogues(player, null, "Anything else?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Anything else?"); stage = 122; break; case 122: - interpreter.sendDialogues(id == 783 ? 783 : id, null, "Well, you'll have to find the broken fence to get in. I'm", "sure you can manage that."); + interpreter.sendDialogues(id == 783 ? 783 : id, FacialExpression.CHILD_SIDE_EYE, "Well, you'll have to find the broken fence to get in. I'm", "sure you can manage that."); stage = 123; break; case 123: end(); break; case 130: - interpreter.sendDialogues(id, null, "Weren't you listening? I saw the flea bag in the old", "lumber mill just north east of here. Just walk past the", "Jolly Boar Inn and you should find it."); + interpreter.sendDialogues(id, FacialExpression.CHILD_SIDE_EYE, "Weren't you listening? I saw the flea bag in the old", "lumber mill just north east of here. Just walk past the", "Jolly Boar Inn and you should find it."); stage = 131; break; case 131: diff --git a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java index 31cd7bbc2..c4eb02518 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/gertrude/GertrudesCat.java @@ -82,7 +82,7 @@ public class GertrudesCat extends Quest { player.getPacketDispatch().sendString("1525 Cooking XP", 277, 10 + 2); player.getPacketDispatch().sendString("A chocolate cake", 277, 11 + 2); player.getPacketDispatch().sendString("A bowl of stew", 277, 12 + 2); - player.getPacketDispatch().sendString("Raise cats.", 277, 13 + 2); + player.getPacketDispatch().sendString("The ability to raise cats", 277, 13 + 2); player.getSkills().addExperience(Skills.COOKING, 1525); player.getPacketDispatch().sendItemZoomOnInterface(kitten.getId(), 240, 277, 3 + 2); setStage(player, 100); diff --git a/Server/src/main/core/game/dialogue/FacialExpression.java b/Server/src/main/core/game/dialogue/FacialExpression.java index 2d6277815..6d415cf0f 100644 --- a/Server/src/main/core/game/dialogue/FacialExpression.java +++ b/Server/src/main/core/game/dialogue/FacialExpression.java @@ -92,7 +92,7 @@ public enum FacialExpression { //Child Chathead? CHILD_ANGRY(7168), CHILD_SIDE_EYE(7169), - CHILD_THINKING_2(7170), + CHILD_RECALLING(7170), CHILD_EVIL_LAUGH(7171), CHILD_FRIENDLY(7172), CHILD_NORMAL(7173), @@ -102,8 +102,30 @@ public enum FacialExpression { CHILD_SAD(7177), CHILD_GUILTY(7178), CHILD_SUSPICIOUS(7179), - CHILD_SHOCKED(7180); //TODO: More? + CHILD_SURPRISED(7180), + ; //TODO: More? + + /* + * From some sources: here's a potential list of chatheads. + * // 667 + * Chat animation group: 1540; linked animations: [7, 8, 9, 6824] + * Chat animation group: 1489; linked animations: [225, 6550, 6551, 6552, 6553, 6555, 8372, 8373, 8374, 8375, 8581, 8582, 9178, 9179, 9180, 9181, 9183, 9187, 9189, 9190, 9192, 9202] + * Chat animation group: 82; linked animations: [554, 555, 556, 557, 562, 563, 564, 565, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 610, 611, 612, 613, 614, 615, 616, 617] + * Chat animation group: 84; linked animations: [558, 559, 560, 561] + * Chat animation group: 80; linked animations: [584, 585, 586, 587] + * Chat animation group: 78; linked animations: [3874] + * Chat animation group: 77; linked animations: [4119, 4120, 4121, 4122] + * Chat animation group: 1124; linked animations: [4843, 4844, 4845, 4846, 8388, 8389, 8390, 8391, 8392, 8393, 8394, 8403, 8404, 8405, 8406, 8898, 8899, 8900] + * Chat animation group: 1309; linked animations: [5661, 5662, 5663, 5665] + * Chat animation group: 1421; linked animations: [6244, 6245, 6246, 7636, 7637, 7638, 7639, 8380, 8381, 8382, 8383, 8475, 8476, 8477, 8478] + * Chat animation group: 1627; linked animations: [7168, 7169, 7170, 7171, 7172, 7173, 7176, 7177, 7178, 7179, 7180, 8824] + * Chat animation group: 1698; linked animations: [7539, 7540, 7541, 7542, 8447, 8448, 8449, 8450] + * Chat animation group: 1885; linked animations: [8395, 8396, 8397, 8398] + * Chat animation group: 1882; linked animations: [8411, 8412, 8413, 8414] + * Chat animation group: 1887; linked animations: [8443, 8444, 8445, 8446, 9315, 9316, 9317, 9318, 9319] + * Chat animation group: 1906; linked animations: [8579, 8580, 8583, 8584, 8585, 8656, 8657, 8659, 8660, 8661, 8662] + */ /** * The animation id. From 50ba3682b57eb9194ec42ff7a1bce947bbab8e9e Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Mon, 17 Feb 2025 10:42:19 +0000 Subject: [PATCH 234/306] Corrected fishing contest quest log Fixed dialogue after fishing contest --- .../quest/fishingcontest/DwarfDialogue.java | 10 ++-- .../quest/fishingcontest/FishingContest.java | 58 +++++++++++++------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java index 0fa32ac49..6e56d58e5 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/DwarfDialogue.java @@ -24,6 +24,11 @@ public class DwarfDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; int questStage = player.getQuestRepository().getStage(Quests.FISHING_CONTEST); + if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) == 100){ + npc(FacialExpression.OLD_NORMAL,"Welcome, oh great fishing champion!","Feel free to pop by and use","our tunnel any time!"); + stage = 2500; + return true; + } if((questStage < 20 && questStage > 0) && !player.getInventory().containsItem(FishingContest.FISHING_PASS)){ player("I lost my fishing pass..."); stage = 1000; @@ -39,11 +44,6 @@ public class DwarfDialogue extends DialoguePlugin { stage = 1500; return true; } - if(player.getQuestRepository().getStage(Quests.FISHING_CONTEST) == 100){ - npc(FacialExpression.OLD_NORMAL,"Welcome, oh great fishing champion!","Feel free to pop by and use","our tunnel any time!"); - stage = 2500; - return true; - } npc(FacialExpression.OLD_NORMAL,"Hmph! What do you want?"); stage = 0; return true; diff --git a/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java b/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java index f713482ae..9e01f552e 100644 --- a/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java +++ b/Server/src/main/content/region/kandarin/quest/fishingcontest/FishingContest.java @@ -19,27 +19,50 @@ public class FishingContest extends Quest { public static final Item GARLIC = new Item(1550); public static final Item SPADE = new Item(952); + // Winner is stranger in black if you did not do the garlic. + // https://www.youtube.com/watch?v=6zL7M8mCL30 @Override public void drawJournal(Player player, int stage) { - int line = 11; + int line = 12; super.drawJournal(player, stage); - if(stage < 10) { - line(player, "I can start this quest by trying to take the !!shortcut??", line++); - line(player, "near !!White Wolf Mountain??", line++); - line(player,"I need level !!10 Fishing?? to start this quest.",line++,player.getSkills().getLevel(Skills.FISHING) >= 10); - } else if (stage >= 10){ - line(player,"The !!mountain Dwarves' home?? would be an ideal way to get across ",line++,stage >= 20); - line(player,"White Wolf Mountain safely. However, the Dwarves aren't too",line++, stage >= 20); - line(player,"fond of strangers. They will let you through if you can !!bring ",line++, stage >= 20); - line(player,"!!them a trophy.?? The trophy is the prize for the annual Hemenster",line++,stage >= 20); - line(player,"!!fishing competition.??",line++,stage >= 20); - if(stage == 20) - line(player,"I should return to !!Austri?? or !!Vestri??.",line++); - if(stage >= 100){ - line(player,"%%QUEST COMPLETE!&&",line++); + if (stage == 0) { + line(player, "I can start this quest by speaking to the !!Dwarves?? at the", line++); + line(player, "tunnel entrances on either side of !!White Wolf Mountain??.", line++); + line(player,"!!I must have level 10 fishing.??", line++, player.getSkills().getLevel(Skills.FISHING) >= 10); + } else if ( stage < 100 ) { + line(player, "The Dwarves will let me use the tunnel through White Wolf", line++, true); + line(player, "Mountain if I can will the Hemenster Fishing Competition.", line++, true); + + if (stage >= 20) { + line(player,"I easily won the contest by catching some Giant Carp.", line++, false); + } else if (stage >= 10) { + // https://youtu.be/z4MfANC2KqI + line(player, "They gave me a !!Fishing Contest Pass?? to enter the contest.", line++, false); + line(player, "I need to bring them back the !!Hemenster Fishing Trophy??.", line++, false); } + + if (stage >= 100) { + + } else if (stage >= 20) { + // https://youtu.be/rysJl-DRihE + line(player, "I should take back the !!Trophy?? back to the !!Dwarf?? at the side of", line++, false); + line(player, "!!White Wolf Mountain?? and claim my !!reward??.", line++, false); + } + + } else { + // https://youtu.be/u5Osw_jas4A + line(player, "The Dwarves' wanted me to earn their friendship by winning", line++, true); + line(player, "the Hemenster Fishing Competition.", line++, true); + line(player, "I scared away a vampyre with some garlic and easily won the", line++, true); + line(player, "contest by catching some Giant Carp.", line++, true); + line++; + line(player,"%%QUEST COMPLETE!&&", line++); + line++; + line(player, "As a reward for getting the Fishing Competition Trophy the", line++, false); + line(player, "Dwarves will let me use their tunnel to travel quickly and", line++, false); + line(player, "safely under White Wolf Mountain anytime I wish.", line++, false); } } @@ -48,9 +71,10 @@ public class FishingContest extends Quest { int ln = 10; super.finish(player); player.getPacketDispatch().sendItemZoomOnInterface(FISHING_TROPHY.getId(), 230, 277, 5); + // https://youtu.be/8dK362LbYdE drawReward(player,"1 Quest Point",ln++); - drawReward(player,"2437 Fishing XP.",ln++); - drawReward(player,"Access to the White Wolf Mountain shortcut.",ln); + drawReward(player,"2437 Fishing XP",ln++); + drawReward(player,"Access to Tunnel shortcut",ln); player.removeAttribute("fishing_contest:garlic"); player.removeAttribute("fishing_contest:won"); player.removeAttribute("fishing_contest:pass-shown"); From 45fb89ec7391b5e2855ebf8bd2db5fa65e9d4de0 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 17 Feb 2025 10:44:44 +0000 Subject: [PATCH 235/306] Hostile random events now take the player's summoning level into account Random event combat level is now selected authentically resulting in more difficult hostile random events --- .../global/ame/events/evilchicken/EvilChickenNPC.kt | 6 ++---- .../global/ame/events/rivertroll/RiverTrollRENPC.kt | 7 ++----- .../content/global/ame/events/rockgolem/RockGolemRENPC.kt | 7 ++----- .../src/main/content/global/ame/events/shade/ShadeRENPC.kt | 4 +--- .../global/ame/events/treespirit/TreeSpiritRENPC.kt | 7 ++----- .../main/content/global/ame/events/zombie/ZombieRENPC.kt | 4 +--- 6 files changed, 10 insertions(+), 25 deletions(-) diff --git a/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt b/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt index ac26b914b..5b065f567 100644 --- a/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt +++ b/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt @@ -9,9 +9,8 @@ import core.tools.RandomFunction import org.rs09.consts.Items import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import java.lang.Integer.max -val ids = 2463..2468 +val ids = (2463..2468).toList() class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(2463) { val phrases = arrayOf("Bwuk","Bwuk bwuk bwuk","Flee from me, @name!","Begone, @name!","Bwaaaauuuk bwuk bwuk","MUAHAHAHAHAAA!") @@ -19,8 +18,7 @@ class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventN override fun init() { super.init() - val index = max(0, (player.properties.combatLevel / 20) - 1) - val id = ids.toList()[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat(phrases.random().replace("@name",player.username.capitalize())) diff --git a/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt b/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt index b69ec7abe..dff28d7e9 100644 --- a/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt +++ b/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt @@ -4,17 +4,14 @@ import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import java.lang.Integer.max - -val ids = 391..396 +val ids = (391..396).toList() class RiverTrollRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(391){ override fun talkTo(npc: NPC) {} override fun init() { super.init() - val index = max(0, (player.properties.combatLevel / 20) - 1) - val id = ids.toList()[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat("Fishies be mine, leave dem fishies!") diff --git a/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt b/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt index 82fda9bf4..eb3399657 100644 --- a/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt +++ b/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt @@ -4,17 +4,14 @@ import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import kotlin.math.max - -val ids = 413..418 +val ids = (413..418).toList() class RockGolemRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(413){ override fun talkTo(npc: NPC) {} override fun init() { super.init() - val index = max(0,(player.properties.combatLevel / 20) - 1) - val id = ids.toList()[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat("Raarrrgghh! Flee human!") diff --git a/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt b/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt index 4d991afdf..60a0f57ae 100644 --- a/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt +++ b/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt @@ -4,15 +4,13 @@ import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import kotlin.math.* class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(425){ val ids = (425..430).toList() override fun talkTo(npc: NPC) {} override fun init() { super.init() - val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1)) - val id = ids[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat("Leave this place!") diff --git a/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt b/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt index 2e4fb3436..3b0033972 100644 --- a/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt +++ b/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt @@ -4,17 +4,14 @@ import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import kotlin.math.max - -val ids = 438..443 +val ids = (438..443).toList() class TreeSpiritRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(438){ override fun talkTo(npc: NPC) {} override fun init() { super.init() - val index = max(0,(player.properties.combatLevel / 20) - 1) - val id = ids.toList()[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat("Leave these woods and never return!") diff --git a/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt b/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt index 230d85ee8..6b43d54b4 100644 --- a/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt +++ b/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt @@ -4,15 +4,13 @@ import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC import core.api.utils.WeightBasedTable -import kotlin.math.* class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(419){ val ids = (419..424).toList() override fun talkTo(npc: NPC) {} override fun init() { super.init() - val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1)) - val id = ids[index] + val id = idForCombatLevel(ids, player) this.transform(id) this.attack(player) sendChat("Brainsssss!") From fb9d6307b39e2a9eb440b87fb5436d5be03e3d77 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 18 Feb 2025 04:32:21 +0000 Subject: [PATCH 236/306] Corrected diamond bolts (e) effect Removed inauthentic Verac armour effect of +1 max hit increase --- .../node/entity/combat/CombatSwingHandler.kt | 11 ++++++-- .../node/entity/combat/MeleeSwingHandler.kt | 8 +++--- .../node/entity/combat/RangeSwingHandler.kt | 28 ++++++++++++++----- .../entity/combat/equipment/Ammunition.java | 6 ++-- .../entity/combat/equipment/BoltEffect.java | 18 ++---------- .../game/system/config/RangedConfigLoader.kt | 1 - 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt index 40df6d765..748e258d5 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt @@ -31,10 +31,14 @@ import kotlin.math.floor * Handles a combat swing. * @author Emperor * @author Ceikry - Kotlin refactoring, general cleanup + * @author Player Name - converted `flags` to ArrayList */ abstract class CombatSwingHandler(var type: CombatStyle?) { - var flags: Array = emptyArray() - constructor(type: CombatStyle?, vararg flags: SwingHandlerFlag) : this(type) { this.flags = flags } + var flags: ArrayList = ArrayList(SwingHandlerFlag.values().size) + constructor(type: CombatStyle?, vararg flags: SwingHandlerFlag) : this(type) { + this.flags = arrayListOf(*flags) + } + /** * The mapping of the special attack handlers. */ @@ -664,5 +668,6 @@ enum class SwingHandlerFlag { IGNORE_STAT_BOOSTS_DAMAGE, IGNORE_STAT_BOOSTS_ACCURACY, IGNORE_PRAYER_BOOSTS_DAMAGE, - IGNORE_PRAYER_BOOSTS_ACCURACY + IGNORE_PRAYER_BOOSTS_ACCURACY, + IGNORE_STAT_REDUCTION } diff --git a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt index c32a7567e..b58fe0c0c 100644 --- a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt @@ -64,16 +64,16 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) if (entity is Player) { state.weapon = Weapon(entity.equipment[3]) } - if (entity!!.properties.armourSet === ArmourSet.VERAC && RandomFunction.random(100) < 25) { + if (entity!!.properties.armourSet == ArmourSet.VERAC && RandomFunction.roll(4)) { state.armourEffect = ArmourSet.VERAC } - if (state.armourEffect === ArmourSet.VERAC || isAccurateImpact(entity, victim, CombatStyle.MELEE)) { + if (state.armourEffect == ArmourSet.VERAC || isAccurateImpact(entity, victim, CombatStyle.MELEE)) { var max = calculateHit(entity, victim, 1.0) if (victim != null) { - if (entity is NPC && state.armourEffect === ArmourSet.VERAC && victim.hasProtectionPrayer(CombatStyle.MELEE)) max = max * 2 / 3 + if (entity is NPC && state.armourEffect == ArmourSet.VERAC && victim.hasProtectionPrayer(CombatStyle.MELEE)) max = max * 2 / 3 } state.maximumHit = max - hit = RandomFunction.random(max + 1) + (if (entity is Player && state.armourEffect === ArmourSet.VERAC) 1 else 0) + hit = RandomFunction.random(max + 1) } state.estimatedHit = hit if(victim != null) { diff --git a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt index c0e20bf67..a197d8b9c 100644 --- a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt @@ -30,11 +30,10 @@ import kotlin.math.floor * @author Emperor * @author Ceikry, conversion to Kotlin + cleanup */ -open class RangeSwingHandler (vararg flags: SwingHandlerFlag) +open class RangeSwingHandler (vararg flags: SwingHandlerFlag) : CombatSwingHandler(CombatStyle.RANGE, *flags) { /** * Constructs a new `RangeSwingHandler` {@Code Object}. */ - : CombatSwingHandler(CombatStyle.RANGE, *flags) { override fun canSwing(entity: Entity, victim: Entity): InteractionType? { if (!isProjectileClipped(entity, victim, false)) { return InteractionType.NO_INTERACT @@ -75,8 +74,17 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) return -1 } var hit = 0 - if (isAccurateImpact(entity, victim, CombatStyle.RANGE)) { - val max = calculateHit(entity, victim, 1.0).also { if(entity?.name?.toLowerCase() == "test10") log(this::class.java, Log.FINE, "Damage: $it") } + val armourPierce = state.ammunition != null && state.ammunition.effect != null && state.ammunition.effect == BoltEffect.DIAMOND && state.ammunition.effect.canFire(state) + if (armourPierce || isAccurateImpact(entity, victim, CombatStyle.RANGE)) { + val max: Int + if (armourPierce) { + state.ammunition.effect.impact(state) + flags.add(SwingHandlerFlag.IGNORE_STAT_REDUCTION) + max = (calculateHit(entity, victim, 1.0) * 1.15).toInt() + flags.remove(SwingHandlerFlag.IGNORE_STAT_REDUCTION) + } else { + max = calculateHit(entity, victim, 1.0) + } state.maximumHit = max hit = RandomFunction.random(max + 1) } @@ -124,7 +132,7 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) if (state.ammunition != null && entity is Player) { val damage = state.ammunition.poisonDamage if (state.estimatedHit > 0 && damage > 8 && RandomFunction.random(10) < 4) { - applyPoison (victim, entity, damage) + applyPoison(victim, entity, damage) } } super.adjustBattleState(entity, victim, state) @@ -161,7 +169,7 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) } override fun impact(entity: Entity?, victim: Entity?, state: BattleState?) { - if (state!!.ammunition != null && state.ammunition.effect != null && state.ammunition.effect.canFire(state)) { + if (state!!.ammunition != null && state.ammunition.effect != null && state.ammunition.effect != BoltEffect.DIAMOND && state.ammunition.effect.canFire(state)) { state.ammunition.effect.impact(state) } val hit = state.estimatedHit @@ -220,7 +228,13 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) if(entity.equipment[EquipmentContainer.SLOT_WEAPON] != null && RangeWeapon.get(entity.equipment[EquipmentContainer.SLOT_WEAPON].id).ammunitionSlot != EquipmentContainer.SLOT_ARROWS && entity.equipment[EquipmentContainer.SLOT_ARROWS] != null) styleStrengthBonus -= entity.equipment[EquipmentContainer.SLOT_ARROWS].definition.getConfiguration(ItemConfigParser.BONUS)[14] var effectiveStrengthLevel = entity.skills.getLevel(Skills.RANGE).toDouble() - if(!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) + if (flags.contains(SwingHandlerFlag.IGNORE_STAT_REDUCTION)) { + val staticLevel = entity.skills.getStaticLevel(Skills.RANGE).toDouble() + if (staticLevel > effectiveStrengthLevel) { + effectiveStrengthLevel = staticLevel + } + } + if (!flags.contains(SwingHandlerFlag.IGNORE_PRAYER_BOOSTS_DAMAGE)) effectiveStrengthLevel = floor(effectiveStrengthLevel + (entity.prayer.getSkillBonus(Skills.RANGE) * effectiveStrengthLevel)) if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveStrengthLevel += 3 effectiveStrengthLevel += 8 diff --git a/Server/src/main/core/game/node/entity/combat/equipment/Ammunition.java b/Server/src/main/core/game/node/entity/combat/equipment/Ammunition.java index 33461f024..a7b895166 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/Ammunition.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/Ammunition.java @@ -74,7 +74,7 @@ public final class Ammunition { * Loads all the {@code Ammunition} info to the mapping. * @return {@code True}. */ - public static final boolean initialize() { + public static boolean initialize() { Document doc; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -141,7 +141,7 @@ public final class Ammunition { * @param id The ammo id. * @return The ammunition object. */ - public static final Ammunition get(int id) { + public static Ammunition get(int id) { return AMMUNITION.get(id); } @@ -189,7 +189,7 @@ public final class Ammunition { } /** - * Sets the baeffect. + * Sets the effect. * @param effect the effect to set. */ public void setEffect(BoltEffect effect) { diff --git a/Server/src/main/core/game/node/entity/combat/equipment/BoltEffect.java b/Server/src/main/core/game/node/entity/combat/equipment/BoltEffect.java index eabede5ff..7fb24f1a5 100644 --- a/Server/src/main/core/game/node/entity/combat/equipment/BoltEffect.java +++ b/Server/src/main/core/game/node/entity/combat/equipment/BoltEffect.java @@ -21,7 +21,6 @@ import static core.api.ContentAPIKt.*; */ public enum BoltEffect { OPAL(9236, Graphics.create(749), new Audio(2918)) { - @Override public void impact(BattleState state) { state.setEstimatedHit(state.getEstimatedHit() + RandomFunction.random(3, 20)); @@ -33,7 +32,6 @@ public enum BoltEffect { }, JADE(9237, new Graphics(755), new Audio(2916)) { - @Override public void impact(BattleState state) { if (state.getVictim() instanceof Player) { @@ -59,7 +57,6 @@ public enum BoltEffect { }, PEARL(9238, Graphics.create(750), new Audio(2920)) { - @Override public void impact(BattleState state) { state.setEstimatedHit(state.getEstimatedHit() + RandomFunction.random(3, 20)); @@ -108,12 +105,11 @@ public enum BoltEffect { EMERALD(9241, new Graphics(752), new Audio(2919)) { @Override public void impact(BattleState state) { - applyPoison(state.getVictim(), state.getAttacker(), 40); + applyPoison(state.getVictim(), state.getAttacker(), 40); super.impact(state); } }, RUBY(9242, new Graphics(754), new Audio(2911, 1)) { // in this case, volume is the number of times to play the sound... - @Override public void impact(BattleState state) { // hit target for 20% of their HP, hit self for 10% of HP int victimPoints = (int) (state.getVictim().getSkills().getLifepoints() * 0.20); @@ -135,15 +131,8 @@ public enum BoltEffect { return super.canFire(state) && state.getAttacker().getSkills().getLifepoints() - playerPoints >= 1; } }, - DIAMOND(9243, new Graphics(758), new Audio(2913)) { - @Override - public void impact(BattleState state) { - state.setEstimatedHit(state.getEstimatedHit() + RandomFunction.random(5, 14)); // unauthentic, needs fixing - super.impact(state); - } - }, + DIAMOND(9243, new Graphics(758), new Audio(2913)) { /* handled in RangeSwingHandler.kt::swing(entity: Entity?, victim: Entity?, state: BattleState?) */ }, DRAGON(9244, new Graphics(756), new Audio(2915)) { - @Override public void impact(BattleState state) { state.setEstimatedHit(state.getEstimatedHit() + RandomFunction.random(17, 29)); @@ -165,10 +154,8 @@ public enum BoltEffect { } return super.canFire(state); } - }, ONYX(9245, new Graphics(753), new Audio(2917)) { - @Override public void impact(BattleState state) { int newDamage = (int) (state.getEstimatedHit() * 0.25); @@ -270,5 +257,4 @@ public enum BoltEffect { public int getItemId() { return itemId; } - } diff --git a/Server/src/main/core/game/system/config/RangedConfigLoader.kt b/Server/src/main/core/game/system/config/RangedConfigLoader.kt index 41a85f4b3..6c54cbd55 100644 --- a/Server/src/main/core/game/system/config/RangedConfigLoader.kt +++ b/Server/src/main/core/game/system/config/RangedConfigLoader.kt @@ -8,7 +8,6 @@ import core.game.node.entity.combat.equipment.BoltEffect import core.game.node.entity.combat.equipment.RangeWeapon import core.game.node.entity.impl.Projectile import core.game.node.entity.npc.NPC -import core.tools.SystemLogger import core.game.world.map.Location import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Graphics From d65a53b27552436137b7fb805b49e65166a21b53 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 18 Feb 2025 06:03:18 +0000 Subject: [PATCH 237/306] Fixed loss of equippable items when swapped with another item that is dropped in the same tick --- .../core/game/global/action/DropListener.kt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Server/src/main/core/game/global/action/DropListener.kt b/Server/src/main/core/game/global/action/DropListener.kt index f6ec5b934..254b582ff 100644 --- a/Server/src/main/core/game/global/action/DropListener.kt +++ b/Server/src/main/core/game/global/action/DropListener.kt @@ -12,6 +12,8 @@ import core.game.node.item.GroundItemManager import core.game.node.item.Item import core.game.system.config.ItemConfigParser import content.global.skill.summoning.pet.Pets +import core.game.node.entity.player.info.LogType +import core.game.node.entity.player.info.PlayerMonitor import org.rs09.consts.Items import org.rs09.consts.Sounds @@ -33,7 +35,7 @@ class DropListener : InteractionListener { } private fun handleDropAction(player: Player, node: Node) : Boolean { val option = getUsedOption(player) - var item = node as? Item ?: return false + val item = node as? Item ?: return false if (option == "drop") { if (Pets.forId(item.id) != null) { player.familiarManager.summon(item, true, true) @@ -43,12 +45,21 @@ class DropListener : InteractionListener { sendMessage(player, "You cannot drop items on top of graves!") return false } - if (getAttribute(player, "equipLock:${node.id}", 0 ) > getWorldTicks()) + if (player.locks.equipmentLock != null) { return false + } closeAllInterfaces(player) - queueScript (player, strength = QueueStrength.SOFT) { - if (player.inventory.replace(null, item.slot) != item) return@queueScript stopExecuting(player) + queueScript(player, strength = QueueStrength.SOFT) { //do this as a script to allow dropping multiple items in the same tick (authentic) + // It's possible for state to change between queueing the script and executing it at the end of the tick (https://forum.2009scape.org/viewtopic.php?f=8&t=1195-lost-bandos-chestplate-whilst-making-iron-titans&p=5292). So, sanity check: + val current = player.inventory.get(item.slot) + if (current == null || current !== item) { + return@queueScript stopExecuting(player) + } + if (player.inventory.replace(null, item.slot) !== item) { + PlayerMonitor.log(player, LogType.DUPE_ALERT, "Potential exploit attempt when player ${player.name} tried to drop ${item.amount}x ${item.id}. The item has been lost and will need to be refunded to the player, but how did they get this to happen?") + return@queueScript stopExecuting(player) + } val droppedItem = item.dropItem if (droppedItem.id == Items.COINS_995) playAudio(player, DROP_COINS_SOUND) else playAudio(player, DROP_ITEM_SOUND) GroundItemManager.create(droppedItem, player.location, player) From cf08e700fbdc3248b8528c9d980cdf1c257b6194 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 18 Feb 2025 06:24:14 +0000 Subject: [PATCH 238/306] Runecrafting pouches now synchronise across bank instances BoB can no longer be used to smuggle weapons to Entrana --- .../content/global/skill/runecrafting/PouchManager.kt | 4 ++-- .../skill/runecrafting/abyss/DarkMageDialogue.java | 11 +++-------- Server/src/main/core/api/ContentAPI.kt | 11 +++++++++-- .../src/main/core/cache/def/impl/ItemDefinition.java | 9 +++++++-- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt index 087478bfc..22cc1865f 100644 --- a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt +++ b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt @@ -75,11 +75,11 @@ class PouchManager(val player: Player) { pouch.currentCap = pouch.capacity pouch.charges = pouch.maxCharges pouch.remakeContainer() + replaceAllItems(player, itemId, itemId - 1) //in case the player had more copies } } else { if (!isDecayedPouch(itemId)) { - val slot = player.inventory.getSlot(Item(itemId)) - replaceSlot(player, slot, Item(itemId + 1)) + replaceAllItems(player, itemId, itemId + 1) } sendMessage(player, "Your pouch has decayed through use.") //https://www.youtube.com/watch?v=FUcPYrgPUlQ pouch.charges = 9 * pouch.currentCap //implied by multiple contemporaneous sources, quantified only by https://oldschool.runescape.wiki/w/Large_pouch diff --git a/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java b/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java index 0348f19c8..a7b6450cd 100644 --- a/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java +++ b/Server/src/main/content/global/skill/runecrafting/abyss/DarkMageDialogue.java @@ -6,6 +6,8 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import org.rs09.consts.Items; +import static core.api.ContentAPIKt.replaceAllItems; + /** * Handles the dark mages dialogue. * @author Vexia @@ -153,14 +155,7 @@ public final class DarkMageDialogue extends DialoguePlugin { pouch.getContainer().add(essItem); } if (id != Items.SMALL_POUCH_5509) { - if (player.getInventory().contains(id + 1, 1)) { - player.getInventory().remove(new Item(id + 1, 1)); - player.getInventory().add(new Item(id, 1)); - } - if (player.getBank().contains(id + 1, 1)) { - player.getBank().remove(new Item(id + 1, 1)); - player.getBank().add(new Item(id, 1)); - } + replaceAllItems(player, id + 1, id); } }); return true; diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 0f1bae085..f11ca49ac 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -408,14 +408,21 @@ fun replaceSlot(player: Player, slot: Int, item: Item, currentItem: Item? = null */ fun replaceAllItems(player: Player, itemId: Int, replaceId: Int) { val item = Item(itemId) - for (container in arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary)) { + val containers = if (player.familiarManager.hasFamiliar() && player.familiarManager.familiar.isBurdenBeast()) { + arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary, (player.familiarManager.familiar as BurdenBeast).container) + } else { + arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary) + } + for (container in containers) { val hasItems = container.getAll(item) - if (!item.definition.isStackable && (container == player.inventory || container == player.equipment)) { + if (!item.definition.isStackable && container != player.bankPrimary && container != player.bankSecondary) { + // just replace for (target in hasItems) { val newItem = Item(replaceId, target.amount) container.replace(newItem, target.slot, true) } } else { + // add to existing stack if possible if (hasItems.size > 0) { val target = hasItems[0] var count = 0 diff --git a/Server/src/main/core/cache/def/impl/ItemDefinition.java b/Server/src/main/core/cache/def/impl/ItemDefinition.java index 6935833f6..0474e11f8 100644 --- a/Server/src/main/core/cache/def/impl/ItemDefinition.java +++ b/Server/src/main/core/cache/def/impl/ItemDefinition.java @@ -605,8 +605,13 @@ public class ItemDefinition extends Definition { * @return {@code True} if so. */ public static boolean canEnterEntrana(Player player) { - Container[] container = new Container[] { player.getInventory(), player.getEquipment() }; - for (Container c : container) { + Container[] containers; + if (player.getFamiliarManager().hasFamiliar() && player.getFamiliarManager().getFamiliar().isBurdenBeast()) { + containers = new Container[] { player.getInventory(), player.getEquipment(), ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer() }; + } else { + containers = new Container[] { player.getInventory(), player.getEquipment() }; + } + for (Container c : containers) { for (Item i : c.toArray()) { if (i == null) { continue; From 74ed5e1beecba4b1bdc729de6c45ca5cc397d112 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Wed, 19 Feb 2025 07:29:26 +0000 Subject: [PATCH 239/306] Fixed bug where swamp tar interactions could steal an entire stack --- .../kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt index 62d8ceb11..79a1b10ab 100644 --- a/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt +++ b/Server/src/main/content/region/kandarin/witchhaven/quest/seaslug/SeaSlugListeners.kt @@ -9,6 +9,7 @@ import core.game.interaction.QueueStrength import core.game.node.entity.combat.ImpactHandler import core.game.node.entity.combat.ImpactHandler.HitsplatType import core.game.node.entity.player.Player +import core.game.node.item.Item import core.game.world.map.Location import org.rs09.consts.Components import org.rs09.consts.Items @@ -76,7 +77,8 @@ class SeaSlugListeners : InteractionListener { // Your torch goes out on the crossing. onUseWith(IntType.ITEM, Items.SWAMP_TAR_1939, Items.POT_OF_FLOUR_1933){ player, used, with -> - if(removeItem(player, used) && removeItem(player, with)) { + val toRemove = Item(used.id, 1, used.asItem().slot) + if(removeItem(player, toRemove) && removeItem(player, with)) { sendMessage(player, "You mix the flour with the swamp tar.") sendMessage(player, "It mixes into a paste.") addItemOrDrop(player, Items.EMPTY_POT_1931) @@ -88,7 +90,8 @@ class SeaSlugListeners : InteractionListener { // You can only cook it using firewood. // sendMessage(player, "You can't cook that in a range.") onUseWith(SCENERY, Items.RAW_SWAMP_PASTE_1940, Scenery.FIRE_2732) { player, used, with -> - if(removeItem(player, used)) { + val toRemove = Item(used.id, 1, used.asItem().slot) + if(removeItem(player, toRemove)) { sendMessage(player, "You warm the paste over the fire. It thickens into a sticky goo.") addItemOrDrop(player, Items.SWAMP_PASTE_1941) } From af58fae1fcff8488efca3a62bf6b8315b76b6218 Mon Sep 17 00:00:00 2001 From: Player Name Date: Wed, 19 Feb 2025 07:30:51 +0000 Subject: [PATCH 240/306] Corrected Biohazard requirements check when using West Ardougne's eastern gates --- .../ardougne/westardougne/handlers/MainGatesListener.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt index b76f5ac83..82a8cd5e3 100644 --- a/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt +++ b/Server/src/main/content/region/kandarin/ardougne/westardougne/handlers/MainGatesListener.kt @@ -13,7 +13,7 @@ class MainGatesListener : InteractionListener { override fun defineListeners() { on(intArrayOf(Scenery.ARDOUGNE_WALL_DOOR_9738, Scenery.ARDOUGNE_WALL_DOOR_9330), IntType.SCENERY, "open") { player, node -> - if (isQuestComplete(player, Quests.BIOHAZARD)) { + if (hasRequirement(player, Quests.BIOHAZARD)) { DoorActionHandler.handleAutowalkDoor(player, node.asScenery()) } else if(inBorders(player, 2556, 3298, 2557, 3301)){ lock(player,2) From 0e65f202235e2f805fe0d96ca6c66e530919f565 Mon Sep 17 00:00:00 2001 From: Player Name Date: Wed, 19 Feb 2025 07:31:29 +0000 Subject: [PATCH 241/306] Fixed another softlock in The Fremennik Trials --- .../quest/thefremenniktrials/TFTInteractionListeners.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt index 4005844f9..51331c124 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt @@ -213,7 +213,9 @@ class TFTInteractionListeners : InteractionListener { on(SWENSEN_LADDER, IntType.SCENERY, "climb-down") { player, _ -> if (!getAttribute(player,"fremtrials:swensen-accepted",false)) { sendNPCDialogue(player,1283,"Where do you think you're going?", core.game.dialogue.FacialExpression.ANGRY) + return@on true } + core.game.global.action.ClimbActionHandler.climb(player, Animation(828), Location.create(2631, 10006, 0)) return@on true } From f0ee476e42ad558c018dfb58a4765a2955364065 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Wed, 19 Feb 2025 07:33:42 +0000 Subject: [PATCH 242/306] Fixed pyramid spawns not despawning Relaxed getting thrown out of the pyramid to rates that appear more authentic --- .../desert/quest/deserttreasure/MummyNPC.kt | 18 +++++ .../quest/deserttreasure/PyramidArea.kt | 73 ++++++++++--------- .../desert/quest/deserttreasure/ScarabNPC.kt | 18 +++++ 3 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/MummyNPC.kt create mode 100644 Server/src/main/content/region/desert/quest/deserttreasure/ScarabNPC.kt diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/MummyNPC.kt b/Server/src/main/content/region/desert/quest/deserttreasure/MummyNPC.kt new file mode 100644 index 000000000..d5fed9d6e --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/MummyNPC.kt @@ -0,0 +1,18 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import org.rs09.consts.NPCs + +class MummyNPC : NPCBehavior(NPCs.MUMMY_1958) { + var clearTime = 0 + + override fun tick(self: NPC): Boolean { + if (clearTime++ > 100) { + clearTime = 0 + poofClear(self) + } + return true + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt b/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt index ab45baf12..2a28610b2 100644 --- a/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt +++ b/Server/src/main/content/region/desert/quest/deserttreasure/PyramidArea.kt @@ -109,7 +109,7 @@ class PyramidArea { Location(3259, 9313, 0), ) - val safeZone = ZoneBorders(3227, 3239, 9310, 9320) + val safeZone = ZoneBorders(3227, 9310, 3239, 9320) // Direction.NORTH - LEFT // rot 0 - LEFT @@ -150,12 +150,15 @@ class PyramidArea { /** Trapdoor randomly throws you out of the Pyramid. */ fun trapdoorTrap(player: Player) { stopWalk(player) + player.walkingQueue.reset() + forceWalk(player, Location(3233, 2887, 0), "") lock(player, 8) sendMessage(player, "You accidentally trigger a trap...") // addScenery(6521, location) -> animateScenery(scenery, 1939), but 6522 does it for you. val pitfallScenery = addScenery(6522, player.location) // Scenery - Trapdoor Scenery animate(player, 1950) // Anim - Player Falling Animation queueScript(player, 4, QueueStrength.SOFT) { stage -> + player.walkingQueue.reset() when (stage) { 0 -> { sendGraphics(354, player.location) // Gfx - Puff of Smoke @@ -169,7 +172,14 @@ class PyramidArea { sendMessage(player, "...and tumble unharmed outside the pyramid.") closeOverlay(player) openOverlay(player, Components.FADE_FROM_BLACK_170) + stopWalk(player) + player.walkingQueue.reset() // animate(player, ??) // Anim - Player Getting Up https://www.youtube.com/watch?v=95OvIPFYCwg + return@queueScript delayScript(player, 3) + } + 2 -> { + player.walkingQueue.reset() + forceWalk(player, Location(3233, 2887, 0), "") return@queueScript stopExecuting(player) } else -> return@queueScript stopExecuting(player) @@ -179,8 +189,6 @@ class PyramidArea { /** Mummies randomly spawns out of a sarcophagus. */ fun spawnMummy(player: Player, sarcophagusLocation: Location) { - stopWalk(player) - lock(player, 3) val sarcophagusScenery = getScenery(sarcophagusLocation) ?: return val locationInFront = sarcophagusScenery.location.transform(getNewLocation(sarcophagusScenery.direction)) // There are 6 sarcophagus, 6512 - 6517 with different door designs. @@ -201,6 +209,7 @@ class PyramidArea { mummyNpc.init() mummyNpc.walkingQueue.addPath(locationInFront.x, locationInFront.y) sendChat(mummyNpc, "Rawr!") + lock(player, 1) stopWalk(player) queueScript(player, 2, QueueStrength.SOFT) { stage -> stopWalk(player) @@ -252,34 +261,30 @@ class PyramidAreaFirstThree: MapArea { getRegionBorders(11597), getRegionBorders(11341), getRegionBorders(11085), - getRegionBorders(12945), ) } override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { if (entity is Player) { + val averageLevel = ( + getDynLevel(entity, Skills.AGILITY) + + getDynLevel(entity, Skills.THIEVING) + ) / 2.0 + val randomValue = RandomFunction.randomDouble(99.5) - if (!PyramidArea.safeZone.insideBorder(entity.location)) { // Safezone is talking to Azzanadra. - val averageLevel = ( - getDynLevel(entity, Skills.AGILITY) + - getDynLevel(entity, Skills.THIEVING) - ) / 2 - val randomValue = RandomFunction.randomDouble(99.5) + if ((1..20).random() == 1) { + // A mummy would jump out if you walk near a sarcophagus of 2 radius. + val sarcoph = PyramidArea.nearSarcophagus(entity.location) + if (sarcoph != null) { + PyramidArea.spawnMummy(entity, sarcoph) + } + } - if ((1..10).random() == 1) { - // A mummy would jump out if you walk near a sarcophagus of 2 radius. - val sarcoph = PyramidArea.nearSarcophagus(entity.location) - if (sarcoph != null) { - PyramidArea.spawnMummy(entity, sarcoph) - } - } - - if ((1..60).random() == 1) { - PyramidArea.spawnScarabs(entity) - } - if (randomValue > averageLevel) { - PyramidArea.trapdoorTrap(entity) - } + if ((1..80).random() == 2) { + PyramidArea.spawnScarabs(entity) + } + if (randomValue > averageLevel && (1..128).random() == 1) { + PyramidArea.trapdoorTrap(entity) } } } @@ -295,16 +300,16 @@ class PyramidAreaFinal: MapArea { override fun entityStep(entity: Entity, location: Location, lastLocation: Location) { if (entity is Player) { - - if ((1..30).random() == 1) { - PyramidArea.spawnScarabs(entity) - } - - if ((1..15).random() == 1) { - // A mummy would jump out if you walk near a sarcophagus of 2 radius. - val sarcoph = PyramidArea.nearSarcophagus(entity.location) - if (sarcoph != null) { - PyramidArea.spawnMummy(entity, sarcoph) + if (!PyramidArea.safeZone.insideBorder(entity.location)) { // Safezone is talking to Azzanadra. + if ((1..20).random() == 1) { + // A mummy would jump out if you walk near a sarcophagus of 2 radius. + val sarcoph = PyramidArea.nearSarcophagus(entity.location) + if (sarcoph != null) { + PyramidArea.spawnMummy(entity, sarcoph) + } + } + if ((1..80).random() == 2) { + PyramidArea.spawnScarabs(entity) } } diff --git a/Server/src/main/content/region/desert/quest/deserttreasure/ScarabNPC.kt b/Server/src/main/content/region/desert/quest/deserttreasure/ScarabNPC.kt new file mode 100644 index 000000000..93dd60d7b --- /dev/null +++ b/Server/src/main/content/region/desert/quest/deserttreasure/ScarabNPC.kt @@ -0,0 +1,18 @@ +package content.region.desert.quest.deserttreasure + +import core.api.* +import core.game.node.entity.npc.NPC +import core.game.node.entity.npc.NPCBehavior +import org.rs09.consts.NPCs + +class ScarabNPC : NPCBehavior(NPCs.SCARABS_1969) { + var clearTime = 0 + + override fun tick(self: NPC): Boolean { + if (clearTime++ > 100) { + clearTime = 0 + poofClear(self) + } + return true + } +} \ No newline at end of file From 6362eee75304788f8de3d94e156470d4907cd95e Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Thu, 20 Feb 2025 10:53:59 +0000 Subject: [PATCH 243/306] Can now recover your digsite trowel from the examiner --- .../misthalin/digsite/dialogue/ExaminerDialogue.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt b/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt index f97b20425..d9f94dfba 100644 --- a/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt +++ b/Server/src/main/content/region/misthalin/digsite/dialogue/ExaminerDialogue.kt @@ -45,7 +45,18 @@ class ExaminerDialogueFile : DialogueBuilderFile() { } b.onQuestStages(Quests.THE_DIG_SITE, 6, 7, 8, 9, 10, 11, 12) - .npcl(FacialExpression.FRIENDLY, "Well, what are you doing here? Get digging!") + .branch { player -> if(inInventory(player, Items.TROWEL_676)) { 0 } else { 1 } } + .let{ branch -> + branch.onValue(0) + .npcl(FacialExpression.FRIENDLY, "Well, what are you doing here? Get digging!") + .end() + branch.onValue(1) + .playerl("I have lost my trowel.") + .npcl("Deary me. That was a good one as well. It's a good job I have another. Here you go...") + .endWith { _, player -> + addItemOrDrop(player, Items.TROWEL_676) + } + } b.onQuestStages(Quests.THE_DIG_SITE, 5) .playerl(FacialExpression.FRIENDLY, "Hello.") From 83b8689b8618524cae9d8468fd3001b534d58410 Mon Sep 17 00:00:00 2001 From: Oven Bread Date: Sun, 23 Feb 2025 04:02:11 +0000 Subject: [PATCH 244/306] Corrected quizmaster lamp reward --- .../global/ame/events/quizmaster/QuizMasterDialogueFile.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt index 3796fac17..4790a8550 100644 --- a/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt +++ b/Server/src/main/content/global/ame/events/quizmaster/QuizMasterDialogueFile.kt @@ -58,7 +58,7 @@ class QuizMasterDialogueFile : DialogueFile() { // Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas. val tableRoll = WeightBasedTable.create( - WeightedItem(Items.LAMP_6796, 1, 1, 1.0, false), + WeightedItem(Items.LAMP_2528, 1, 1, 1.0, false), WeightedItem(Items.CABBAGE_1965, 1, 1, 1.0, false), WeightedItem(Items.DIAMOND_1601, 1, 1, 1.0, false), WeightedItem(Items.BUCKET_1925, 1, 1, 1.0, false), From 448f970c10bd1ea869beb801df72ab7cf92de5de Mon Sep 17 00:00:00 2001 From: Kennynes Date: Sun, 23 Feb 2025 13:13:47 +0000 Subject: [PATCH 245/306] Fixed wrong door used in heroes' quest --- Server/data/configs/door_configs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/data/configs/door_configs.json b/Server/data/configs/door_configs.json index 9608881e7..ec17288a2 100644 --- a/Server/data/configs/door_configs.json +++ b/Server/data/configs/door_configs.json @@ -312,7 +312,7 @@ "metal": "false" }, { - "id": "2036", + "id": "1530", "replaceId": "1531", "fence": "false", "metal": "false" From 249c501184147b08408445bbf479e798cff1a44a Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 24 Feb 2025 20:44:17 -0700 Subject: [PATCH 246/306] Squashed commit of the following: commit 3177468c3261b783bdab2486e939121d7d28bff3 Author: randy Date: Mon Feb 24 20:35:53 2025 -0700 Final touches on teleorb commit e7b41fbf509150ef489ab2644e55b0d5baaec638 Author: randy Date: Mon Feb 24 19:22:04 2025 -0700 Added new teleorb file commit f99da5b28817ab5b03fe0506f0e9442d463381a8 Author: randy Date: Mon Feb 24 19:20:56 2025 -0700 Implemented Strange Teleorb as a custom teleport item Implemented Strange Teleport as a custom teleport item This item is crafting by casting Charge Air Orb on the Abyssal Rift at the center of the abyss. It can be inspected to save a location and add charges, and can be activated to teleport to the saved location. Charges require 20 law runes or an additional orb. --- Server/data/configs/item_configs.json | 2 +- .../global/handlers/item/SnowscapeTeleorb.kt | 140 ++++++++++++++++++ .../global/skill/magic/modern/ModernData.kt | 9 ++ .../skill/magic/modern/ModernListeners.kt | 1 + 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index bcfb80f63..e16807e0a 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -130888,7 +130888,7 @@ "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" }, { - "destroy_message": "You gained this orb from Dark Squall's base. You can probably get another one from visiting the same place.", + "destroy_message": "You can make another by casting the Charge Air Orb spell on the Abyssal Rift in the center of the Abyss.", "examine": "This orb can used to teleport people...somehow.", "durability": null, "name": "Strange teleorb", diff --git a/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt b/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt new file mode 100644 index 000000000..9f5c33dae --- /dev/null +++ b/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt @@ -0,0 +1,140 @@ +package content.global.handlers.item + +import core.api.* +import core.game.node.Node +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.item.Item +import core.game.interaction.InteractionListener +import core.game.interaction.IntType +import core.game.world.map.Location +import core.game.world.map.build.DynamicRegion +import core.game.world.map.zone.ZoneRestriction +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.game.node.entity.player.link.TeleportManager +import core.game.dialogue.* +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.Sounds + +import core.game.component.Component + +/** + * Listener for the strange teleorb object. Normally this object is part of the While Guthix Sleeps quest, but it has been repurposed. + * The new purpose is a custom teleport artifact, allowing players to save a location and teleport back to it. + * @author + */ +class SnowscapeTeleorb : InteractionListener { + + // The teleorb item id + val teleorb = 14534 + + // How many law runes are required for one teleport charge + val runesPerTeleport = 20 + + override fun defineListeners() { + on(teleorb, IntType.ITEM, "inspect") { player, node -> + inspect(player, node) + return@on true + } + on(teleorb, IntType.ITEM, "activate") { player, node -> + activate(player, node) + return@on true + } + } + private fun inspect(player: Player, node: Node) { + openDialogue(player,SnowscapeTeleorbDialogue()) + } + + private fun activate(player: Player, node: Node) { + val charges = getAttribute(player, "teleorb:charges",0) as Int + if (charges >= runesPerTeleport) { + val destination = getAttribute(player, "teleorb:location", Location.create(3236,3218,0)) + player.getTeleporter().send(destination, TeleportManager.TeleportType.ENTRANA_MAGIC_DOOR) + setAttribute(player, "/save:teleorb:charges", charges - runesPerTeleport) + player.sendMessage("Charges remaining: " + ((getAttribute(player, "teleorb:charges",0) as Int) / runesPerTeleport)) + rewardXP(player, Skills.MAGIC, 15.0 * runesPerTeleport) + } else { + player.sendMessage("The teleorb is out of charges.") + } + } + + +} + + + + +class SnowscapeTeleorbDialogue : DialogueFile() { + + // How many law runes are required for one teleport charge + val runesPerTeleport = 20 + + val teleorb = 14534 + val lawRune = 563 + + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + START_DIALOGUE -> options("Update Location","Recharge","Show Info").also {stage++} + + 1 -> when (buttonID) { + 1 -> player?.let { + end() + val region = it.getViewport().getRegion() + if (region == null || region is DynamicRegion || it.getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) { + it.sendMessage("This location cannot be saved!") + } else { + setAttribute(it, "/save:teleorb:location", it.getLocation()) + sendInputDialogue(it, false, "Location saved. Enter a description of this location:",) { value -> + setAttribute(it, "/save:teleorb:description", value as String) + } + it.sendMessage("Location saved.") + it.graphics(Graphics(343)) + it.animate(Animation(1818)) + playAudio(it, Sounds.TELE_OTHER_CAST_199) + } + } + 2 -> options("Recharge with Law Runes","Recharge with additional orbs").also {stage++} + 3 -> player?.let { + end() + it.sendMessage("Current saved location: " + getAttribute(it, "teleorb:description", "Unknown").replace("_"," ")) + it.sendMessage("Charges remaining: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport)) + } + } + 2 -> when (buttonID) { + 1 -> player?.let { + end() + sendInputDialogue(it, true, "Each charge requires $runesPerTeleport Law Runes. How many runes would you like to use?",) { value -> + var amount = kotlin.math.min(amountInInventory(it,lawRune), value as Int) + if (removeItem(it, Item(lawRune, amount))) { + it.sendMessage("You charge the teleorb with $amount Law Runes.") + amount += (getAttribute(it, "teleorb:charges",0) as Int) + setAttribute(it, "/save:teleorb:charges", amount) + it.sendMessage("Current charges: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport)) + it.graphics(Graphics(141,96)) + it.animate(Animation(722)) + playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888) + } + } + } + 2 -> player?.let { + end() + sendInputDialogue(it, true, "Each additional orb adds one charge. How many would you like to use?",) { value -> + var amount = kotlin.math.min(amountInInventory(it,teleorb) - 1, value as Int) + if (amount > 0 && removeItem(it, Item(teleorb, amount))) { + it.sendMessage("You destroy $amount teleorbs, fusing their energy into one") + amount = amount * runesPerTeleport + amount += (getAttribute(it, "teleorb:charges",0) as Int) + setAttribute(it, "/save:teleorb:charges", amount) + it.sendMessage("Current charges: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport)) + it.graphics(Graphics(141,96)) + it.animate(Animation(722)) + playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888) + } + } + } + } + } + } +} diff --git a/Server/src/main/content/global/skill/magic/modern/ModernData.kt b/Server/src/main/content/global/skill/magic/modern/ModernData.kt index 793a757b5..4740bd02d 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernData.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernData.kt @@ -50,6 +50,15 @@ enum class ChargeOrbData( Graphics(150, 90), Sounds.CHARGE_AIR_ORB_116, Items.AIR_ORB_573 + ), + CHARGE_TELE_ORB( + 7171, + arrayOf(Item(Items.COSMIC_RUNE_564, 3), Item(Items.AIR_RUNE_556, 30), Item(Items.UNPOWERED_ORB_567)), + 66, + 76.0, + Graphics(150, 90), + Sounds.CHARGE_AIR_ORB_116, + 14534 ); companion object{ val spellMap = HashMap() diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index edeee3520..16c7f8fbe 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -138,6 +138,7 @@ class ModernListeners : SpellListener("modern"){ onCast(Modern.CHARGE_EARTH_ORB, OBJECT, Scenery.OBELISK_OF_EARTH_29415, 3, method = ::chargeOrb) onCast(Modern.CHARGE_FIRE_ORB, OBJECT, Scenery.OBELISK_OF_FIRE_2153, 3, method = ::chargeOrb) onCast(Modern.CHARGE_AIR_ORB, OBJECT, Scenery.OBELISK_OF_AIR_2152, 3, method = ::chargeOrb) + onCast(Modern.CHARGE_AIR_ORB, OBJECT, 7171, 3, method = ::chargeOrb) } private fun boneConvert(player: Player,bananas: Boolean){ From 16da0ed93ea9b1d6458a19e7d8b3174b6bff1414 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Mar 2025 09:34:48 -0700 Subject: [PATCH 247/306] Implemented custom satchels These satchels are normally from creature creation. The custom versions can be crafted by using an enchantment spell on hides, and have a stackable inventory that only stores certain items. - Plain: Level 1 enchant on Blue D hide. Carries anything but can only be emptied by using it on a bank booth. - Green: Level 2 enchant on Green D hide. Carries any seed or herb. Harvesting farming plots with the satchel equipped returns noted produce. - Red: Level 3 enchant on Red D hide. Carries summoning charms. Charms dropped by mobs are automatically added to the satchel. - Gold: Level 4 enchant on Dagannoth hide. Carries ore. Smelting at the furnace will use ore in the satchel. - Rune: Level 5 enchant on Suqah hide. Carries catalytic runes. Spells will use runes in the satchel. - Black: Level 6 enchant on Black D hide. Placeholder, as I don't have a use for it yet. --- Server/data/configs/item_configs.json | 10 +- .../item/EnchantJewelleryTabListener.kt | 6 + .../handlers/item/SnowscapeSatchelListener.kt | 179 ++++++++++++++++++ .../global/skill/farming/CropHarvester.kt | 12 +- .../global/skill/magic/SpellListener.kt | 5 + .../content/global/skill/magic/SpellUtils.kt | 10 +- .../smithing/smelting/SmeltingPulse.java | 8 +- .../familiar/BurdenInterfacePlugin.java | 6 + .../main/content/minigame/mta/EnchantSpell.kt | 6 + .../node/entity/combat/spell/MagicSpell.java | 8 +- .../node/entity/npc/drop/NPCDropTables.java | 19 +- .../core/game/node/entity/player/Player.java | 9 + .../player/info/login/PlayerSaveParser.kt | 29 +++ .../entity/player/info/login/PlayerSaver.kt | 15 ++ 14 files changed, 301 insertions(+), 21 deletions(-) create mode 100755 Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index e16807e0a..c9c560d81 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -93923,7 +93923,7 @@ }, { "shop_price": "128", - "examine": "I can keep my grub in here.", + "examine": "I can keep my items in here, but I'll need a banker to get them out.", "durability": null, "name": "Plain satchel", "weight": "0.1", @@ -93932,7 +93932,7 @@ "equipment_slot": "5" }, { - "examine": "I can keep my grub in here.", + "examine": "I can keep my seeds and herbs in here.", "durability": null, "name": "Green satchel", "weight": "0.1", @@ -93942,7 +93942,7 @@ }, { "shop_price": "128", - "examine": "I can keep my grub in here.", + "examine": "I can keep my summoning charms in here.", "durability": null, "name": "Red satchel", "weight": "0.1", @@ -93960,7 +93960,7 @@ "equipment_slot": "5" }, { - "examine": "I can keep my grub in here.", + "examine": "I can keep my ores in here.", "durability": null, "name": "Gold satchel", "weight": "0.1", @@ -93969,7 +93969,7 @@ "equipment_slot": "5" }, { - "examine": "I can keep my grub in here.", + "examine": "I can keep my catalytic runes in here.", "durability": null, "name": "Rune satchel", "weight": "0.1", diff --git a/Server/src/main/content/global/handlers/item/EnchantJewelleryTabListener.kt b/Server/src/main/content/global/handlers/item/EnchantJewelleryTabListener.kt index 1a31d30b5..b37ed1b1e 100644 --- a/Server/src/main/content/global/handlers/item/EnchantJewelleryTabListener.kt +++ b/Server/src/main/content/global/handlers/item/EnchantJewelleryTabListener.kt @@ -10,12 +10,14 @@ import org.rs09.consts.Sounds class EnchantJewelleryTabListener : InteractionListener { private val LVL_1_ENCHANT = mapOf( + Items.BLUE_DRAGONHIDE_1751 to Items.PLAIN_SATCHEL_10877, Items.SAPPHIRE_RING_1637 to Items.RING_OF_RECOIL_2550, Items.SAPPHIRE_NECKLACE_1656 to Items.GAMES_NECKLACE8_3853, Items.SAPPHIRE_AMULET_1694 to Items.AMULET_OF_MAGIC_1727, Items.SAPPHIRE_BRACELET_11072 to Items.BRACELET_OF_CLAY_11074 ) private val LVL_2_ENCHANT = mapOf( + Items.GREEN_DRAGONHIDE_1753 to Items.GREEN_SATCHEL_10878, Items.EMERALD_RING_1639 to Items.RING_OF_DUELLING8_2552, Items.EMERALD_NECKLACE_1658 to Items.BINDING_NECKLACE_5521, Items.EMERALD_AMULET_1696 to Items.AMULET_OF_DEFENCE_1729, @@ -23,6 +25,7 @@ class EnchantJewelleryTabListener : InteractionListener { ) private val LVL_3_ENCHANT = mapOf( + Items.RED_DRAGONHIDE_1749 to Items.RED_SATCHEL_10879, Items.RUBY_RING_1641 to Items.RING_OF_FORGING_2568, Items.RUBY_NECKLACE_1660 to Items.DIGSITE_PENDANT_5_11194, Items.RUBY_AMULET_1698 to Items.AMULET_OF_STRENGTH_1725, @@ -30,6 +33,7 @@ class EnchantJewelleryTabListener : InteractionListener { ) private val LVL_4_ENCHANT = mapOf( + Items.DAGANNOTH_HIDE_6155 to Items.GOLD_SATCHEL_10881, Items.DIAMOND_RING_1643 to Items.RING_OF_LIFE_2570, Items.DIAMOND_NECKLACE_1662 to Items.PHOENIX_NECKLACE_11090, Items.DIAMOND_AMULET_1700 to Items.AMULET_OF_POWER_1731, @@ -37,6 +41,7 @@ class EnchantJewelleryTabListener : InteractionListener { ) private val LVL_5_ENCHANT = mapOf( + Items.SUQAH_HIDE_9080 to Items.RUNE_SATCHEL_10882, Items.DRAGONSTONE_RING_1645 to Items.RING_OF_WEALTH4_14646, Items.DRAGON_NECKLACE_1664 to Items.SKILLS_NECKLACE4_11105, Items.DRAGONSTONE_AMMY_1702 to Items.AMULET_OF_GLORY4_1712, @@ -44,6 +49,7 @@ class EnchantJewelleryTabListener : InteractionListener { ) private val LVL_6_ENCHANT = mapOf( + Items.BLACK_DRAGONHIDE_1747 to Items.BLACK_SATCHEL_10880, Items.ONYX_RING_6575 to Items.RING_OF_STONE_6583, Items.ONYX_NECKLACE_6577 to Items.BERSERKER_NECKLACE_11128, Items.ONYX_AMULET_6581 to Items.AMULET_OF_FURY_6585, diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt new file mode 100755 index 000000000..5dde40e25 --- /dev/null +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -0,0 +1,179 @@ +package content.global.handlers.item + +import core.api.* +import core.game.container.Container +import content.global.skill.summoning.familiar.BurdenContainerListener +import core.game.node.Node +import core.game.node.entity.player.Player +//import core.game.node.entity.player.info.login.PlayerSaver +import core.game.node.item.Item +import core.game.interaction.InteractionListener +import core.game.interaction.IntType +import org.json.simple.JSONArray +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import org.rs09.consts.Items + +import core.game.component.Component +import core.game.component.CloseEvent +import core.game.container.access.InterfaceContainer +import content.global.handlers.scenery.BankBoothListener + +/** + * Listener for satchels from Creature Creation, repurposed for Snowscape + * They are repurposed as item pouches, using the summoning familiar inventory interface + * @author + */ +class SnowscapeSatchelListener : InteractionListener { + + companion object { + + val plainSatchelId = 10877 + val greenSatchelId = 10878 + val redSatchelId = 10879 + val blackSatchelId = 10880 + val goldSatchelId = 10881 + val runeSatchelId = 10882 + val satchelIds = intArrayOf(plainSatchelId,greenSatchelId,redSatchelId,blackSatchelId,goldSatchelId,runeSatchelId) + + //val runeSatchelAllowed = intArrayOf(558,559,564,562,9075,561,563,560,565,566) + //val runesForbidden = intArrayOf(556,555,557,554,4695,4696,4698,4697,4694,4699) + + + + + + private fun transferItem(player: Player, satchelId: Int, item: Item, amount: Int, withdraw: Boolean, asNote: Boolean = false) { + if (withdraw == false && !isAllowed(satchelId, unnote(item).getId())) { + player.sendMessage(item.getName() + " cannot be stored in the " + Item(satchelId).getName() + ".") + return + } + if (withdraw == true && asNote == false && satchelId == plainSatchelId) { + player.sendMessage("This satchel can only be emptied by a banker. Use it on a bank booth to get the items.") + return + } + val to = if (withdraw) player.getInventory() else getSatchel(player, satchelId) + val from = if (withdraw) getSatchel(player, satchelId) else player.getInventory() + val maximum = if (asNote) to.getMaximumAdd(note(item)) else to.getMaximumAdd(unnote(item)) + if (maximum < 1 && withdraw == false) { + player.sendMessage("There is not enough space for the " + item.getName() + " in the satchel.") + return + } + val finalAmount = kotlin.comparisons.minOf(amount, from.getAmount(item), maximum) + val finalItem = Item(item.getId(), finalAmount) + if (finalAmount > 0 && from.remove(finalItem)) { + if (asNote) to.add(note(finalItem)) else to.add(unnote(finalItem)) + } + } + + private fun emptySatchel(player: Player, satchelId: Int, asNote: Boolean = false) { + if (asNote == false && satchelId == plainSatchelId) { + player.sendMessage("This satchel can only be emptied by a banker. Use it on a Bank Booth to get the items.") + return + } + val satchel = getSatchel(player, satchelId) + repeat(satchel.capacity()) { index -> + var item = satchel.get(index) + if (item != null) { + transferItem(player, satchelId, item, satchel.getAmount(item), true, asNote) + } + } + } + + + //Function to handle constructing the correct interfaces when the satchel is opened + private fun openSatchel(player: Player, node: Node) { + val satchelId = node.asItem().getId() + val satchel = getSatchel(player, satchelId) + if (satchel.getListeners().count() < 1) satchel.register(BurdenContainerListener(player)) + + player.getInterfaceManager().open(Component(671)).setCloseEvent(CloseEvent { player, component -> + player.getInterfaceManager().closeSingleTab() + removeAttribute(player, "openSatchel") + return@CloseEvent true + } + ) + setAttribute(player, "openSatchel", satchelId) + satchel.shift() + player.getInterfaceManager().openSingleTab(Component(665)) + InterfaceContainer.generateItems(player, player.getInventory().toArray(), arrayOf("Store-X","Store-All","Store-10","Store-5","Store-1"),665,0,7,4,93) + InterfaceContainer.generateItems(player, satchel.toArray(), arrayOf("Withdraw-X","Withdraw-All","Withdraw-10","Withdraw-5","Withdraw-1"),671,27,5,6,30) + } + + // This is called by BurdenInterfacePlugin.java when the player interacts with the familiar interface and the "openSatchel" attribute exists + fun satchelInterfaceAction(player: Player, component: Component, opcode: Int, button: Int, slot: Int, itemId: Int) { + //player.sendMessage("Button:" + button.toString() + ". Opcode:" + opcode.toString()) + val satchelId = getAttribute(player, "openSatchel", 0) + val withdraw = component.getId() == 671 + val container = if (withdraw) getSatchel(player, satchelId) else player.getInventory() + val item = if (slot >= 0 && slot < container.capacity()) container.get(slot) else null + if (item == null && button != 29) return + when (opcode) { + 155 -> if (button == 29) emptySatchel(player, satchelId) else transferItem(player, satchelId, item!!, 1, withdraw) + 196 -> transferItem(player, satchelId, item!!, 5, withdraw) + 124 -> transferItem(player, satchelId, item!!, 10, withdraw) + 199 -> transferItem(player, satchelId, item!!, container.getAmount(item), withdraw) + 234 -> sendInputDialogue(player, true, "Enter the amount:") { value -> transferItem(player, satchelId, item!!, value as Int, withdraw) } + 9 -> player.sendMessage(item!!.getDefinition().getExamine()) + } + } + + + + fun getSatchel(player: Player, satchelId: Int): Container { + var satchel: Container? = null + when (satchelId) { + plainSatchelId -> satchel = player.plainSatchel + greenSatchelId -> satchel = player.greenSatchel + redSatchelId -> satchel = player.redSatchel + blackSatchelId -> satchel = player.blackSatchel + goldSatchelId -> satchel = player.goldSatchel + runeSatchelId -> satchel = player.runeSatchel + } + return satchel!! + } + + // Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on the Red Satchel if the player has one + fun isAllowed(satchelId: Int, itemId: Int): Boolean { + when (satchelId) { + plainSatchelId -> return itemId !in satchelIds + greenSatchelId -> return (Item(itemId).getName().contains(" seed") || Item(itemId).getName().contains("Grimy") || Item(itemId).getName().contains("Clean ")) + redSatchelId -> return itemId in intArrayOf(12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168) + blackSatchelId -> return itemId in intArrayOf(995) + goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892) + runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566) + } + return false + } + } + + + + override fun defineListeners() { + + onUseAnyWith(IntType.ITEM, *satchelIds) { player, used, with -> + val satchelId = with.asItem().getId() + transferItem(player, satchelId, used.asItem(), player.getInventory().getAmount(used.asItem()),false) + return@onUseAnyWith true + } + + on(satchelIds, IntType.ITEM, "inspect","operate") { player, node -> + openSatchel(player, node) + return@on true + } + + on(satchelIds, IntType.ITEM, "empty") { player, node -> + emptySatchel(player, node.asItem().getId()) + return@on true + } + + // BankBoothListener values are public but BankChestListener values are not, so rather than edit the BankChestListener file I have copied the IDs here. 12309 is the Culinomancer's chest. + val bankChests = intArrayOf(3194,4483,10562,14382,16695,16696,21301,27662,27663) + val bankUseWiths = intArrayOf(*BankBoothListener.BANK_BOOTHS, 12309, *bankChests) + onUseWith(IntType.SCENERY, satchelIds, *bankUseWiths) { player, used, with -> + emptySatchel(player, used.asItem().getId(), true) + return@onUseWith true + } + + } +} diff --git a/Server/src/main/content/global/skill/farming/CropHarvester.kt b/Server/src/main/content/global/skill/farming/CropHarvester.kt index 79919bdca..b70347b67 100644 --- a/Server/src/main/content/global/skill/farming/CropHarvester.kt +++ b/Server/src/main/content/global/skill/farming/CropHarvester.kt @@ -83,14 +83,16 @@ class CropHarvester : OptionHandler() { return true } val necklace = getItemFromEquipment(player, EquipmentSlot.NECK) - var amulet = false + var noted = false if (necklace != null && (necklace.name.lowercase().contains("amulet of farming") || necklace.name.lowercase().contains("amulet of nature"))) { - amulet = true - } + noted = true + } else if (inEquipment(player,10878,1)) { + noted = true + } val sendHarvestMessages = if (fPatch.type == PatchType.FLOWER_PATCH) false else true if (sendHarvestMessages && firstHarvest) { sendMessage(player, "You begin to harvest the $patchName.") - if (amulet) { + if (noted) { sendMessage(player, "The leprechaun exchanges your produce for banknotes.") } firstHarvest = false @@ -100,7 +102,7 @@ class CropHarvester : OptionHandler() { // TODO: If a flower patch is being harvested, delay the clearing of the // patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75 delay = 2 - if (amulet) { + if (noted) { addItem(player, note(reward).id) } else { addItem(player, reward.id) diff --git a/Server/src/main/content/global/skill/magic/SpellListener.kt b/Server/src/main/content/global/skill/magic/SpellListener.kt index 64383b0a7..c9ba1b177 100644 --- a/Server/src/main/content/global/skill/magic/SpellListener.kt +++ b/Server/src/main/content/global/skill/magic/SpellListener.kt @@ -62,7 +62,12 @@ abstract class SpellListener(val bookName: String) : Listener { } fun removeRunes(player: Player,removeAttr: Boolean = true){ + /* Snowscape modification: remove runes from the inventory or rune satchel player.inventory.remove(*player.getAttribute("spell:runes",ArrayList()).toTypedArray()) + */ + player.getAttribute("spell:runes",ArrayList()).toTypedArray().forEach { rune -> + if (!player.inventory.remove(rune)) player.runeSatchel.remove(rune) + } if(removeAttr) { player.removeAttribute("spell:runes") player.removeAttribute("tablet-spell") diff --git a/Server/src/main/content/global/skill/magic/SpellUtils.kt b/Server/src/main/content/global/skill/magic/SpellUtils.kt index a80d646a5..ce84d606f 100644 --- a/Server/src/main/content/global/skill/magic/SpellUtils.kt +++ b/Server/src/main/content/global/skill/magic/SpellUtils.kt @@ -6,6 +6,7 @@ import core.game.node.entity.combat.spell.CombinationRune import core.game.node.entity.combat.spell.MagicStaff import core.game.node.entity.combat.spell.Runes import core.game.node.item.Item +import core.api.* object SpellUtils { fun usingStaff(p: Player, rune: Int): Boolean { @@ -20,15 +21,16 @@ object SpellUtils { return false } + // Snowscape modifications: check the runeStachel container for the base runes if the player is carrying one fun hasRune(p:Player,rune:Item):Boolean{ val removeItems = p.getAttribute("spell:runes",ArrayList()) if(usingStaff(p,rune.id)) return true - if(p.inventory.containsItem(rune)){ + if(p.inventory.containsItem(rune) || (inEquipmentOrInventory(p, 10882) && p.runeSatchel.containsItem(rune))){ removeItems.add(rune) p.setAttribute("spell:runes",removeItems) } - val baseAmt = p.inventory.getAmount(rune.id) + val baseAmt = p.inventory.getAmount(rune.id) + (if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(rune.id) else 0) var amtRemaining = rune.amount - baseAmt val possibleComboRunes = CombinationRune.eligibleFor(Runes.forId(rune.id)) for (r in possibleComboRunes) { @@ -49,9 +51,9 @@ object SpellUtils { fun hasRune(p: Player, item: Item, toRemove: MutableList, message: Boolean): Boolean { if (!usingStaff(p, item.id)) { - val hasBaseRune = p.inventory.contains(item.id, item.amount) + val hasBaseRune = p.inventory.contains(item.id, item.amount) || (inEquipmentOrInventory(p, 10882) && p.runeSatchel.contains(item.id, item.amount)) if (!hasBaseRune) { - val baseAmt = p.inventory.getAmount(item.id) + val baseAmt = p.inventory.getAmount(item.id) + (if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(item.id) else 0) if (baseAmt > 0) { toRemove.add(Item(item.id, p.inventory.getAmount(item.id))) } diff --git a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java index 5f7876db9..e3e06df64 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java +++ b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java @@ -99,7 +99,8 @@ public class SmeltingPulse extends SkillPulse { return false; } for (Item item : bar.getOres()) { - if (!player.getInventory().contains(item.getId(), item.getAmount())) { + //Snowscape modification: check gold satchel for ores as well, if carried + if (!player.getInventory().contains(item.getId(), item.getAmount()) && !(inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(item.getId(), item.getAmount()))) { player.getPacketDispatch().sendMessage("You do not have the required ores to make this bar."); return false; } @@ -128,7 +129,7 @@ public class SmeltingPulse extends SkillPulse { player.getPacketDispatch().sendMessage("You place the required ores and attempt to create a bar of " + StringUtils.formatDisplayName(bar.toString().toLowerCase()) + "."); } for (Item i : bar.getOres()) { - if (!player.getInventory().remove(i)) { + if (!(player.getInventory().remove(i) || player.goldSatchel.remove(i))) { return true; } } @@ -147,7 +148,8 @@ public class SmeltingPulse extends SkillPulse { player.sendMessage("The magic of the Varrock armour enables you to smelt 2 bars at the same time."); } } - player.getInventory().add(new Item(bar.getProduct().getId(), amt)); + //player.getInventory().add(new Item(bar.getProduct().getId(), amt)); + addItemOrDrop(player, bar.getProduct().getId(), amt); player.dispatch(new ResourceProducedEvent(bar.getProduct().getId(), 1, player, -1)); double xp = bar.getExperience() * amt; // Goldsmith gauntlets diff --git a/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java b/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java index f9a8fd1a2..275b4abf5 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java +++ b/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java @@ -11,6 +11,8 @@ import core.plugin.Initializable; import core.plugin.Plugin; import kotlin.Unit; +import content.global.handlers.item.SnowscapeSatchelListener; + /** * Handles the beast of burden interface. * @author Emperor @@ -27,6 +29,10 @@ public final class BurdenInterfacePlugin extends ComponentPlugin { @Override public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { + if (getAttribute(player, "openSatchel", null) != null) { + SnowscapeSatchelListener.Companion.satchelInterfaceAction(player, component, opcode, button, slot, itemId); + return true; + } if (!player.getFamiliarManager().hasFamiliar() || !player.getFamiliarManager().getFamiliar().isBurdenBeast()) { return false; } diff --git a/Server/src/main/content/minigame/mta/EnchantSpell.kt b/Server/src/main/content/minigame/mta/EnchantSpell.kt index d6df04fe8..fc8878a27 100644 --- a/Server/src/main/content/minigame/mta/EnchantSpell.kt +++ b/Server/src/main/content/minigame/mta/EnchantSpell.kt @@ -113,6 +113,7 @@ class EnchantSpell : MagicSpell { Items.SAPPHIRE_NECKLACE_1656 to Item(Items.GAMES_NECKLACE8_3853), Items.SAPPHIRE_AMULET_1694 to Item(Items.AMULET_OF_MAGIC_1727), Items.SAPPHIRE_BRACELET_11072 to Item(Items.BRACELET_OF_CLAY_11074), + Items.BLUE_DRAGONHIDE_1751 to Item(Items.PLAIN_SATCHEL_10877), //Begin MTA-specific enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), @@ -132,6 +133,7 @@ class EnchantSpell : MagicSpell { Items.EMERALD_NECKLACE_1658 to Item(Items.BINDING_NECKLACE_5521), Items.EMERALD_AMULET_1696 to Item(Items.AMULET_OF_DEFENCE_1729), Items.EMERALD_BRACELET_11076 to Item(Items.CASTLEWAR_BRACE3_11079), + Items.GREEN_DRAGONHIDE_1753 to Item(Items.GREEN_SATCHEL_10878), //Begin MTA-Specific Enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), @@ -151,6 +153,7 @@ class EnchantSpell : MagicSpell { Items.RUBY_NECKLACE_1660 to Item(Items.DIGSITE_PENDANT_5_11194), Items.RUBY_AMULET_1698 to Item(Items.AMULET_OF_STRENGTH_1725), Items.RUBY_BRACELET_11085 to Item(Items.INOCULATION_BRACE_11088), + Items.RED_DRAGONHIDE_1749 to Item(Items.RED_SATCHEL_10879), //Begin MTA-Specific Enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), @@ -169,6 +172,7 @@ class EnchantSpell : MagicSpell { Items.DIAMOND_NECKLACE_1662 to Item(Items.PHOENIX_NECKLACE_11090), Items.DIAMOND_AMULET_1700 to Item(Items.AMULET_OF_POWER_1731), Items.DIAMOND_BRACELET_11092 to Item(Items.FORINTHRY_BRACE5_11095), + Items.DAGANNOTH_HIDE_6155 to Item(Items.GOLD_SATCHEL_10881), //Begin MTA-Specific Enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), @@ -188,6 +192,7 @@ class EnchantSpell : MagicSpell { Items.DRAGON_NECKLACE_1664 to Item(Items.SKILLS_NECKLACE4_11105), Items.DRAGONSTONE_AMMY_1702 to Item(Items.AMULET_OF_GLORY4_1712), Items.DRAGON_BRACELET_11115 to Item(Items.COMBAT_BRACELET4_11118), + Items.SUQAH_HIDE_9080 to Item(Items.RUNE_SATCHEL_10882), //Begin MTA-Specific Enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), @@ -207,6 +212,7 @@ class EnchantSpell : MagicSpell { Items.ONYX_NECKLACE_6577 to Item(Items.BERSERKER_NECKLACE_11128), Items.ONYX_AMULET_6581 to Item(Items.AMULET_OF_FURY_6585), Items.ONYX_BRACELET_11130 to Item(Items.REGEN_BRACELET_11133), + Items.BLACK_DRAGONHIDE_1747 to Item(Items.BLACK_SATCHEL_10880), //Begin MTA-Specific Enchantments Items.CUBE_6899 to Item(Items.ORB_6902), Items.CYLINDER_6898 to Item(Items.ORB_6902), diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index 601cc835f..250e9489d 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import static core.api.ContentAPIKt.playGlobalAudio; +import static core.api.ContentAPIKt.inEquipmentOrInventory; /** * Represents a magic spell. @@ -243,7 +244,9 @@ public abstract class MagicSpell implements Plugin { } if (remove) { toRemove.forEach(i -> { - p.getInventory().remove(i); + if (!p.getInventory().remove(i)){ + p.runeSatchel.remove(i); + } }); } return true; @@ -277,7 +280,8 @@ public abstract class MagicSpell implements Plugin { */ public boolean hasRune(Player p, Item item, List toRemove, boolean message) { if (!usingStaff(p, item.getId())) { - boolean hasBaseRune = p.getInventory().contains(item.getId(),item.getAmount()); + // Snowscape modification: check the rune satchel for the base runes if the player is carrying one + boolean hasBaseRune = p.getInventory().contains(item.getId(),item.getAmount()) || (inEquipmentOrInventory(p, 10882,1) && p.runeSatchel.contains(item.getId(),item.getAmount())); if(!hasBaseRune){ int baseAmt = p.getInventory().getAmount(item.getId()); if(baseAmt > 0){ diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 84f33d6ce..3a71d14ca 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -27,6 +27,7 @@ import content.global.skill.summoning.familiar.BurdenBeast; import content.global.skill.summoning.familiar.Forager; import content.global.skill.summoning.SummoningPouch; import content.global.skill.summoning.familiar.PackYakNPC; +import content.global.handlers.item.SnowscapeSatchelListener; import java.util.ArrayList; import java.util.List; @@ -104,6 +105,9 @@ public final class NPCDropTables { if (handleBoneCrusher(player, item)) { return; } + if (handleSatchel(player, item)) { + return; + } if (handleCurrency(player, item)) { return; } @@ -181,7 +185,7 @@ public final class NPCDropTables { return true; } if (((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().add(item)) { - player.sendMessage("Your familiar picked up " + item.getAmount() + " " + item.getName() + "."); + player.sendMessage("Your familiar picked up " + item.getAmount() + " " + item.getName() + "."); return true; } else { return false; @@ -266,6 +270,17 @@ public final class NPCDropTables { player.getSkills().addExperience(Skills.PRAYER, item.getAmount() * bone.getExperience()); return true; } + + //Snowscape modification: loot certain items into the red satchel if carried + private boolean handleSatchel(Player player, Item item) { + if (inEquipmentOrInventory(player,10879,1)){ + if (SnowscapeSatchelListener.Companion.isAllowed(10879,item.getId()) && player.redSatchel.add(item)) { + player.sendMessage("Your red satchel stashed " + item.getAmount() + " " + item.getName() + "."); + return true; + } + } + return false; + } /** * Snowscape custom: Automatically loot coins and tokkul if wearing a ring of wealth. @@ -278,7 +293,7 @@ public final class NPCDropTables { Item ring = player.getEquipment().get(12); if (ring != null && ring.getId() >= 14638 && ring.getId() <=14646) { if (player.getInventory().add(item)) { - player.sendMessage("Your Ring collected " + item.getAmount() + " " + item.getName() + "."); + player.sendMessage("Your ring collected " + item.getAmount() + " " + item.getName() + "."); return true; } } diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index afaa0c1f5..06436975c 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -311,6 +311,15 @@ public class Player extends Entity { public byte[] opCounts = new byte[255]; public int invalidPacketCount = 0; + // Snowscape additions + // The satchel containers. + public final Container plainSatchel = new Container(6, ContainerType.ALWAYS_STACK); + public final Container greenSatchel = new Container(30, ContainerType.ALWAYS_STACK); + public final Container redSatchel = new Container(30, ContainerType.ALWAYS_STACK); + public final Container blackSatchel = new Container(30, ContainerType.ALWAYS_STACK); + public final Container goldSatchel = new Container(30, ContainerType.ALWAYS_STACK); + public final Container runeSatchel = new Container(30, ContainerType.ALWAYS_STACK); + /** * Constructs a new {@code Player} {@code Object}. * @param details The player's details. diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index 03fc75d67..4f9d57e44 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -74,6 +74,7 @@ class PlayerSaveParser(val player: Player) { parseStatistics() parseAchievements() parsePouches() + parseSnowscapeData() } fun runContentHooks() @@ -358,4 +359,32 @@ class PlayerSaveParser(val player: Player) { player.version = saveFile!!["version"].toString().toInt() } } + + //Load the custom data added by snowscape + fun parseSnowscapeData() { + saveFile ?: return + if (!(saveFile!!.containsKey("snowscape_data"))) return + + val snowscapeData = saveFile!!["snowscape_data"] as JSONObject + + val plainSatchel = snowscapeData["plainSatchel"] + if (plainSatchel != null) player.plainSatchel.parse(plainSatchel as JSONArray) + + val greenSatchel = snowscapeData["greenSatchel"] + if (greenSatchel != null) player.greenSatchel.parse(greenSatchel as JSONArray) + + val redSatchel = snowscapeData["redSatchel"] + if (redSatchel != null) player.redSatchel.parse(redSatchel as JSONArray) + + val blackSatchel = snowscapeData["blackSatchel"] + if (blackSatchel != null) player.blackSatchel.parse(blackSatchel as JSONArray) + + val goldSatchel = snowscapeData["goldSatchel"] + if (goldSatchel != null) player.goldSatchel.parse(goldSatchel as JSONArray) + + val runeSatchel = snowscapeData["runeSatchel"] + if (runeSatchel != null) player.runeSatchel.parse(runeSatchel as JSONArray) + + + } } diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 11c15b4d8..1f1e3d566 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -55,6 +55,7 @@ class PlayerSaver (val player: Player){ saveStatManager(saveFile) saveAttributes(saveFile) savePouches(saveFile) + saveSnowscapeData(saveFile) contentHooks.forEach { it.savePlayer(player, saveFile) } return saveFile } @@ -643,4 +644,18 @@ class PlayerSaver (val player: Player){ root.put("core_data",coreData) } + + // Function to save the custom data added by snowscape + fun saveSnowscapeData(root: JSONObject){ + val snowscapeData = JSONObject() + + snowscapeData.put("plainSatchel", saveContainer(player.plainSatchel)) + snowscapeData.put("greenSatchel", saveContainer(player.greenSatchel)) + snowscapeData.put("redSatchel", saveContainer(player.redSatchel)) + snowscapeData.put("blackSatchel", saveContainer(player.blackSatchel)) + snowscapeData.put("goldSatchel", saveContainer(player.goldSatchel)) + snowscapeData.put("runeSatchel", saveContainer(player.runeSatchel)) + + root.put("snowscape_data",snowscapeData) + } } From a411c7a5e2f60a38e5e82c66f6cf65decd65a5c9 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Mar 2025 11:21:34 -0700 Subject: [PATCH 248/306] Custom Silver Sickle bonecrusher functionality improvements The automatic bone burying function now works when the sickle is equipped or in the inventory, and also affects bones from hunter traps. --- .../main/content/global/skill/hunter/TrapSetting.java | 10 +++++++++- .../core/game/node/entity/npc/drop/NPCDropTables.java | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Server/src/main/content/global/skill/hunter/TrapSetting.java b/Server/src/main/content/global/skill/hunter/TrapSetting.java index 421a982bf..73a69dbd8 100644 --- a/Server/src/main/content/global/skill/hunter/TrapSetting.java +++ b/Server/src/main/content/global/skill/hunter/TrapSetting.java @@ -20,6 +20,8 @@ import org.rs09.consts.Sounds; import static core.api.ContentAPIKt.playAudio; +import core.game.node.entity.npc.drop.NPCDropTables; + /** * A setting for a trap type. * @author Vexia @@ -161,7 +163,13 @@ public class TrapSetting { return; } addTool(player, wrapper, type); - player.getInventory().add(wrapper.getItems().toArray(new Item[] {})); + // Snowscape modification: custom bonecrusher functionality extended to include hunter bones + //player.getInventory().add(wrapper.getItems().toArray(new Item[] {})); + for (Item item: wrapper.getItems().toArray(new Item[] {})) { + if (!NPCDropTables.handleBoneCrusher(player, item)) { + player.getInventory().add(item); + } + } } else { if (isObjectTrap() && !ground) { player.getInventory().add(wrapper.getItems().toArray(new Item[] {})); diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 3a71d14ca..216f15638 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -259,12 +259,12 @@ public final class NPCDropTables { * @param item The item * @return true if successfully added experience. */ - private boolean handleBoneCrusher(Player player, Item item) { + public static boolean handleBoneCrusher(Player player, Item item) { Bones bone = Bones.forId(item.getId()); if (bone == null) { return false; } - if (!player.getInventory().containsItem(new Item(2963, 1)) || !player.getAttribute("bonecrusher:enabled", false)) { + if (!inEquipmentOrInventory(player,2963, 1) || !player.getAttribute("bonecrusher:enabled", false)) { return false; } player.getSkills().addExperience(Skills.PRAYER, item.getAmount() * bone.getExperience()); From e88bdf94d306e7af11f09f44f1ad698d0eb0fdce Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Mar 2025 15:15:24 -0700 Subject: [PATCH 249/306] Port Phasmatys entry fee can be paid with Ecto-tokens in the bank --- .../region/morytania/phas/handlers/PhasmatysZone.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/region/morytania/phas/handlers/PhasmatysZone.java b/Server/src/main/content/region/morytania/phas/handlers/PhasmatysZone.java index 70131a4ba..3cf16842e 100644 --- a/Server/src/main/content/region/morytania/phas/handlers/PhasmatysZone.java +++ b/Server/src/main/content/region/morytania/phas/handlers/PhasmatysZone.java @@ -187,11 +187,14 @@ public final class PhasmatysZone extends MapZone implements Plugin { */ private void handleEnergyBarrier(Player player, Scenery object) { boolean force = object.getLocation().equals(3659, 3508, 0) && player.getLocation().getY() < 3508 || object.getLocation().equals(3652, 3485, 0) && player.getLocation().getX() > 3652; - if (!force && !player.getInventory().contains(4278, 2)) { + //Snowscape modification: allow paying from bank or inventory. Also notify player if they don't have enough, since the dialogue doesn't seem to trigger + if (!force && !(player.getInventory().contains(4278, 2) || player.getBank().contains(4278, 2))) { + player.sendMessage("You need 2 ecto-tokens in your inventory or bank to pay the entry fee."); player.getDialogueInterpreter().open(1706); return; } - if (force || player.getInventory().remove(new Item(4278, 2))) { + if (force || player.getInventory().remove(new Item(4278, 2)) || player.getBank().remove(new Item(4278, 2))) { + if (!force) player.sendMessage("You pay the ghost guard 2 ecto-tokens to enter the barrier."); final Direction direction = Direction.getLogicalDirection(player.getLocation(), object.getLocation()); Location end = player.getLocation().transform(direction, 2); if (player.getLocation().getY() >= 3508) { From c59e13f0aab3ed00ce6b8db240543a8142d12cb2 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Mar 2025 15:50:40 -0700 Subject: [PATCH 250/306] Added Spirit Weed Seeds to Master Farmer drop table --- Server/src/main/content/global/skill/thieving/Pickpockets.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/src/main/content/global/skill/thieving/Pickpockets.kt b/Server/src/main/content/global/skill/thieving/Pickpockets.kt index 4580f2518..e4c1eda77 100644 --- a/Server/src/main/content/global/skill/thieving/Pickpockets.kt +++ b/Server/src/main/content/global/skill/thieving/Pickpockets.kt @@ -122,6 +122,7 @@ enum class Pickpockets(val ids: IntArray, val requiredLevel: Int, val low: Doubl WeightedItem(Items.TARROMIN_SEED_5293,1,1,50.0), WeightedItem(Items.HARRALANDER_SEED_5294,1,1,25.0), WeightedItem(Items.RANARR_SEED_5295,1,1,8.0), + WeightedItem(Items.SPIRIT_WEED_SEED_12176,1,1,8.0), WeightedItem(Items.TOADFLAX_SEED_5296,1,1,8.0), WeightedItem(Items.IRIT_SEED_5297,1,1,8.0), WeightedItem(Items.AVANTOE_SEED_5298,1,1,8.0), From fe117e6976f71bf4a1ec38a85091a3182c17f1a5 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 5 Mar 2025 15:57:02 -0700 Subject: [PATCH 251/306] Added Fountain of Heroes to main floor of the Heroes Guild --- Server/data/ObjectParser.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/data/ObjectParser.xml b/Server/data/ObjectParser.xml index 547e2eaf1..e132f1f69 100644 --- a/Server/data/ObjectParser.xml +++ b/Server/data/ObjectParser.xml @@ -26,5 +26,6 @@ + From 40d5478b57c2ffeeb0a21d5793012e5fe863f476 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 6 Mar 2025 05:57:40 -0700 Subject: [PATCH 252/306] Runecrafting rebalance - use one essence at a time Runecraft with one essence at a time instead of the whole inventory at once. Doubled rune and exp output to compensate. Also, Ourania and Combination runes are now affected by rune multiplier. All elemental runes share the same level, exp, and multiplier as air runes. Add small multiplier for Soul Runes. --- .../global/skill/runecrafting/Rune.java | 10 +-- .../skill/runecrafting/RuneCraftPulse.java | 66 ++++++++++++------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/Rune.java b/Server/src/main/content/global/skill/runecrafting/Rune.java index 7736c579b..78bd327b9 100644 --- a/Server/src/main/content/global/skill/runecrafting/Rune.java +++ b/Server/src/main/content/global/skill/runecrafting/Rune.java @@ -10,10 +10,10 @@ import core.game.node.item.Item; */ public enum Rune { AIR(Runes.AIR_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), - MIND(Runes.MIND_RUNE.transform(), 2, 5.5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98, 112 }), - WATER(Runes.WATER_RUNE.transform(), 5, 6, new int[] { 1, 19, 38, 57, 76, 95, 114 }), - EARTH(Runes.EARTH_RUNE.transform(), 9, 6.5, new int[] { 1, 26, 52, 78, 104 }), - FIRE(Runes.FIRE_RUNE.transform(), 14, 7, new int[] { 1, 35, 70, 105 }), + MIND(Runes.MIND_RUNE.transform(), 2, 5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98, 112 }), + WATER(Runes.WATER_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), + EARTH(Runes.EARTH_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), + FIRE(Runes.FIRE_RUNE.transform(), 1, 7, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), BODY(Runes.BODY_RUNE.transform(), 20, 7.5, new int[] { 1, 46, 92, 138 }), COSMIC(Runes.COSMIC_RUNE.transform(), 27, 8, new int[] { 1, 59, 118 }), CHAOS(Runes.CHAOS_RUNE.transform(), 35, 8.5, new int[] { 1, 74, 148 }), @@ -22,7 +22,7 @@ public enum Rune { LAW(Runes.LAW_RUNE.transform(), 54, 9.5, new int[] { 1, 110, }), DEATH(Runes.DEATH_RUNE.transform(), 65, 10, new int[] { 1, 131 }), BLOOD(Runes.BLOOD_RUNE.transform(), 77, 10.5, new int[] { 1, 154 }), - SOUL(Runes.SOUL_RUNE.transform(), 90, 11); + SOUL(Runes.SOUL_RUNE.transform(), 90, 11, new int[] { 1, 179 }); /** * Constructs a new {@code Rune} {@code Object}. diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index a3bc80b5f..4781983fb 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -150,7 +150,7 @@ public final class RuneCraftPulse extends SkillPulse { talisman = t; } } - player.lock(4); + player.lock(2); return true; } @@ -163,13 +163,17 @@ public final class RuneCraftPulse extends SkillPulse { @Override public boolean reward() { + setDelay(5); if (!combination) { - craftTablet(); - craft(); + if (amountInInventory(player, SOFT_CLAY.getId()) > 0) { + craftTablet(); + } else { + craft(); + } } else { combine(); } - return true; + return false; } private static final int[][] OuraniaTable = { //https://x.com/JagexAsh/status/1312893446395506688/photo/1 @@ -191,8 +195,10 @@ public final class RuneCraftPulse extends SkillPulse { */ private void craft() { final Item item = getEssenceItem(); - int amount = player.getInventory().getAmount(item); + //int amount = player.getInventory().getAmount(item); + int amount = 2; if (altar.isOurania()) { + amount = 1; if (removeItem(player, item, Container.INVENTORY)) { sendMessage(player, "You bind the temple's power into runes."); player.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_RC, amount); @@ -213,15 +219,15 @@ public final class RuneCraftPulse extends SkillPulse { break; } } - rewardXP(player, Skills.RUNECRAFTING, rune.getExperience() * 2); - addItemOrDrop(player, rune.getRune().getId(), 1); + rewardXP(player, Skills.RUNECRAFTING, rune.getExperience() * 4); + addItemOrDrop(player, rune.getRune().getId(), getMultiplier(rune)); } } } else { int total = 0; for(int j = 0; j < amount; j++) { // since getMultiplier is stochastic, roll `amount` independent copies - total += getMultiplier(); + total += getMultiplier(rune); } if (removeItem(player, item, Container.INVENTORY)) { @@ -244,7 +250,8 @@ public final class RuneCraftPulse extends SkillPulse { player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 2, 3); } // Craft 196 or more air runes simultaneously - if (altar == Altar.AIR && total >= 196) { + //Snowscape: since runecrafting is one essence at a time, you can't craft 196 at once. So just trigger when level 66 is reached. + if (altar == Altar.AIR && getDynLevel(player, Skills.RUNECRAFTING) >= 66) { player.getAchievementDiaryManager().finishTask(player, DiaryType.FALADOR, 2, 2); } // Craft a water rune at the Water Altar @@ -264,25 +271,31 @@ public final class RuneCraftPulse extends SkillPulse { boolean imbued = hasSpellImbue(); if (!imbued ? removeItem(player, remove, Container.INVENTORY) : imbued) { int amount = 0; - int essenceAmt = player.getInventory().getAmount(PURE_ESSENCE); + //int essenceAmt = player.getInventory().getAmount(PURE_ESSENCE); + int essenceAmt = 1; + int multiplier = getMultiplier(altar.getRune()) * 2; final Item rune = node.getName().contains("rune") ? Rune.forItem(node).getRune() : Rune.forName(Talisman.forItem(node).name()).getRune(); int runeAmt = player.getInventory().getAmount(rune); - amount = Math.min(essenceAmt, runeAmt); - if (removeItem(player, new Item(PURE_ESSENCE.getId(), amount), Container.INVENTORY) && removeItem(player, new Item(rune.getId(), amount), Container.INVENTORY)) { + amount = Math.min(multiplier, runeAmt); + if (removeItem(player, new Item(PURE_ESSENCE.getId(), essenceAmt), Container.INVENTORY) && removeItem(player, new Item(rune.getId(), amount), Container.INVENTORY)) { + rewardXP(player, Skills.RUNECRAFTING, combo.getExperience()); for (int i = 0; i < amount; i++) { if (RandomFunction.random(1, 3) == 1 || hasBindingNecklace()) { addItemOrDrop(player, combo.getRune().getId(), 1); - rewardXP(player, Skills.RUNECRAFTING, combo.getExperience()); + //rewardXP(player, Skills.RUNECRAFTING, combo.getExperience()); } } if (hasBindingNecklace()) { player.getEquipment().get(EquipmentContainer.SLOT_AMULET).setCharge(player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() - 1); - if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() > 14) { + if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() >= 400) { if (player.getEquipment().remove(BINDING_NECKLACE, true)) { - sendMessage(player, "Your binding necklace crumbles into dust."); + sendMessage(player, "Your binding necklace crumbles into dust."); + playAudio(player, Sounds.DESTROY_OBJECT_2381); } } } + // Snowscape: adding the imbue effect after crafting so that a talisman isn't required for every essence + player.setAttribute("spell:imbue", GameWorld.getTicks() + 20); } } } @@ -291,7 +304,8 @@ public final class RuneCraftPulse extends SkillPulse { * Method used to craft tablets. Custom for Snowscape */ private final void craftTablet() { - int amount = player.getInventory().getAmount(new Item(1761)); + //int amount = player.getInventory().getAmount(new Item(1761)); + int amount = 1; Item clay = new Item(1761, amount); Item tablet = null; if (altar == Altar.AIR) { tablet = new Item(13599, amount); } @@ -331,15 +345,19 @@ public final class RuneCraftPulse extends SkillPulse { */ private Item getEssenceItem() { if (altar.isOurania() && amountInInventory(player, PURE_ESSENCE.getId()) > 0) { - return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + //return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + return new Item(PURE_ESSENCE.getId(), 1); } if (!rune.isNormal() && amountInInventory(player, PURE_ESSENCE.getId()) > 0) { - return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + //return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + return new Item(PURE_ESSENCE.getId(), 1); } if (rune.isNormal() && amountInInventory(player, RUNE_ESSENCE.getId()) > 0) { - return new Item(RUNE_ESSENCE.getId(), amountInInventory(player, RUNE_ESSENCE.getId())); + //return new Item(RUNE_ESSENCE.getId(), amountInInventory(player, RUNE_ESSENCE.getId())); + return new Item(RUNE_ESSENCE.getId(), 1); } - return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + //return new Item(PURE_ESSENCE.getId(), amountInInventory(player, PURE_ESSENCE.getId())); + return new Item(PURE_ESSENCE.getId(), 1); } /** @@ -347,10 +365,10 @@ public final class RuneCraftPulse extends SkillPulse { * * @return the amount. */ - public int getMultiplier() { - if (altar.isOurania()) { - return 1; - } + public int getMultiplier(Rune rune) { + //if (altar.isOurania()) { + // return 1; + //} int rcLevel = getDynLevel(player, Skills.RUNECRAFTING); int runecraftingFormulaRevision = ServerConstants.RUNECRAFTING_FORMULA_REVISION; boolean lumbridgeDiary = player.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE).isComplete(1); From 9926b5c244897ac87b6a872a604b40e0513fb012 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 6 Mar 2025 21:40:20 -0700 Subject: [PATCH 253/306] Fixed autocast bug - Player autocast spell now loads properly on login This was caused by items being unequipped and re-equipped on login to verify that the player meets the requirements to use it. As a consequence of this bugfix, if the requirements for an item change (like a new quest comes out) then the item won't be forcibly unequipped. I can live with that though. --- .../node/entity/player/info/login/LoginConfiguration.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index 4fcc49823..0f8771092 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -149,11 +149,15 @@ public final class LoginConfiguration { //We should have already been doing this. //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. if (item == null) continue; +//Snowscape: removed the re-equip section, as that cleared the autocast spell on login and I don't care about catching the odd item requirement change. + 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)) { player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); addItemOrBank(player, item.getId(), item.getAmount()); } +*/ } SpellBookManager.SpellBook currentSpellBook = SpellBookManager.SpellBook.forInterface(player.getSpellBookManager().getSpellBook()); From 18d30a3e1e4b36b10419564884d5e6a00e0dc533 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 8 Mar 2025 14:50:09 -0700 Subject: [PATCH 254/306] Added ability to swap spellbooks by operating the Mage's Book The spellbook needs to first be unlocked by completing the quest and using the book on the respoctive altar. --- .../handlers/item/SnowscapeMagesBook.kt | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt diff --git a/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt b/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt new file mode 100644 index 000000000..886d0a3a0 --- /dev/null +++ b/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt @@ -0,0 +1,91 @@ +package content.global.handlers.item + +import core.api.* +import core.game.node.Node +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.SpellBookManager.SpellBook +//import core.game.node.item.Item +import core.game.interaction.InteractionListener +import core.game.interaction.IntType +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.game.dialogue.* +import core.tools.START_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.Sounds +import org.rs09.consts.Scenery +import org.rs09.consts.Animations +import content.data.Quests + +//import core.game.component.Component + +/** + * Listener for the Mage's Book from Mage Training Arena. The other spellbooks can be inscribed into the book by using it on the respective altar. + * Operate the book to switch to spellbooks that have been added. + * + */ +class SnowscapeMagesBook : InteractionListener { + + + override fun defineListeners() { + on(Items.MAGES_BOOK_6889, IntType.ITEM, "operate") { player, node -> + if (player.inCombat()) { + player.sendMessage("You cannot concentrate on the book during combat.") + } else { + player.animate(Animation(6299)) + player.graphics(Graphics(1062)) + openDialogue(player, SnowscapeMagesBookDialogue()) + } + return@on true + } + + val altars = intArrayOf(Scenery.ALTAR_6552,Scenery.ALTAR_17010) + + onUseWith(IntType.SCENERY, Items.MAGES_BOOK_6889, *altars) { player, used, with -> + val ancient = (with.getId() == Scenery.ALTAR_6552) + val quest = if (ancient) Quests.DESERT_TREASURE else Quests.LUNAR_DIPLOMACY + val attribute = if (ancient) "/save:snowscape:magesbook:2" else "/save:snowscape:magesbook:3" + + if (hasRequirement(player, quest)){ + setAttribute(player, attribute, true) + sendDialogue(player, "You carefully focus on the magic in the altar, and inscribe it into the book.") + playAudio(player, Sounds.LUNAR_STAT_SPY_3620) + playAudio(player, Sounds.LUNAR_STAT_SPY_IMPACT_3621) + animate(player, Animations.LUNAR_SPELLBOOK_STATSPY_6293) + } + return@onUseWith true + } + } +} + + + + +class SnowscapeMagesBookDialogue : DialogueFile() { + + + override fun handle(componentID: Int, buttonID: Int) { + when (stage) { + START_DIALOGUE -> options("Modern","Ancient","Lunar").also {stage++} + + 1 -> { + end() + if (player == null) return + // This is ordered a little strange, but checking the quest comes first so that access to the spellbook is lost when the quest is released, until it's completed. + if (buttonID == 2 && !hasRequirement(player!!, Quests.DESERT_TREASURE)) return + if (buttonID == 3 && !hasRequirement(player!!, Quests.LUNAR_DIPLOMACY)) return + if (buttonID > 1 && !getAttribute(player!!, "snowscape:magesbook:$buttonID", false)) { + val altarDescription = if (buttonID == 2) "altar in the Pyramid" else "Astral altar" + sendDialogue(player!!, "The book does not contain the knowledge of those spells. Use the book on the $altarDescription to inscribe it.") + return + } + player!!.spellBookManager.setSpellBook(SpellBook.values()[buttonID - 1]) + player!!.spellBookManager.update(player!!) + playAudio(player!!, Sounds.PRAYER_RECHARGE_2674) + sendMessage(player!!, "You retrieve the inscribed knowledge and let it fill your mind.") + + } + + } + } +} From 9c8c2ada70e4dcef210da85b8ae6019b44898d49 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 8 Mar 2025 15:00:08 -0700 Subject: [PATCH 255/306] Can now talk to people on Lunar Isle even if your seal of passage is in the bank --- Server/src/main/core/api/ContentAPI.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 11786ad1b..55bc7c460 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -2321,7 +2321,9 @@ fun unnote(item: Item): Item { * @return True if Seal of Passage present, false otherwise. */ fun hasSealOfPassage(player: Player): Boolean { - return inEquipmentOrInventory(player, Items.SEAL_OF_PASSAGE_9083) + // Snowscape: modified to include checking the bank as well as equipment or inventory. + return player.hasItem(Item(Items.SEAL_OF_PASSAGE_9083)) + //return inEquipmentOrInventory(player, Items.SEAL_OF_PASSAGE_9083) } /** From dda80d535bc1e2c6bd824eaf65c1467cae3e2b20 Mon Sep 17 00:00:00 2001 From: Player Name Date: Mon, 10 Mar 2025 03:18:27 +0000 Subject: [PATCH 256/306] Fixed a pet growth bug that could cause an error logging in --- .../skill/summoning/familiar/FamiliarManager.java | 10 +++++++++- .../main/content/global/skill/summoning/pet/Pet.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java index 888fa8f3e..3f210dd95 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java +++ b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java @@ -128,7 +128,12 @@ public final class FamiliarManager { } if (currentPet != -1) { int last = this.petDetails.get(currentPet).size() - 1; - PetDetails details = this.petDetails.get(currentPet).get(last); + PetDetails details; + if (last < 0) { //missing data in save due to historical bug (see GL !2077) + details = new PetDetails(0); + } else { + details = this.petDetails.get(currentPet).get(last); + } Pets pets = Pets.forId(currentPet); familiar = new Pet(player, details, currentPet, pets.getNpcId(currentPet)); } else if (familiarData.containsKey("familiar")) { @@ -414,6 +419,9 @@ public final class FamiliarManager { * @param details The new pet details. */ public void addDetails(int itemId, PetDetails details) { + if (petDetails.get(itemId) == null) { + petDetails.put(itemId, new ArrayList<>()); + } petDetails.get(itemId).add(details); } diff --git a/Server/src/main/content/global/skill/summoning/pet/Pet.java b/Server/src/main/content/global/skill/summoning/pet/Pet.java index bb83f16d4..99048c140 100644 --- a/Server/src/main/content/global/skill/summoning/pet/Pet.java +++ b/Server/src/main/content/global/skill/summoning/pet/Pet.java @@ -129,8 +129,8 @@ public final class Pet extends Familiar { if (pet.isKitten(itemId)) { owner.incrementAttribute("/save:stats_manager:cats_raised"); } - owner.getFamiliarManager().removeDetails(getItemId()); owner.getFamiliarManager().addDetails(newItemId, details); + owner.getFamiliarManager().removeDetails(getItemId()); owner.getFamiliarManager().morphPet(new Item(newItemId), false, location, details.getHunger(), 0); owner.getPacketDispatch().sendMessage("Your pet has grown larger."); } From daf312ce6beb21712e4b3020a13965fae3de0df3 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 12 Mar 2025 08:31:22 -0600 Subject: [PATCH 257/306] Fixes related to ironman mode and exp rates Default exp rate is now 1.0, Restored the option to select 10x (no longer limited to hardcore ironmen) Restored option to select hardcore ironman mode. Permadeath now properly clears the custom satchels. Ironmen can no longer trade (custom feature allow untradebale items to be traded was allowing ironmen to trade all items with a warning) Implemented option to select Boosted mode --- .../dialogue/TutorialMagicTutorDialogue.kt | 36 +++++++++++++++---- Server/src/main/core/api/utils/Permadeath.kt | 8 +++++ .../player/info/login/PlayerSaveParser.kt | 2 ++ .../link/request/trade/TradeContainer.java | 12 +++++-- .../core/game/node/entity/skill/Skills.java | 2 +- Server/worldprops/default.conf | 5 +-- 6 files changed, 52 insertions(+), 13 deletions(-) diff --git a/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt b/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt index a92d70916..540382e1f 100644 --- a/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt +++ b/Server/src/main/content/region/misc/tutisland/dialogue/TutorialMagicTutorDialogue.kt @@ -93,11 +93,12 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di } } 71 -> when(stage){ - 0 -> options("Set Ironman Mode (current: ${player.ironmanManager.mode.name})", "Change XP Rate (current: ${player.skills.experienceMultiplier}x)", "I'm ready now.").also { stage++ } + 0 -> options("Set Ironman Mode (current: ${player.ironmanManager.mode.name})", "Change XP Rate (current: ${player.skills.experienceMultiplier}x)", "Toggle Boosted mode (current: ${if (getAttribute(player, "snowscape:boostedmode", false)) "Enabled" else "Disabled"})", "I'm ready now.").also { stage++ } 1 -> when(buttonId){ - 1 -> options("None","Standard","Ultimate","Nevermind.").also { stage = 10 } - 2 -> options("1.0x","2.5x","5.0x").also { stage = 20 } - 3 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, you're all finished here now. I'll give you a reasonable number of starting items when you leave.").also { stage = 30 } + 1 -> options("None","Standard (No trading)","Ultimate (No trading and no bank)","Hardcore (No trading and PERMADEATH!)","Nevermind.").also { stage = 10 } + 2 -> options("1.0x","2.5x","5.0x","10.0x").also { stage = 20 } + 3 -> options("Enable", "Disable").also { stage = 25 } + 4 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, you're all finished here now. I'll give you a reasonable number of starting items when you leave.").also { stage = 30 } } 10 -> { @@ -109,12 +110,15 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di 0 -> IronmanMode.NONE 1 -> IronmanMode.STANDARD 2 -> IronmanMode.ULTIMATE + 3 -> IronmanMode.HARDCORE else -> IronmanMode.NONE } if (mode != IronmanMode.NONE) stage = 11 player.dialogueInterpreter.sendDialogue("You set your ironman mode to: ${mode.name}.") player.ironmanManager.mode = mode +/* if (player.skills.experienceMultiplier == 10.0) player.skills.experienceMultiplier = 5.0 +*/ } else { @@ -124,19 +128,32 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di 11 -> player.dialogueInterpreter.sendPlainMessage(false, *splitLines("WARNING: You have selected an ironman mode. This is an uncompromising mode that WILL completely restrict your ability to trade. This MAY leave you unable to complete certain content, including quests.")).also { stage = 0 } 20 -> { - val rates = arrayOf(1.0,2.5,5.0) + val rates = arrayOf(1.0,2.5,5.0,10.0) val rate = rates[buttonId - 1] +/* if(rate == 10.0) { player.dialogueInterpreter.sendDialogue("10.0x is no longer available!") player.skills.experienceMultiplier = 5.0 stage = 0 return true } +*/ player.dialogueInterpreter.sendDialogue("You set your XP rate to: ${rate}x.") player.skills.experienceMultiplier = rate stage = 0 } + 25 -> { + when(buttonId) { + 1 -> setAttribute(player, "/save:snowscape:boostedmode", true) + 2 -> removeAttribute(player, "snowscape:boostedmode") + } + val currentMode = getAttribute(player, "snowscape:boostedmode", false) + //setAttribute(player, "/save:snowscape:boostedmode", !currentMode) + player.dialogueInterpreter.sendPlainMessage(false, *splitLines("You have ${if (currentMode) "Enabled" else "Disabled"} Boosted mode. Boosted mode makes some custom features much more powerful, which will bypass many game-balance obstacles and lead to easier progression. Not recommended if you want a more traditional experience.")).also { stage = 0 } + + } + 30 -> player.dialogueInterpreter.sendOptions("Leave Tutorial Island?", "Yes, I'm ready.", "No, not yet.").also { stage++ } 31 -> when(buttonId) { @@ -148,7 +165,7 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di setAttribute(player, "/save:tutorial:complete", true) setVarbit(player, 3756, 0) setVarp(player, 281, 1000, true) - teleport(player, Location.create(3233, 3230), TeleportManager.TeleportType.NORMAL) + teleport(player, ServerConstants.HOME_LOCATION!!, TeleportManager.TeleportType.NORMAL) closeOverlay(player) player.inventory.clear() @@ -159,10 +176,15 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di player.inventory.add(*STARTER_PACK) player.bank.add(*STARTER_BANK) + if(player.ironmanManager.mode == IronmanMode.HARDCORE){ + setAttribute(player, "/save:permadeath", true) + } +/* if(player.skills.experienceMultiplier == 10.0) { player.skills.experienceMultiplier = 5.0 } +*/ //This overwrites the stuck dialogue after teleporting to Lumbridge for some reason //Dialogue from 2007 or thereabouts @@ -182,7 +204,7 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di player.unhook(TutorialUseWithReceiver) player.unhook(TutorialInteractionReceiver) player.unhook(TutorialButtonReceiver) - RulesAndInfo.openFor(player) + //RulesAndInfo.openFor(player) if (GameWorld.settings!!.enable_default_clan) { player.communication.currentClan = ServerConstants.SERVER_NAME.toLowerCase() diff --git a/Server/src/main/core/api/utils/Permadeath.kt b/Server/src/main/core/api/utils/Permadeath.kt index c7e5069f4..1e7f13e9f 100644 --- a/Server/src/main/core/api/utils/Permadeath.kt +++ b/Server/src/main/core/api/utils/Permadeath.kt @@ -42,6 +42,14 @@ fun permadeath(target: Player) { target.saveVarp.clear() target.timers.clearTimers() + //Snowscape custom data + target.plainSatchel.clear() + target.greenSatchel.clear() + target.redSatchel.clear() + target.goldSatchel.clear() + target.runeSatchel.clear() + target.blackSatchel.clear() + // Skills target.skills = Skills(target) diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index 4f9d57e44..cb0e151f4 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -331,6 +331,7 @@ class PlayerSaveParser(val player: Player) { player.skills.parse(skillData) player.skills.experienceGained = saveFile!!["totalEXP"].toString().toDouble() player.skills.experienceMultiplier = saveFile!!["exp_multiplier"].toString().toDouble() +/* Snowscape: removing this function since it causes the default exp rate to override player selection, and not allow 10x or higher multipliers if (GameWorld.settings?.default_xp_rate != 5.0) { player.skills.experienceMultiplier = GameWorld.settings?.default_xp_rate!! } @@ -339,6 +340,7 @@ class PlayerSaveParser(val player: Player) { divisor = player.skills.experienceMultiplier / 5.0 player.skills.correct(divisor) } +*/ if (saveFile!!.containsKey("milestone")) { val milestone: JSONObject = saveFile!!["milestone"] as JSONObject player.skills.combatMilestone = (milestone.get("combatMilestone")).toString().toInt() diff --git a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java index f71eafabc..b2ce8da3a 100644 --- a/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java +++ b/Server/src/main/core/game/node/entity/player/link/request/trade/TradeContainer.java @@ -49,9 +49,8 @@ public final class TradeContainer extends Container { return; } if (!tradeable(item) && !GameWorld.getSettings().isDevMode()) { - player.getPacketDispatch().sendMessage("This item is not normally tradeable. Be careful not to break any quests!"); //player.getPacketDispatch().sendMessage("You can't trade this item."); - //return; + return; } Item remove = new Item(item.getId(), amount); remove.setAmount(stabalizeAmount(remove, amount, player.getInventory())); @@ -167,8 +166,10 @@ public final class TradeContainer extends Container { return true; } if (player.getIronmanManager().isIronman() || target != null && target.getIronmanManager().isIronman()) { + sendMessage(player,"Cannot trade that item to or from an Ironman."); return false; } +/* Snowscape: removing this section. Not that we use bots, but the IP for every account is 0.0.0.0 so it fails the check every time) if ((playerIsBot || targetIsBot) && (playerIP.equals(targetIP) || playerMac.equals(targetMac) || playerHost.equals(targetHost))){ sendMessage(player, colorize("%RYou can not trade items with your own bot accounts.")); return false; @@ -176,7 +177,12 @@ public final class TradeContainer extends Container { if (item.getName().equals("Coins") && item.getId() != 995) { return false; } - return definition.isTradeable(); +*/ + if (!definition.isTradeable()) { + sendMessage(player, "This item is not normally tradeable. Be careful not to break any quests!"); + } + return true; + //return definition.isTradeable(); } /** diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index a97be4b00..d94ccebb1 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -41,7 +41,7 @@ public final class Skills { /** * Represents the constant modifier of experience. */ - public double experienceMultiplier = 5.0; + public double experienceMultiplier = 1.0; /** * The maximum experience multiplier. diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index 37ca25c6c..511ab41c6 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -58,8 +58,9 @@ members = true #activity as displayed on the world list activity = "SnowScape" pvp = false -#any default_xp_rate other than 5.0 will override player selection -default_xp_rate = 5.0 +#Snowscape: this used to force player xp rate to match this number if set to anything other than 5.0, but that has been disabled +#now it does nothing, as the default exp rate is actually set by Skills.java when a new player is created. +default_xp_rate = 1.0 allow_slayer_reroll = false #enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already. enable_default_clan = true From b109b982477e342520091ddb8659777cab46a466 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 12 Mar 2025 09:52:19 -0600 Subject: [PATCH 258/306] Strange teleorb custom teleport item now only requires 2 Law runes per charge instead of 20 --- .../global/handlers/item/SnowscapeTeleorb.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt b/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt index 9f5c33dae..789827f2c 100644 --- a/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeTeleorb.kt @@ -31,7 +31,8 @@ class SnowscapeTeleorb : InteractionListener { val teleorb = 14534 // How many law runes are required for one teleport charge - val runesPerTeleport = 20 + val runesPerTeleportNormal = 20 + val runesPerTeleportBoosted = 2 override fun defineListeners() { on(teleorb, IntType.ITEM, "inspect") { player, node -> @@ -49,6 +50,7 @@ class SnowscapeTeleorb : InteractionListener { private fun activate(player: Player, node: Node) { val charges = getAttribute(player, "teleorb:charges",0) as Int + var runesPerTeleport = if (getAttribute(player, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal if (charges >= runesPerTeleport) { val destination = getAttribute(player, "teleorb:location", Location.create(3236,3218,0)) player.getTeleporter().send(destination, TeleportManager.TeleportType.ENTRANA_MAGIC_DOOR) @@ -69,7 +71,8 @@ class SnowscapeTeleorb : InteractionListener { class SnowscapeTeleorbDialogue : DialogueFile() { // How many law runes are required for one teleport charge - val runesPerTeleport = 20 + val runesPerTeleportNormal = 20 + val runesPerTeleportBoosted = 2 val teleorb = 14534 val lawRune = 563 @@ -98,6 +101,7 @@ class SnowscapeTeleorbDialogue : DialogueFile() { 2 -> options("Recharge with Law Runes","Recharge with additional orbs").also {stage++} 3 -> player?.let { end() + var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal it.sendMessage("Current saved location: " + getAttribute(it, "teleorb:description", "Unknown").replace("_"," ")) it.sendMessage("Charges remaining: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport)) } @@ -105,6 +109,7 @@ class SnowscapeTeleorbDialogue : DialogueFile() { 2 -> when (buttonID) { 1 -> player?.let { end() + var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal sendInputDialogue(it, true, "Each charge requires $runesPerTeleport Law Runes. How many runes would you like to use?",) { value -> var amount = kotlin.math.min(amountInInventory(it,lawRune), value as Int) if (removeItem(it, Item(lawRune, amount))) { @@ -114,16 +119,17 @@ class SnowscapeTeleorbDialogue : DialogueFile() { it.sendMessage("Current charges: " + ((getAttribute(it, "teleorb:charges",0) as Int) / runesPerTeleport)) it.graphics(Graphics(141,96)) it.animate(Animation(722)) - playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888) + playAudio(it, Sounds.LUNAR_EMBUE_RUNES_2888) //Yes, Imbue is mispelled in the sounds list. } } } 2 -> player?.let { end() + var runesPerTeleport = if (getAttribute(it, "snowscape:boostedmode", false)) runesPerTeleportBoosted else runesPerTeleportNormal sendInputDialogue(it, true, "Each additional orb adds one charge. How many would you like to use?",) { value -> var amount = kotlin.math.min(amountInInventory(it,teleorb) - 1, value as Int) if (amount > 0 && removeItem(it, Item(teleorb, amount))) { - it.sendMessage("You destroy $amount teleorbs, fusing their energy into one") + it.sendMessage("You destroy $amount teleorbs, fusing their energy into one.") amount = amount * runesPerTeleport amount += (getAttribute(it, "teleorb:charges",0) as Int) setAttribute(it, "/save:teleorb:charges", amount) From 6458a6ef9546fe75df3a485be52ab040eb8f171a Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 12 Mar 2025 11:30:37 -0600 Subject: [PATCH 259/306] Satchel changes. Rune satchel allows all runes in Boosted mode. Red satchel allows clue scrolls. --- .../global/handlers/item/SnowscapeSatchelListener.kt | 8 ++++---- .../core/game/node/entity/npc/drop/NPCDropTables.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt index 5dde40e25..d2eed85fc 100755 --- a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -44,7 +44,7 @@ class SnowscapeSatchelListener : InteractionListener { private fun transferItem(player: Player, satchelId: Int, item: Item, amount: Int, withdraw: Boolean, asNote: Boolean = false) { - if (withdraw == false && !isAllowed(satchelId, unnote(item).getId())) { + if (withdraw == false && !isAllowed(player, satchelId, unnote(item).getId())) { player.sendMessage(item.getName() + " cannot be stored in the " + Item(satchelId).getName() + ".") return } @@ -134,14 +134,14 @@ class SnowscapeSatchelListener : InteractionListener { } // Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on the Red Satchel if the player has one - fun isAllowed(satchelId: Int, itemId: Int): Boolean { + fun isAllowed(player: Player, satchelId: Int, itemId: Int): Boolean { when (satchelId) { plainSatchelId -> return itemId !in satchelIds greenSatchelId -> return (Item(itemId).getName().contains(" seed") || Item(itemId).getName().contains("Grimy") || Item(itemId).getName().contains("Clean ")) - redSatchelId -> return itemId in intArrayOf(12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168) + redSatchelId -> return itemId in intArrayOf(12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168) || Item(itemId).getName().equals("Clue scroll") blackSatchelId -> return itemId in intArrayOf(995) goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892) - runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566) + runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566) || (getAttribute(player,"snowscape:boostedmode",false) && itemId in intArrayOf(556,555,557,554,4694,4695,4696,4697,4698,4699)) } return false } diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 216f15638..e971313df 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -274,7 +274,7 @@ public final class NPCDropTables { //Snowscape modification: loot certain items into the red satchel if carried private boolean handleSatchel(Player player, Item item) { if (inEquipmentOrInventory(player,10879,1)){ - if (SnowscapeSatchelListener.Companion.isAllowed(10879,item.getId()) && player.redSatchel.add(item)) { + if (SnowscapeSatchelListener.Companion.isAllowed(player,10879,item.getId()) && player.redSatchel.add(item)) { player.sendMessage("Your red satchel stashed " + item.getAmount() + " " + item.getName() + "."); return true; } From 81730af934fec5284c30d52590df8fcee36a9b93 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 12 Mar 2025 12:04:53 -0600 Subject: [PATCH 260/306] Customized world list info --- Server/src/main/core/net/lobby/WorldList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/net/lobby/WorldList.java b/Server/src/main/core/net/lobby/WorldList.java index c7d24f36b..1a9a719dd 100644 --- a/Server/src/main/core/net/lobby/WorldList.java +++ b/Server/src/main/core/net/lobby/WorldList.java @@ -119,7 +119,7 @@ public final class WorldList { * Populates the world list. */ static { - addWorld(new WorldDefinition(1, 0, FLAG_MEMBERS | FLAG_LOOTSHARE, "2009Scape Classic", "127.0.0.1", "Anywhere, USA", COUNTRY_USA)); + addWorld(new WorldDefinition(1, 0, FLAG_MEMBERS | FLAG_LOOTSHARE, "Snowscape custom server", "127.0.0.1", "Canada", COUNTRY_CANADA)); } /** From fb0dd3a27db06abaab1bc6ce44766caeceabca78 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 13 Mar 2025 11:19:56 -0600 Subject: [PATCH 261/306] Minor fixes for the custom runecrafting implementation Fixed the exp rate for mind and fire runes. Combination runes now also get double exp like the rest of runecrafting, and all of them give the same exp as lava runes Added a message when crafting combination runes without a binding necklace. --- .../global/skill/runecrafting/CombinationRune.java | 10 +++++----- .../main/content/global/skill/runecrafting/Rune.java | 4 ++-- .../global/skill/runecrafting/RuneCraftPulse.java | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/CombinationRune.java b/Server/src/main/content/global/skill/runecrafting/CombinationRune.java index 62760bfdc..e23a78f8b 100644 --- a/Server/src/main/content/global/skill/runecrafting/CombinationRune.java +++ b/Server/src/main/content/global/skill/runecrafting/CombinationRune.java @@ -7,11 +7,11 @@ import core.game.node.item.Item; * @author 'Vexia */ public enum CombinationRune { - MIST(new Item(4695), 6, 8.0, new Altar[] { Altar.WATER, Altar.AIR }, Rune.AIR, Rune.WATER), - DUST(new Item(4696), 10, 8.3, new Altar[] { Altar.EARTH, Altar.AIR }, Rune.AIR, Rune.EARTH), - MUD(new Item(4698), 13, 9.3, new Altar[] { Altar.EARTH, Altar.WATER }, Rune.WATER, Rune.EARTH), - SMOKE(new Item(4697), 15, 8.5, new Altar[] { Altar.FIRE, Altar.AIR }, Rune.AIR, Rune.FIRE), - STEAM(new Item(4694), 19, 9.3, new Altar[] { Altar.WATER, Altar.FIRE }, Rune.WATER, Rune.FIRE), + MIST(new Item(4695), 6, 10.0, new Altar[] { Altar.WATER, Altar.AIR }, Rune.AIR, Rune.WATER), + DUST(new Item(4696), 10, 10.0, new Altar[] { Altar.EARTH, Altar.AIR }, Rune.AIR, Rune.EARTH), + MUD(new Item(4698), 13, 10.0, new Altar[] { Altar.EARTH, Altar.WATER }, Rune.WATER, Rune.EARTH), + SMOKE(new Item(4697), 15, 10.0, new Altar[] { Altar.FIRE, Altar.AIR }, Rune.AIR, Rune.FIRE), + STEAM(new Item(4694), 19, 10.0, new Altar[] { Altar.WATER, Altar.FIRE }, Rune.WATER, Rune.FIRE), LAVA(new Item(4699), 23, 10.0, new Altar[] { Altar.FIRE, Altar.EARTH }, Rune.EARTH, Rune.FIRE); /** diff --git a/Server/src/main/content/global/skill/runecrafting/Rune.java b/Server/src/main/content/global/skill/runecrafting/Rune.java index 78bd327b9..ef69a1d2f 100644 --- a/Server/src/main/content/global/skill/runecrafting/Rune.java +++ b/Server/src/main/content/global/skill/runecrafting/Rune.java @@ -10,10 +10,10 @@ import core.game.node.item.Item; */ public enum Rune { AIR(Runes.AIR_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), - MIND(Runes.MIND_RUNE.transform(), 2, 5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98, 112 }), + MIND(Runes.MIND_RUNE.transform(), 2, 5.5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98, 112 }), WATER(Runes.WATER_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), EARTH(Runes.EARTH_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), - FIRE(Runes.FIRE_RUNE.transform(), 1, 7, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), + FIRE(Runes.FIRE_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }), BODY(Runes.BODY_RUNE.transform(), 20, 7.5, new int[] { 1, 46, 92, 138 }), COSMIC(Runes.COSMIC_RUNE.transform(), 27, 8, new int[] { 1, 59, 118 }), CHAOS(Runes.CHAOS_RUNE.transform(), 35, 8.5, new int[] { 1, 74, 148 }), diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 4781983fb..819337a57 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -278,7 +278,7 @@ public final class RuneCraftPulse extends SkillPulse { int runeAmt = player.getInventory().getAmount(rune); amount = Math.min(multiplier, runeAmt); if (removeItem(player, new Item(PURE_ESSENCE.getId(), essenceAmt), Container.INVENTORY) && removeItem(player, new Item(rune.getId(), amount), Container.INVENTORY)) { - rewardXP(player, Skills.RUNECRAFTING, combo.getExperience()); + rewardXP(player, Skills.RUNECRAFTING, combo.getExperience() * 2); for (int i = 0; i < amount; i++) { if (RandomFunction.random(1, 3) == 1 || hasBindingNecklace()) { addItemOrDrop(player, combo.getRune().getId(), 1); @@ -293,6 +293,8 @@ public final class RuneCraftPulse extends SkillPulse { playAudio(player, Sounds.DESTROY_OBJECT_2381); } } + } else { + sendMessage(player, "Some of the runes are destroyed, as you are not wearing a Binding Necklace."); } // Snowscape: adding the imbue effect after crafting so that a talisman isn't required for every essence player.setAttribute("spell:imbue", GameWorld.getTicks() + 20); From 61f5120cfcbf99b4f8d00fb23946ef439ed27605 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 17 Mar 2025 08:24:43 -0600 Subject: [PATCH 262/306] Fixed attack range when attacking large creatures from certain angles When attacking a 2x2 or larger creature from the SW, attack range would be reduced. Most noticeable on halberds. Fixed by checking the closest tile when attacking from a distance. --- .../main/core/game/node/entity/combat/MagicSwingHandler.kt | 4 ++-- .../main/core/game/node/entity/combat/MeleeSwingHandler.kt | 2 +- .../main/core/game/node/entity/combat/RangeSwingHandler.kt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt index 82bf1d5d8..1838c72e1 100644 --- a/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MagicSwingHandler.kt @@ -25,9 +25,9 @@ open class MagicSwingHandler (vararg flags: SwingHandlerFlag) } var distance = 10 var type = InteractionType.STILL_INTERACT - var goodRange = victim.centerLocation.withinDistance(entity.centerLocation, getCombatDistance(entity, victim, distance)) + var goodRange = victim.getClosestOccupiedTile(entity.location).withinDistance(entity.centerLocation, getCombatDistance(entity, victim, distance)) if (victim.walkingQueue.isMoving && !goodRange) { - goodRange = victim.centerLocation.withinDistance(entity.centerLocation, getCombatDistance(entity, victim, ++distance)) + goodRange = victim.getClosestOccupiedTile(entity.location).withinDistance(entity.centerLocation, getCombatDistance(entity, victim, ++distance)) type = InteractionType.MOVE_INTERACT } if (goodRange && isAttackable(entity, victim) != InteractionType.NO_INTERACT) { diff --git a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt index b58fe0c0c..90c30e728 100644 --- a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt @@ -322,7 +322,7 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) } return victim.getSwingHandler(false).type == CombatStyle.MELEE && e.withinDistance(victim.location, 1) && victim.properties.combatPulse.getVictim() === entity && entity.index < victim.index } - return entity.centerLocation.withinDistance(victim.centerLocation, distance + (size shr 1) + (victim.size() shr 1)) + return entity.centerLocation.withinDistance(victim.getClosestOccupiedTile(entity.location), distance + (size shr 1) + (victim.size() shr 1)) } } } diff --git a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt index 7a083b748..ead12b6c3 100644 --- a/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/RangeSwingHandler.kt @@ -53,10 +53,10 @@ open class RangeSwingHandler (vararg flags: SwingHandlerFlag) : CombatSwingHandl distance = 10 } } - var goodRange = victim.centerLocation.withinDistance(entity.centerLocation, getCombatDistance(entity, victim, distance)) + var goodRange = victim.getClosestOccupiedTile(entity.location).withinDistance(entity.centerLocation, getCombatDistance(entity, victim, distance)) var type = InteractionType.STILL_INTERACT if (victim.walkingQueue.isMoving && !goodRange) { - goodRange = victim.centerLocation.withinDistance(entity.centerLocation, getCombatDistance(entity, victim, ++distance)) + goodRange = victim.getClosestOccupiedTile(entity.location).withinDistance(entity.centerLocation, getCombatDistance(entity, victim, ++distance)) type = InteractionType.MOVE_INTERACT } if (goodRange && super.canSwing(entity, victim) != InteractionType.NO_INTERACT) { From 07d8bb6a133b4ee924129bb5c481aacb1f4e9305 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 17 Mar 2025 08:53:29 -0600 Subject: [PATCH 263/306] Silver Sickle custom bonecrusher now also "buries" ashes that are dropped by enemies. --- Server/src/main/content/global/skill/prayer/Bones.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Server/src/main/content/global/skill/prayer/Bones.kt b/Server/src/main/content/global/skill/prayer/Bones.kt index 755a8062b..0917df2cb 100644 --- a/Server/src/main/content/global/skill/prayer/Bones.kt +++ b/Server/src/main/content/global/skill/prayer/Bones.kt @@ -28,6 +28,7 @@ enum class Bones( */ val bonemealId: Int?, ) { + ASHES(Items.ASHES_592, 4.5, null), //Snowscape: added ashes so the bonecrusher feature gives prayer exp. Ashes cannot be bured normally. BONES(Items.BONES_526, 4.5, Items.BONEMEAL_4255), BONES_2(Items.BONES_2530, 4.5, Items.BONEMEAL_4255), BONES_3(Items.BONES_3187, 4.5, Items.BONEMEAL_4255), From d02b16d970d581cfb1c534eea84fc002702ad554 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 17 Mar 2025 10:19:17 -0600 Subject: [PATCH 264/306] Selecting "Make 10" on crafting dragonhide gear now makes 30. --- .../content/global/skill/crafting/LeatherCraftDialogue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/crafting/LeatherCraftDialogue.java b/Server/src/main/content/global/skill/crafting/LeatherCraftDialogue.java index 0692339a6..65fa4ae71 100644 --- a/Server/src/main/content/global/skill/crafting/LeatherCraftDialogue.java +++ b/Server/src/main/content/global/skill/crafting/LeatherCraftDialogue.java @@ -196,7 +196,7 @@ public final class LeatherCraftDialogue extends DialoguePlugin { case 5: case 9: case 13: - amt = 10; + amt = 30; break; case 4: case 8: From a5eb1ea9298cb2a1660943171f8a2b68ad139cfe Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 17 Mar 2025 10:42:24 -0600 Subject: [PATCH 265/306] Elemental Battlestaves can optionally be crafted with a Dramen staff instead of a Battlestaff --- .../content/global/skill/crafting/BattlestaffListener.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/skill/crafting/BattlestaffListener.kt b/Server/src/main/content/global/skill/crafting/BattlestaffListener.kt index 54a82b557..bb31a0689 100644 --- a/Server/src/main/content/global/skill/crafting/BattlestaffListener.kt +++ b/Server/src/main/content/global/skill/crafting/BattlestaffListener.kt @@ -10,11 +10,11 @@ import kotlin.math.min class BattlestaffListener : InteractionListener { - private val battlestaff = Items.BATTLESTAFF_1391 + private val battlestaff = intArrayOf(Items.BATTLESTAFF_1391, Items.DRAMEN_STAFF_772) val orbs = BattlestaffProduct.values().map { it.requiredOrbItemId }.toIntArray() override fun defineListeners() { - onUseWith(IntType.ITEM, orbs, battlestaff) { player, used, with -> + onUseWith(IntType.ITEM, orbs, *battlestaff) { player, used, with -> val product = BattlestaffProduct.productMap[used.id] ?: return@onUseWith true if (!hasLevelDyn(player, Skills.CRAFTING, product.minimumLevel)) { @@ -25,7 +25,7 @@ class BattlestaffListener : InteractionListener { // Avoids sending dialogue if only one can be created if (amountInInventory(player, used.id) == 1 || amountInInventory(player, with.id) == 1) { - if (removeItem(player, product.requiredOrbItemId) && removeItem(player, Items.BATTLESTAFF_1391)) { + if (removeItem(player, product.requiredOrbItemId) && removeItem(player, with.id)) { addItem(player, product.producedItemId, product.amountProduced) rewardXP(player, Skills.CRAFTING, product.experience) } @@ -44,7 +44,7 @@ class BattlestaffListener : InteractionListener { runTask(player, 2, amount) { if (amount < 1) return@runTask - if (removeItem(player, product.requiredOrbItemId) && removeItem(player, Items.BATTLESTAFF_1391)) { + if (removeItem(player, product.requiredOrbItemId) && removeItem(player, with.id)) { addItem(player, product.producedItemId, product.amountProduced) rewardXP(player, Skills.CRAFTING, product.experience) } From 7be39c73b9c11ff9d79a8698d799bc0418208c82 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 17 Mar 2025 15:48:40 -0600 Subject: [PATCH 266/306] All satchels now autoloot items they can hold The plain satchel, due to its ability to carry any item, will only loot items that already exist in the satchel. --- .../handlers/item/SnowscapeSatchelListener.kt | 2 +- .../game/node/entity/npc/drop/NPCDropTables.java | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt index d2eed85fc..7df3b7d74 100755 --- a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -133,7 +133,7 @@ class SnowscapeSatchelListener : InteractionListener { return satchel!! } - // Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on the Red Satchel if the player has one + // Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on satchels the player is carrying. fun isAllowed(player: Player, satchelId: Int, itemId: Int): Boolean { when (satchelId) { plainSatchelId -> return itemId !in satchelIds diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index e971313df..07a58af70 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -271,12 +271,17 @@ public final class NPCDropTables { return true; } - //Snowscape modification: loot certain items into the red satchel if carried + //Snowscape modification: loot certain items into the satchels if carried private boolean handleSatchel(Player player, Item item) { - if (inEquipmentOrInventory(player,10879,1)){ - if (SnowscapeSatchelListener.Companion.isAllowed(player,10879,item.getId()) && player.redSatchel.add(item)) { - player.sendMessage("Your red satchel stashed " + item.getAmount() + " " + item.getName() + "."); - return true; + for (int satchelId = 10877; satchelId <= 10882; satchelId++) { + if (inEquipmentOrInventory(player,satchelId,1) && SnowscapeSatchelListener.Companion.isAllowed(player,satchelId,item.getId())){ + if (satchelId == 10877 && !player.plainSatchel.contains(item.getId(),1)) { + continue; + } + if (SnowscapeSatchelListener.Companion.getSatchel(player, satchelId).add(unnote(item))) { + player.sendMessage("Your " + new Item(satchelId).getName() + " stashed " + item.getAmount() + " " + item.getName() + "."); + return true; + } } } return false; From 4991b07ff81fc5cbcd8088f7559915fc821f599d Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 21 Mar 2025 14:59:52 -0600 Subject: [PATCH 267/306] Changes to Gold Satchel Only coal will be used from the satchel when smelting, the other ores must be in the inventory (to prevent smelting more than you can carry). Bars and gems (cut and uncut) can now also be stored in the satchel. --- .../global/handlers/item/SnowscapeSatchelListener.kt | 4 ++-- .../global/skill/smithing/smelting/SmeltingPulse.java | 10 ++++++---- .../core/game/node/entity/npc/drop/NPCDropTables.java | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt index 7df3b7d74..d2fb6fbac 100755 --- a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -138,9 +138,9 @@ class SnowscapeSatchelListener : InteractionListener { when (satchelId) { plainSatchelId -> return itemId !in satchelIds greenSatchelId -> return (Item(itemId).getName().contains(" seed") || Item(itemId).getName().contains("Grimy") || Item(itemId).getName().contains("Clean ")) - redSatchelId -> return itemId in intArrayOf(12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168) || Item(itemId).getName().equals("Clue scroll") + redSatchelId -> return itemId in intArrayOf(*(12158..12168).toList().toIntArray()) || Item(itemId).getName().equals("Clue scroll") blackSatchelId -> return itemId in intArrayOf(995) - goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892) + goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892,2349,2351,2353,2355,2357,2359,2361,2363,2365,1601,1603,1605,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625,1627,1629,1631,6571,6573) runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566) || (getAttribute(player,"snowscape:boostedmode",false) && itemId in intArrayOf(556,555,557,554,4694,4695,4696,4697,4698,4699)) } return false diff --git a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java index e3e06df64..fc5e01696 100644 --- a/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java +++ b/Server/src/main/content/global/skill/smithing/smelting/SmeltingPulse.java @@ -99,10 +99,12 @@ public class SmeltingPulse extends SkillPulse { return false; } for (Item item : bar.getOres()) { - //Snowscape modification: check gold satchel for ores as well, if carried - if (!player.getInventory().contains(item.getId(), item.getAmount()) && !(inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(item.getId(), item.getAmount()))) { - player.getPacketDispatch().sendMessage("You do not have the required ores to make this bar."); - return false; + //Snowscape modification: check gold satchel for coal as well, if carried + if (!player.getInventory().contains(item.getId(), item.getAmount())) { + if (!(item.getId() == Items.COAL_453 && inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(item.getId(), item.getAmount()))) { + player.getPacketDispatch().sendMessage("You do not have the required ores to make this bar."); + return false; + } } } return true; diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 07a58af70..4f55c9bd1 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -274,7 +274,7 @@ public final class NPCDropTables { //Snowscape modification: loot certain items into the satchels if carried private boolean handleSatchel(Player player, Item item) { for (int satchelId = 10877; satchelId <= 10882; satchelId++) { - if (inEquipmentOrInventory(player,satchelId,1) && SnowscapeSatchelListener.Companion.isAllowed(player,satchelId,item.getId())){ + if (inEquipmentOrInventory(player,satchelId,1) && SnowscapeSatchelListener.Companion.isAllowed(player,satchelId,unnote(item).getId())){ if (satchelId == 10877 && !player.plainSatchel.contains(item.getId(),1)) { continue; } From 4799069ebd9455afbbef9288152ef0a4ae068e43 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 22 Mar 2025 21:23:28 -0600 Subject: [PATCH 268/306] Summoning rework Pouches are not consumed. Points are not lost when summoning. However, lifespan is directly tied to summoning points, and the familiar despawns at zero points. Created a new pouch storage that can be accessed from the summoning tab by pressing "call pet" when no familiar is active. This allows freely switching familiars as long as points are maintained. Special move points start at empty instead of full, and replenish 1 point every 3 ticks instead of 15 points every 50 ticks. --- .../skill/summoning/SummoningTabListener.kt | 5 +- .../familiar/BurdenInterfacePlugin.java | 4 + .../skill/summoning/familiar/Familiar.java | 23 +++-- .../summoning/familiar/FamiliarManager.java | 28 ++++-- .../familiar/SnowscapeFamiliarInterface.kt | 96 +++++++++++++++++++ Server/src/main/core/api/utils/Permadeath.kt | 1 + .../core/game/node/entity/player/Player.java | 2 + .../player/info/login/PlayerSaveParser.kt | 2 + .../entity/player/info/login/PlayerSaver.kt | 2 + .../entity/player/link/InterfaceManager.java | 8 +- 10 files changed, 147 insertions(+), 24 deletions(-) create mode 100644 Server/src/main/content/global/skill/summoning/familiar/SnowscapeFamiliarInterface.kt diff --git a/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt b/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt index c47862b62..ee39b8470 100644 --- a/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt +++ b/Server/src/main/content/global/skill/summoning/SummoningTabListener.kt @@ -4,6 +4,8 @@ import content.global.skill.summoning.pet.Pet import core.api.sendMessage import core.game.interaction.InterfaceListener +import content.global.skill.summoning.familiar.SnowscapeFamiliarInterface + class SummoningTabListener : InterfaceListener { override fun defineInterfaceListeners() { on(662) { player, _, opcode, buttonID, _, _ -> @@ -12,7 +14,8 @@ class SummoningTabListener : InterfaceListener { if (player.familiarManager.hasFamiliar()) { player.familiarManager.familiar.call() } else { - player.getPacketDispatch().sendMessage("You don't have a follower.") + SnowscapeFamiliarInterface.Companion.openInterface(player) + //player.getPacketDispatch().sendMessage("You don't have a follower.") } } 67 -> { diff --git a/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java b/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java index 275b4abf5..84de00f93 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java +++ b/Server/src/main/content/global/skill/summoning/familiar/BurdenInterfacePlugin.java @@ -32,6 +32,10 @@ public final class BurdenInterfacePlugin extends ComponentPlugin { if (getAttribute(player, "openSatchel", null) != null) { SnowscapeSatchelListener.Companion.satchelInterfaceAction(player, component, opcode, button, slot, itemId); return true; + } + if (getAttribute(player, "openSummonStorage", false)) { + SnowscapeFamiliarInterface.Companion.interfaceAction(player, component, opcode, button, slot, itemId); + return true; } if (!player.getFamiliarManager().hasFamiliar() || !player.getFamiliarManager().getFamiliar().isBurdenBeast()) { return false; diff --git a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java index 064de882c..636787050 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/Familiar.java +++ b/Server/src/main/content/global/skill/summoning/familiar/Familiar.java @@ -36,6 +36,8 @@ import java.util.List; import static core.api.ContentAPIKt.*; +import core.game.component.Component; + /** * Represents a familiar. * @author Emperor @@ -80,7 +82,7 @@ public abstract class Familiar extends NPC implements Plugin { /** * The amount of special points left. */ - protected int specialPoints = 60; + protected int specialPoints = 0; /** * The pouch id. @@ -178,7 +180,7 @@ public abstract class Familiar extends NPC implements Plugin { this.pointsPerTick = 0.0; } else { //int drain = pouch.getLevelRequired() - pouch.getSummonCost() + 1; - // Snowscape: removing the initial drain and making it drain over the life of the familiar. Removing the +1 makes the final drain happen on the last tick of the familiar's life. That works for our new system, as the familiar timer won't start until that final tick happens. + // Snowscape: removing the initial drain and making it drain over the life of the familiar. Removing the +1 makes the final drain happen on the last tick of the familiar's life. That works for our new system. int drain = pouch.getLevelRequired(); this.pointsPerTick = (double) drain / maximumTicks; } @@ -225,21 +227,20 @@ public abstract class Familiar extends NPC implements Plugin { @Override public void handleTickActions() { - //Snowscape: only count down the familiar timer if summoning points are zero, and give some summoning exp every minute a familiar is summoned. - if (owner.getSkills().getLevel(Skills.SUMMONING) == 0) { - ticks--; - } + //Snowscape: ticks are calculated from the summoning points (including fractional drain), so the familiar will despawn when points reach zero, but the timer goes up if points are restored + //ticks--; + ticks = Double.valueOf(maximumTicks*(owner.getSkills().getLevel(Skills.SUMMONING)-fracDrain)/pouch.getLevelRequired()).intValue(); if (getWorldTicks() % 100 == 0) { owner.getSkills().addExperience(Skills.SUMMONING, pouch.getLevelRequired()+10, true); } fracDrain += pointsPerTick; - if (fracDrain > 1.0 && ticks > 0) { + if (fracDrain > 1.0) { fracDrain -= 1.0; owner.getSkills().updateLevel(Skills.SUMMONING, -1, 0); } - if (ticks % 50 == 0) { - updateSpecialPoints(-15); + if (getWorldTicks() % 3 == 0) { + updateSpecialPoints(-1); if (!getText().isEmpty()) { super.sendChat(getText()); } @@ -258,6 +259,7 @@ public abstract class Familiar extends NPC implements Plugin { } else { owner.getPacketDispatch().sendMessage("Your familiar has vanished."); } + playAudio(owner, Sounds.PRAYER_DRAIN_2672); dismiss(); return; } @@ -665,7 +667,8 @@ public abstract class Familiar extends NPC implements Plugin { setVarp(owner, 1175, 182986); setVarp(owner, 1174, -1); owner.getAppearance().sync(); - owner.getInterfaceManager().setViewedTab(3); + owner.getInterfaceManager().openTab(new Component(662)); + owner.getInterfaceManager().setViewedTab(7); } /** diff --git a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java index 94802a146..c9a9cb9fa 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java +++ b/Server/src/main/content/global/skill/summoning/familiar/FamiliarManager.java @@ -142,7 +142,13 @@ public final class FamiliarManager { ((BurdenBeast) familiar).container.parse(famInv); } familiar.setAttribute("hp",Integer.parseInt( currentFamiliar.get("lifepoints").toString())); - } + } else { + //Snowscape: Copied from Familiar.dismiss(), this clears the fields on the summoning tab if no familiar is loaded + setVarp(player, 448, -1); + setVarp(player, 1176, 0); + setVarp(player, 1175, 182986); + setVarp(player, 1174, -1); + } } /** @@ -164,12 +170,12 @@ public final class FamiliarManager { public void summon(Item item, boolean pet, boolean deleteItem) { boolean renew = false; if (hasFamiliar()) { - if (familiar.getPouchId() == item.getId()) { - renew = true; - } else { + //if (familiar.getPouchId() == item.getId()) { + // renew = true; + //} else { player.getPacketDispatch().sendMessage("You already have a follower."); return; - } + //} } if (player.getZoneMonitor().isRestricted(ZoneRestriction.FOLLOWERS) && !player.getLocks().isLocked("enable_summoning")) { player.getPacketDispatch().sendMessage("This is a Summoning-free area."); @@ -193,6 +199,10 @@ public final class FamiliarManager { return; } */ + if (player.getSkills().getLevel(Skills.SUMMONING) < 1) { + player.getPacketDispatch().sendMessage("You need at least one Summoning point to summon this familiar."); + return; + } final int npcId = pouch.getNpcId(); Familiar fam = !renew ? FAMILIARS.get(npcId) : familiar; if (fam == null) { @@ -207,11 +217,11 @@ public final class FamiliarManager { return; } } - if (!player.getInventory().remove(item)) { - return; - } + //if (!player.getInventory().remove(item)) { + // return; + //} //player.getSkills().updateLevel(Skills.SUMMONING, -pouch.getSummonCost(), 0); - player.getSkills().addExperience(Skills.SUMMONING, pouch.getSummonExperience()); + //player.getSkills().addExperience(Skills.SUMMONING, pouch.getSummonExperience()); if (!renew) { familiar = fam; spawnFamiliar(); diff --git a/Server/src/main/content/global/skill/summoning/familiar/SnowscapeFamiliarInterface.kt b/Server/src/main/content/global/skill/summoning/familiar/SnowscapeFamiliarInterface.kt new file mode 100644 index 000000000..388b746a0 --- /dev/null +++ b/Server/src/main/content/global/skill/summoning/familiar/SnowscapeFamiliarInterface.kt @@ -0,0 +1,96 @@ +package content.global.skill.summoning.familiar + +import core.api.* +import core.game.container.Container +import content.global.skill.summoning.familiar.BurdenContainerListener +//import core.game.node.Node +import core.game.node.entity.player.Player +import core.game.node.item.Item +//import core.game.interaction.InteractionListener +//import core.game.interaction.IntType +//import org.json.simple.JSONArray +//import org.json.simple.JSONObject +//import org.json.simple.parser.JSONParser +import org.rs09.consts.Items + +import core.game.component.Component +import core.game.component.CloseEvent +import core.game.container.access.InterfaceContainer + +/* Custom Snowscape class. Allows storing summoning pouches in a special storage that can be accessed by using the "call familiar" button when no familiars are summoned. +* Familiars can be summoned from this storage. +* Designed around the snowscape summoning rework, where pouches are not consumed when summoning +*/ + +class SnowscapeFamiliarInterface { + companion object { + + + //Function to handle constructing the interface + public fun openInterface(player: Player) { + val storage = player.summoningPouches + if (storage.getListeners().count() < 1) storage.register(BurdenContainerListener(player)) + + player.getInterfaceManager().open(Component(671)).setCloseEvent(CloseEvent { player, component -> + player.getInterfaceManager().closeSingleTab() + removeAttribute(player, "openSummonStorage") + //Summoning tab cannot be interacted with until it's closed and re-opened for some reason + player.getInterfaceManager().removeTabs(7) + player.getInterfaceManager().openTab(Component(662)) + player.getInterfaceManager().setViewedTab(7) + return@CloseEvent true + } + ) + setAttribute(player, "openSummonStorage", true) + storage.shift() + player.getInterfaceManager().openSingleTab(Component(665)) + InterfaceContainer.generateItems(player, player.getInventory().toArray(), arrayOf("Add"),665,0,7,4,93) + InterfaceContainer.generateItems(player, storage.toArray(), arrayOf("Remove","Summon"),671,27,5,6,30) + } + + + fun interfaceAction(player: Player, component: Component, opcode: Int, button: Int, slot: Int, itemId: Int) { + val inventory = component.getId() == 665 + val container = if (inventory) player.getInventory() else player.summoningPouches + val item = if (slot >= 0 && slot < container.capacity()) container.get(slot) else null + if (item == null && button != 29) return + + if (opcode == 9) player.sendMessage(item!!.getDefinition().getExamine()) + + if (inventory) { + when (opcode) { + 155 -> addPouch(player, item!!) + } + } else { + when (opcode) { + 155 -> if (button != 29) summonPouch(player, item!!) + 196 -> removePouch(player, item!!) + } + } + } + + private fun addPouch(player: Player, item: Item) { + if (!hasOption(item, "Summon")){ + sendMessage(player, "You can only add summoning pouches.") + return + } else if (player.summoningPouches.containsItem(item)) { + sendMessage(player, "You have already added this familiar's pouch.") + return + } else if (player.summoningPouches.add(item)) { + player.getInventory().remove(item) + } + } + + private fun removePouch(player: Player, item: Item) { + if (player.getInventory().add(item)) { + player.summoningPouches.remove(item) + } + } + + private fun summonPouch(player: Player, item: Item) { + player.getInterfaceManager().close() + SummonFamiliarPlugin().handle(player, item, "summon") + } + + } +} \ No newline at end of file diff --git a/Server/src/main/core/api/utils/Permadeath.kt b/Server/src/main/core/api/utils/Permadeath.kt index 1e7f13e9f..cbd442bc7 100644 --- a/Server/src/main/core/api/utils/Permadeath.kt +++ b/Server/src/main/core/api/utils/Permadeath.kt @@ -49,6 +49,7 @@ fun permadeath(target: Player) { target.goldSatchel.clear() target.runeSatchel.clear() target.blackSatchel.clear() + target.summoningPouches.clear() // Skills target.skills = Skills(target) diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 06436975c..6416acb37 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -319,6 +319,8 @@ public class Player extends Entity { public final Container blackSatchel = new Container(30, ContainerType.ALWAYS_STACK); public final Container goldSatchel = new Container(30, ContainerType.ALWAYS_STACK); public final Container runeSatchel = new Container(30, ContainerType.ALWAYS_STACK); + // The summoning pouch storage + public final Container summoningPouches = new Container(30); /** * Constructs a new {@code Player} {@code Object}. diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index cb0e151f4..2e661c782 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -387,6 +387,8 @@ class PlayerSaveParser(val player: Player) { val runeSatchel = snowscapeData["runeSatchel"] if (runeSatchel != null) player.runeSatchel.parse(runeSatchel as JSONArray) + val summoningPouches = snowscapeData["summoningPouches"] + if (summoningPouches != null) player.summoningPouches.parse(summoningPouches as JSONArray) } } diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 1f1e3d566..15ab459af 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -656,6 +656,8 @@ class PlayerSaver (val player: Player){ snowscapeData.put("goldSatchel", saveContainer(player.goldSatchel)) snowscapeData.put("runeSatchel", saveContainer(player.runeSatchel)) + snowscapeData.put("summoningPouches", saveContainer(player.summoningPouches)) + root.put("snowscape_data",snowscapeData) } } diff --git a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java index 4a0fb00ae..eaa9ca5da 100644 --- a/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java +++ b/Server/src/main/core/game/node/entity/player/link/InterfaceManager.java @@ -358,9 +358,9 @@ public final class InterfaceManager { openTab(6, new Component(player.getSpellBookManager().getSpellBook())); // Magic break; case 7: - if (player.getFamiliarManager().hasFamiliar()) { + //if (player.getFamiliarManager().hasFamiliar()) { openTab(7, new Component(662)); - } + //} break; default: openTab(i, new Component(DEFAULT_TABS[i])); @@ -393,9 +393,9 @@ public final class InterfaceManager { openTab(4, new Component(Components.WORNITEMS_387)); // Equipment openTab(5, new Component(Components.PRAYER_271)); // Prayer openTab(6, new Component(player.getSpellBookManager().getSpellBook())); // Magic - if (player.getFamiliarManager().hasFamiliar()) { + //if (player.getFamiliarManager().hasFamiliar()) { openTab(7, new Component(Components.LORE_STATS_SIDE_662)); // summoning. - } + //} openTab(8, new Component(Components.FRIENDS2_550)); // Friends openTab(9, new Component(Components.IGNORE2_551)); // Ignores openTab(10, new Component(Components.CLANJOIN_589)); // Clan chat From 0622aed00cb61ab912166683ff01a38444044f44 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 25 Mar 2025 09:28:14 +0000 Subject: [PATCH 269/306] Fixed incorrect items in circulation Corrected incorrect rune kite (h) Corrected incorrect adamant kite (h) Corrected incorrect lamps Corrected incorrect blurberry specials --- .../quest/deathplateau/HaroldDialogueFile.kt | 8 +------- Server/src/main/core/ServerConstants.kt | 2 +- .../entity/player/info/login/SaveVersionHooks.kt | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt index 005206e10..e4242212b 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt +++ b/Server/src/main/content/region/asgarnia/burthorpe/quest/deathplateau/HaroldDialogueFile.kt @@ -109,15 +109,9 @@ class HaroldDialogueFile : DialogueFile() { 21 -> playerl(FacialExpression.ASKING, "What?").also { stage++ } 22 -> npcl(FacialExpression.FRIENDLY, "I really fancy one of those Blurberry Specials. I never get over to the Gnome Stronghold so I haven't had one for ages!").also { stage++ } 23 -> { - if (removeItem(player!!, Items.BLURBERRY_SPECIAL_2064)) { + if (removeItem(player!!, Items.BLURBERRY_SPECIAL_2064) || removeItem(player!!, Items.PREMADE_BLURB_SP_2028)) { sendMessage(player!!, "You give Harold a Blurberry Special.") sendItemDialogue(player!!, Items.BLURBERRY_SPECIAL_2064, "You give Harold a Blurberry Special.").also { stage++ } - } else if (removeItem(player!!, Items.BLURBERRY_SPECIAL_9520)) { // This should not be here since 9520 is used by the gnome restaurant minigame. - sendMessage(player!!, "You give Harold a Blurberry Special.") - sendItemDialogue(player!!, Items.BLURBERRY_SPECIAL_2064, "You give Harold a Blurberry Special.").also { stage++ } - } else if (removeItem(player!!, Items.PREMADE_BLURB_SP_2028)) { - sendMessage(player!!, "You give Harold a Blurberry Special.") - sendItemDialogue(player!!, Items.PREMADE_BLURB_SP_2028, "You give Harold a Blurberry Special.").also { stage++ } } else { player(FacialExpression.FRIENDLY, "I'll go and get you one.").also { stage = END_DIALOGUE } } diff --git a/Server/src/main/core/ServerConstants.kt b/Server/src/main/core/ServerConstants.kt index 26923a269..30a6ab377 100644 --- a/Server/src/main/core/ServerConstants.kt +++ b/Server/src/main/core/ServerConstants.kt @@ -18,7 +18,7 @@ class ServerConstants { var NOAUTH_DEFAULT_ADMIN: Boolean = true @JvmField - var CURRENT_SAVEFILE_VERSION = 3 + var CURRENT_SAVEFILE_VERSION = 4 @JvmField var DAILY_ACCOUNT_LIMIT = 3 diff --git a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt index fe26b8b8f..f1d5e4819 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/SaveVersionHooks.kt @@ -81,6 +81,22 @@ class SaveVersionHooks : LoginListener { } } + if (player.version < 4) { //GL !2065 + replaceAllItems(player, Items.BLURBERRY_SPECIAL_9520, Items.BLURBERRY_SPECIAL_2064) + replaceAllItems(player, Items.BLURBERRY_SPECIAL_9521, Items.BLURBERRY_SPECIAL_2065) + replaceAllItems(player, Items.LAMP_6796, Items.LAMP_2528) + replaceAllItems(player, Items.RUNE_SHIELDH1_10667, Items.RUNE_SHIELDH1_7336) + replaceAllItems(player, Items.RUNE_SHIELDH2_10670, Items.RUNE_SHIELDH2_7342) + replaceAllItems(player, Items.RUNE_SHIELDH3_10673, Items.RUNE_SHIELDH3_7348) + replaceAllItems(player, Items.RUNE_SHIELDH4_10676, Items.RUNE_SHIELDH4_7354) + replaceAllItems(player, Items.RUNE_SHIELDH5_10679, Items.RUNE_SHIELDH5_7360) + replaceAllItems(player, Items.ADAMANT_SHIELDH1_10666, Items.ADAMANT_SHIELDH1_7334) + replaceAllItems(player, Items.ADAMANT_SHIELDH2_10669, Items.ADAMANT_SHIELDH2_7340) + replaceAllItems(player, Items.ADAMANT_SHIELDH3_10672, Items.ADAMANT_SHIELDH3_7346) + replaceAllItems(player, Items.ADAMANT_SHIELDH4_10675, Items.ADAMANT_SHIELDH4_7352) + replaceAllItems(player, Items.ADAMANT_SHIELDH5_10678, Items.ADAMANT_SHIELDH5_7358) + } + // Finish up player.version = ServerConstants.CURRENT_SAVEFILE_VERSION } From 63f8ec3cbfbcc7f0b7a42edbbc8c67b6298fec07 Mon Sep 17 00:00:00 2001 From: Lucid Enigma Date: Tue, 25 Mar 2025 09:37:26 +0000 Subject: [PATCH 270/306] Fixed facial expressions in dialogue for Tree Gnome Village NPCs --- .../quest/tree/CommanderMontaiDialogue.kt | 53 ++++++------ .../kandarin/quest/tree/ElkoyDialogue.kt | 57 ++++++------- .../kandarin/quest/tree/KingBolrenDialogue.kt | 81 ++++++++++--------- .../quest/tree/LieutenantSchepburDialogue.kt | 9 ++- .../kandarin/quest/tree/LocalGnomeDialogue.kt | 3 +- .../kandarin/quest/tree/RemsaiDialogue.kt | 15 ++-- .../quest/tree/TrackerGnomeOneDialogue.kt | 11 +-- .../quest/tree/TrackerGnomeThreeDialogue.kt | 21 ++--- .../quest/tree/TrackerGnomeTwoDialogue.kt | 17 ++-- 9 files changed, 138 insertions(+), 129 deletions(-) diff --git a/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt index cc79075df..e758479a2 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/CommanderMontaiDialogue.kt @@ -4,6 +4,7 @@ import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class CommanderMontaiDialogue : DialogueFile(){ @@ -12,19 +13,19 @@ class CommanderMontaiDialogue : DialogueFile(){ if (questStage == 10) { when(stage) { 0 -> playerl("Hello.").also { stage++ } - 1 -> npcl("Hello traveller, are you here to help or just to watch?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello traveller, are you here to help or just to watch?").also { stage++ } 2 -> playerl("I've been sent by King Bolren to retrieve the orb of protection.").also { stage++ } - 3 -> npcl("Excellent we need all the help we can get.").also { stage++ } - 4 -> npcl("I'm Commander Montai. The orb is in the Khazard stronghold to the north, but until we weaken their defences we can't get close.").also { stage++ } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Excellent we need all the help we can get.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "I'm Commander Montai. The orb is in the Khazard stronghold to the north, but until we weaken their defences we can't get close.").also { stage++ } 5 -> playerl("What can I do?").also { stage++ } - 6 -> npcl("Firstly we need to strengthen our own defences. We desperately need wood to make more battlements, once the battlements are gone it's all over. Six loads of normal logs should do it.").also { stage++ } + 6 -> npcl(FacialExpression.OLD_NORMAL, "Firstly we need to strengthen our own defences. We desperately need wood to make more battlements, once the battlements are gone it's all over. Six loads of normal logs should do it.").also { stage++ } 7 -> options("Ok, I'll gather some wood.", "Sorry, I no longer want to be involved.").also { stage++ } 8 -> when (buttonID) { 1 -> playerl("Ok, I'll gather some wood.").also { stage = 10 } 2 -> playerl("Sorry, I no longer want to be involved.").also { stage = 9 } } - 9 -> npcl("That's a shame, we could have done with your help.").also { stage = END_DIALOGUE } - 10 -> npcl("Please be as quick as you can, I don't know how much longer we can hold out.").also { + 9 -> npcl(FacialExpression.OLD_NORMAL, "That's a shame, we could have done with your help.").also { stage = END_DIALOGUE } + 10 -> npcl(FacialExpression.OLD_NORMAL, "Please be as quick as you can, I don't know how much longer we can hold out.").also { setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 20) stage = END_DIALOGUE } @@ -33,43 +34,43 @@ class CommanderMontaiDialogue : DialogueFile(){ if(inInventory(player!!, Items.LOGS_1511,6)){ when(stage) { 0 -> playerl("Hello.").also { stage++ } - 1 -> npcl("Hello again, we're still desperate for wood soldier.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello again, we're still desperate for wood soldier.").also { stage++ } 2 -> playerl("I have some here. (You give six loads of logs to the commander.)").also{ stage++ } 3 -> { // Remove the 6 normal logs for(i in 1..6) { removeItem(player!!,Items.LOGS_1511) } setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 25) - npcl("That's excellent, now we can make more defensive battlements. Give me a moment to organize the troops and then come speak to me. I'll inform you of our next phase of attack.") + npcl(FacialExpression.OLD_NORMAL, "That's excellent, now we can make more defensive battlements. Give me a moment to organize the troops and then come speak to me. I'll inform you of our next phase of attack.") stage = END_DIALOGUE } } } else { when(stage) { 0 -> playerl("Hello.").also { stage++ } - 1 -> npcl("Hello again, we're still desperate for wood soldier. We need six loads of normal logs.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello again, we're still desperate for wood soldier. We need six loads of normal logs.").also { stage++ } 2 -> playerl("I'll see what I can do.").also { stage++ } - 3 -> npcl("Thank you.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Thank you.").also { stage = END_DIALOGUE } } } } else if (questStage == 25) { when(stage) { 0 -> playerl("How are you doing Montai?").also { stage++ } - 1 -> npcl("We're hanging in there soldier. For the next phase of our attack we need to breach their stronghold.").also { stage++ } - 2 -> npcl("The ballista can break through the stronghold wall, and then we can advance and seize back the orb.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "We're hanging in there soldier. For the next phase of our attack we need to breach their stronghold.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "The ballista can break through the stronghold wall, and then we can advance and seize back the orb.").also { stage++ } 3 -> playerl("So what's the problem?").also { stage++ } - 4 -> npcl("From this distance we can't get an accurate enough shot. We need the correct coordinates of the stronghold for a direct hit. I've sent out three tracker gnomes to gather them.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "From this distance we can't get an accurate enough shot. We need the correct coordinates of the stronghold for a direct hit. I've sent out three tracker gnomes to gather them.").also { stage++ } 5 -> playerl("Have they returned?").also { stage++ } - 6 -> npcl("I'm afraid not, and we're running out of time. I need you to go into the heart of the battlefield, find the trackers, and bring back the coordinates.").also { stage++ } - 7 -> npcl("Do you think you can do it?").also { stage++ } + 6 -> npcl(FacialExpression.OLD_NORMAL, "I'm afraid not, and we're running out of time. I need you to go into the heart of the battlefield, find the trackers, and bring back the coordinates.").also { stage++ } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Do you think you can do it?").also { stage++ } 8 -> options("No, I've had enough of your battle.", "I'll try my best.").also { stage++ } 9 -> when(buttonID) { 1 -> playerl("No, I've had enough of your battle.").also { stage = 10 } 2 -> playerl("I'll try my best.").also { stage = 11 } } - 10 -> npcl("I understand, this isn't your fight.").also { stage = END_DIALOGUE } - 11 -> npcl("Thank you, you're braver than most.").also { stage++ } - 12 -> npcl("I don't know how long I will be able to hold out. Once you have the coordinates come back and fire the ballista right into those monsters.").also { stage++ } - 13 -> npcl("If you can retrieve the orb and bring safety back to my people, none of the blood spilled on this field will be in vain.").also { + 10 -> npcl(FacialExpression.OLD_NORMAL, "I understand, this isn't your fight.").also { stage = END_DIALOGUE } + 11 -> npcl(FacialExpression.OLD_NORMAL, "Thank you, you're braver than most.").also { stage++ } + 12 -> npcl(FacialExpression.OLD_NORMAL, "I don't know how long I will be able to hold out. Once you have the coordinates come back and fire the ballista right into those monsters.").also { stage++ } + 13 -> npcl(FacialExpression.OLD_NORMAL, "If you can retrieve the orb and bring safety back to my people, none of the blood spilled on this field will be in vain.").also { setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 30) stage = END_DIALOGUE } @@ -77,29 +78,29 @@ class CommanderMontaiDialogue : DialogueFile(){ } else if (questStage == 30) { when(stage) { 0 -> playerl("Hello.").also { stage++ } - 1 -> npcl("Hello warrior. We need the coordinates for a direct hit from the ballista.").also { stage++ } - 2 -> npcl("Once you have a direct hit you will be able to enter the stronghold and retrieve the orb.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello warrior. We need the coordinates for a direct hit from the ballista.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "Once you have a direct hit you will be able to enter the stronghold and retrieve the orb.").also { stage = END_DIALOGUE } } } else if (questStage == 31) { if(inInventory(player!!,Items.ORB_OF_PROTECTION_587)){ when(stage) { 0 -> playerl("I have the orb of protection.").also { stage++ } - 1 -> npcl("Incredible, for a human you really are something.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_HAPPY, "Incredible, for a human you really are something.").also { stage++ } 2 -> playerl("Thanks... I think!").also { stage++ } - 3 -> npcl("I'll stay here with my troops and try and hold Khazard's men back. You return the orb to the gnome village. Go as quick as you can, the village is still unprotected.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_NORMAL, "I'll stay here with my troops and try and hold Khazard's men back. You return the orb to the gnome village. Go as quick as you can, the village is still unprotected.").also { stage = END_DIALOGUE } } } else { when(stage) { 0 -> playerl("I've breached the stronghold.").also { stage++ } - 1 -> npcl("I saw, that was a beautiful sight. The Khazard troops didn't know what hit them.").also { stage++ } - 2 -> npcl("Now is the time to retrieve the orb. It's all in your hands. I'll be praying for you.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "I saw, that was a beautiful sight. The Khazard troops didn't know what hit them.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "Now is the time to retrieve the orb. It's all in your hands. I'll be praying for you.").also { stage = END_DIALOGUE } } } } else if (questStage != 0){ when(stage) { 0 -> playerl("Hello Montai, how are you?").also { stage++ } - 1 -> npcl("I'm ok, this battle is going to take longer to win than I expected. The Khazard troops won't give up even without the orb.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "I'm ok, this battle is going to take longer to win than I expected. The Khazard troops won't give up even without the orb.").also { stage++ } 2 -> playerl("Hang in there.").also { stage = END_DIALOGUE } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt index 135624829..708033a0d 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/ElkoyDialogue.kt @@ -11,6 +11,7 @@ import org.rs09.consts.Items import core.game.dialogue.DialogueFile import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeEntrance import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeVillage +import core.game.dialogue.FacialExpression import core.game.world.GameWorld.Pulser import core.tools.END_DIALOGUE @@ -45,30 +46,30 @@ class ElkoyDialogue : DialogueFile(){ inInventory(player!!, Items.ORBS_OF_PROTECTION_588) && followLocation == "exit" -> { when(stage) { 0 -> playerl("Hello Elkoy. I have the orb.").also { stage++ } - 1 -> npcl("Take it to King Bolren, I'm sure he'll be pleased to see you.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_HAPPY, "Take it to King Bolren, I'm sure he'll be pleased to see you.").also { stage++ } 2 -> options("Alright, I'll do that.", "Can you guide me out of the maze now?").also { stage++ } 3 -> when(buttonID) { 1 -> playerl("Alright, I'll do that.").also { stage = END_DIALOGUE } 2 -> playerl("Can you guide me out of the maze now?").also { stage = 4 } } - 4 -> npcl("If you like, but please take the orb to King Bolren soon.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "If you like, but please take the orb to King Bolren soon.").also { stage++ } 5 -> { travelCutscene(player!!, mazeEntrance) stage++ } - 6 -> npcl("Here we are. Please don't lose the orb!").also { stage = END_DIALOGUE } + 6 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. Please don't lose the orb!").also { stage = END_DIALOGUE } } } inInventory(player!!, Items.ORB_OF_PROTECTION_587) -> { when(stage) { 0 -> playerl("Hello Elkoy.").also { stage++ } - 1 -> npcl("You're back! And the orb?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "You're back! And the orb?").also { stage++ } 2 -> playerl("I have it here.").also { stage++ } 3 -> { if(locY > 3161){ - npcl("You're our saviour. Please return it to the village and we are all saved. Would you like me to show you the way to the village?").also { stage++ } + npcl(FacialExpression.OLD_NORMAL, "You're our saviour. Please return it to the village and we are all saved. Would you like me to show you the way to the village?").also { stage++ } } else { - npcl("Take the orb to King Bolren, I'm sure he'll be pleased to see you.").also { stage = END_DIALOGUE } + npcl(FacialExpression.OLD_NORMAL, "Take the orb to King Bolren, I'm sure he'll be pleased to see you.").also { stage = END_DIALOGUE } } } 4 -> options("Yes please.", "No thanks Elkoy.").also { stage++ } @@ -76,24 +77,24 @@ class ElkoyDialogue : DialogueFile(){ 1 -> playerl("Yes please.").also { stage = 7 } 2 -> playerl("No thanks Elkoy.").also { stage = 6 } } - 6 -> npcl("Ok then, take care.").also { stage = END_DIALOGUE } + 6 -> npcl(FacialExpression.OLD_NORMAL, "Ok then, take care.").also { stage = END_DIALOGUE } 7 -> travelCutscene(player!!, mazeVillage).also { stage++ } - 8 -> npcl("Here we are. Take the orb to King Bolren, I'm sure he'll be pleased to see you.").also { stage = END_DIALOGUE } + 8 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. Take the orb to King Bolren, I'm sure he'll be pleased to see you.").also { stage = END_DIALOGUE } } } inInventory(player!!, Items.ORBS_OF_PROTECTION_588) || questStage == 100 -> { when(stage) { 0 -> playerl("Hello Elkoy.").also { stage++ } - 1 -> npcl("You truly are a hero.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_HAPPY, "You truly are a hero.").also { stage++ } 2 -> playerl("Thanks.").also { stage++ } - 3 -> npcl("You saved us by defeating the warlord. I'm humbled and wish you well.").also { stage++ } - 4 -> npcl("Would you like me to show you the way to the ${followLocation}?").also { stage++ } + 3 -> npcl(FacialExpression.OLD_NORMAL, "You saved us by defeating the warlord. I'm humbled and wish you well.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "Would you like me to show you the way to the ${followLocation}?").also { stage++ } 5 -> options("Yes please.", "No thanks Elkoy.").also { stage++ } 6 -> when(buttonID) { 1 -> playerl("Yes please.").also { stage = 8 } 2 -> playerl("No thanks Elkoy.").also { stage = 7 } } - 7 -> npcl("Ok then, take care.").also { stage = END_DIALOGUE } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Ok then, take care.").also { stage = END_DIALOGUE } 8 -> { if(followLocation == "village") { travelCutscene(player!!, mazeVillage) @@ -104,33 +105,33 @@ class ElkoyDialogue : DialogueFile(){ stage++ } } - 9 -> npcl("Here we are. Have a safe journey.").also { stage = END_DIALOGUE } - 10 -> npcl("Here we are. Feel free to have a look around.").also { stage = END_DIALOGUE } + 9 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. Have a safe journey.").also { stage = END_DIALOGUE } + 10 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. Feel free to have a look around.").also { stage = END_DIALOGUE } } } questStage == 0 -> { when(stage) { 0 -> playerl("Hello there.").also { stage++ } - 1 -> npcl("Hello, welcome to our maze. I'm Elkoy the tree gnome.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello, welcome to our maze. I'm Elkoy the tree gnome.").also { stage++ } 2 -> playerl("I haven't heard of your sort.").also { stage++ } - 3 -> npcl("There's not many of us left. Once you could find tree gnomes anywhere in the world, now we hide in small groups to avoid capture.").also { stage++ } + 3 -> npcl(FacialExpression.OLD_SAD, "There's not many of us left. Once you could find tree gnomes anywhere in the world, now we hide in small groups to avoid capture.").also { stage++ } 4 -> playerl("Capture from whom?").also { stage++ } - 5 -> npcl("Tree gnomes have been hunted for so called 'fun' since as long as I can remember.").also { stage++ } - 6 -> npcl("Our main threat nowadays are General Khazard's troops. They know no mercy, but are also very dense. They'll never find their way through our maze.").also { stage++ } - 7 -> npcl("Have fun.").also { stage = END_DIALOGUE } + 5 -> npcl(FacialExpression.OLD_NORMAL, "Tree gnomes have been hunted for so called 'fun' since as long as I can remember.").also { stage++ } + 6 -> npcl(FacialExpression.OLD_NORMAL, "Our main threat nowadays are General Khazard's troops. They know no mercy, but are also very dense. They'll never find their way through our maze.").also { stage++ } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Have fun.").also { stage = END_DIALOGUE } } } questStage in 1..39 -> { when (stage) { - 0 -> npcl("Oh my! The orb, they have the orb. We're doomed.").also { stage++ } + 0 -> npcl(FacialExpression.OLD_DISTRESSED, "Oh my! The orb, they have the orb. We're doomed.").also { stage++ } 1 -> playerl("Perhaps I'll be able to get it back for you.").also { stage++ } - 2 -> npcl("Would you like me to show you the way to the ${followLocation}?").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "Would you like me to show you the way to the ${followLocation}?").also { stage++ } 3 -> options("Yes please.", "No thanks Elkoy.").also { stage++ } 4 -> when (buttonID) { 1 -> playerl("Yes please.").also { stage = 6 } 2 -> playerl("No thanks Elkoy.").also { stage = 5 } } - 5 -> npcl("Ok then, take care.").also { stage = END_DIALOGUE } + 5 -> npcl(FacialExpression.OLD_NORMAL, "Ok then, take care.").also { stage = END_DIALOGUE } 6 -> { if(followLocation == "village") travelCutscene(player!!, mazeVillage) @@ -138,20 +139,20 @@ class ElkoyDialogue : DialogueFile(){ travelCutscene(player!!, mazeEntrance) stage++ } - 7 -> npcl("Here we are. I hope you get the orb back soon.").also { stage = END_DIALOGUE } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. I hope you get the orb back soon.").also { stage = END_DIALOGUE } } } questStage == 40 -> { when(stage) { 0 -> playerl("Hello Elkoy.").also { stage++ } - 1 -> npcl("Did you hear? Khazard's men have pillaged the village! They slaughtered many, and took the other orbs in an attempt to lead us out of the maze. When will the misery end?").also { stage++ } - 2 -> npcl("Would you like me to show you the way to the ${followLocation}?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Did you hear? Khazard's men have pillaged the village! They slaughtered many, and took the other orbs in an attempt to lead us out of the maze. When will the misery end?").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "Would you like me to show you the way to the ${followLocation}?").also { stage++ } 3 -> options("Yes please.", "No thanks Elkoy.").also { stage++ } 4 -> when(buttonID) { 1 -> playerl("Yes please.").also { stage = 6 } 2 -> playerl("No thanks Elkoy.").also { stage = 5 } } - 5 -> npcl("Ok then, take care.").also { stage = END_DIALOGUE } + 5 -> npcl(FacialExpression.OLD_NORMAL, "Ok then, take care.").also { stage = END_DIALOGUE } 6 -> { if(followLocation == "village") { travelCutscene(player!!, mazeVillage) @@ -161,8 +162,8 @@ class ElkoyDialogue : DialogueFile(){ stage++ } } - 7 -> npcl("Please try to get our orbs back for us, otherwise the village is doomed!").also { stage = END_DIALOGUE } - 8 -> npcl("Here we are. Despite what has happened here, I hope you feel welcome.").also { stage = END_DIALOGUE } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Please try to get our orbs back for us, otherwise the village is doomed!").also { stage = END_DIALOGUE } + 8 -> npcl(FacialExpression.OLD_NORMAL, "Here we are. Despite what has happened here, I hope you feel welcome.").also { stage = END_DIALOGUE } } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt index 73c26fc14..89f6d5c11 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/KingBolrenDialogue.kt @@ -10,6 +10,7 @@ import org.rs09.consts.Items import org.rs09.consts.NPCs import core.game.dialogue.DialogueFile import content.region.kandarin.quest.tree.TreeGnomeVillage.Companion.mazeEntrance +import core.game.dialogue.FacialExpression import core.game.world.GameWorld import core.tools.END_DIALOGUE @@ -20,37 +21,37 @@ class KingBolrenDialogue : DialogueFile() { questStage < 10 -> { when (stage) { 0 -> playerl("Hello.").also { stage++ } - 1 -> npcl("Well hello stranger. My name's Bolren, I'm the king of the tree gnomes.").also { stage++ } - 2 -> npcl("I'm surprised you made it in, maybe I made the maze too easy.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Well hello stranger. My name's Bolren, I'm the king of the tree gnomes.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "I'm surprised you made it in, maybe I made the maze too easy.").also { stage++ } 3 -> playerl("Maybe.").also { stage++ } - 4 -> npcl("I'm afraid I have more serious concerns at the moment. Very serious.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "I'm afraid I have more serious concerns at the moment. Very serious.").also { stage++ } 5 -> options("I'll leave you to it then.", "Can I help at all?").also { stage++ } 6 -> when (buttonID) { 1 -> playerl("I'll leave you to it then.").also { stage = 7 } 2 -> playerl("Can I help at all?").also { stage = 8 } } - 7 -> npcl("Ok, take care.").also { stage = END_DIALOGUE } - 8 -> npcl("I'm glad you asked.").also { stage++ } - 9 -> npcl("The truth is my people are in grave danger. We have always been protected by the Spirit Tree. No creature of dark can harm us while its three orbs are in place.").also { stage++ } - 10 -> npcl("We are not a violent race, but we fight when we must. Many gnomes have fallen battling the dark forces of Khazard to the North.").also { stage++ } - 11 -> npcl("We became desperate, so we took one orb of protection to the battlefield. It was a foolish move.").also { stage++ } - 12 -> npcl("Khazard troops seized the orb. Now we are completely defenceless.").also { stage++ } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Ok, take care.").also { stage = END_DIALOGUE } + 8 -> npcl(FacialExpression.OLD_NORMAL, "I'm glad you asked.").also { stage++ } + 9 -> npcl(FacialExpression.OLD_SAD, "The truth is my people are in grave danger. We have always been protected by the Spirit Tree. No creature of dark can harm us while its three orbs are in place.").also { stage++ } + 10 -> npcl(FacialExpression.OLD_SAD, "We are not a violent race, but we fight when we must. Many gnomes have fallen battling the dark forces of Khazard to the North.").also { stage++ } + 11 -> npcl(FacialExpression.OLD_SAD, "We became desperate, so we took one orb of protection to the battlefield. It was a foolish move.").also { stage++ } + 12 -> npcl(FacialExpression.OLD_NORMAL, "Khazard troops seized the orb. Now we are completely defenceless.").also { stage++ } 13 -> playerl("How can I help?").also { stage++ } - 14 -> npcl("You would be a huge benefit on the battlefield. If you would go there and try to retrieve the orb, my people and I will be forever grateful.").also { stage++ } + 14 -> npcl(FacialExpression.OLD_NORMAL,"You would be a huge benefit on the battlefield. If you would go there and try to retrieve the orb, my people and I will be forever grateful.").also { stage++ } 15 -> options("I would be glad to help.", "I'm sorry but I won't be involved.").also { stage++ } 16 -> when (buttonID) { 1 -> playerl("I would be glad to help.").also { stage = 18 } 2 -> playerl("I'm sorry but I won't be involved.").also { stage = 17 } } - 17 -> npcl("Ok then, travel safe.").also { stage = END_DIALOGUE } - 18 -> npcl("Thank you. The battlefield is to the north of the maze. Commander Montai will inform you of their current situation.").also { stage++ } - 19 -> npcl("That is if he's still alive.").also { stage++ } - 20 -> npcl("My assistant shall guide you out. Good luck friend, try your best to return the orb.").also { + 17 -> npcl(FacialExpression.OLD_NORMAL, "Ok then, travel safe.").also { stage = END_DIALOGUE } + 18 -> npcl(FacialExpression.OLD_NORMAL, "Thank you. The battlefield is to the north of the maze. Commander Montai will inform you of their current situation.").also { stage++ } + 19 -> npcl(FacialExpression.OLD_NORMAL, "That is if he's still alive.").also { stage++ } + 20 -> npcl(FacialExpression.OLD_NORMAL, "My assistant shall guide you out. Good luck friend, try your best to return the orb.").also { stage++ } 21 -> { teleport(player!!, mazeEntrance) - sendNPCDialogue(player!!, NPCs.ELKOY_5179, "We're out of the maze now. Please hurry, we must have the orb if we are to survive.") + sendNPCDialogue(player!!, NPCs.ELKOY_5179, "We're out of the maze now. Please hurry, we must have the orb if we are to survive.", FacialExpression.OLD_NORMAL) setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 10) stage = END_DIALOGUE } @@ -59,7 +60,7 @@ class KingBolrenDialogue : DialogueFile() { questStage < 31 -> { when (stage) { 0 -> playerl("Hello Bolren.").also { stage++ } - 1 -> npcl("Hello traveller, we must retrieve the orb. It's being held by Khazard troops north of here.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello traveller, we must retrieve the orb. It's being held by Khazard troops north of here.").also { stage++ } 2 -> playerl("Ok, I'll try my best.").also { stage = END_DIALOGUE } } } @@ -67,32 +68,32 @@ class KingBolrenDialogue : DialogueFile() { if(inInventory(player!!,Items.ORB_OF_PROTECTION_587)){ when(stage) { 0 -> playerl("I have the orb.").also { stage++ } - 1 -> npcl("Oh my... The misery, the horror!").also { stage++ } + 1 -> npcl(FacialExpression.OLD_DISTRESSED, "Oh my... The misery, the horror!").also { stage++ } 2 -> playerl("King Bolren, are you OK?").also { stage++ } - 3 -> npcl("Thank you traveller, but it's too late. We're all doomed.").also { stage++ } + 3 -> npcl(FacialExpression.OLD_DISTRESSED, "Thank you traveller, but it's too late. We're all doomed.").also { stage++ } 4 -> playerl("What happened?").also { stage++ } - 5 -> npcl("They came in the night. I don't know how many, but enough.").also { stage++ } + 5 -> npcl(FacialExpression.OLD_DISTRESSED, "They came in the night. I don't know how many, but enough.").also { stage++ } 6 -> playerl("Who?").also { stage++ } - 7 -> npcl("Khazard troops. They slaughtered anyone who got in their way. Women, children, my wife.").also { stage++ } + 7 -> npcl(FacialExpression.OLD_DISTRESSED, "Khazard troops. They slaughtered anyone who got in their way. Women, children, my wife.").also { stage++ } 8 -> playerl("I'm sorry.").also { stage++ } - 9 -> npcl("They took the other orbs, now we are defenceless.").also { stage++ } + 9 -> npcl(FacialExpression.OLD_BOWS_HEAD_SAD, "They took the other orbs, now we are defenceless.").also { stage++ } 10 -> playerl("Where did they take them?").also { stage++ } - 11 -> npcl("They headed north of the stronghold. A warlord carries the orbs.").also { stage++ } + 11 -> npcl(FacialExpression.OLD_NORMAL, "They headed north of the stronghold. A warlord carries the orbs.").also { stage++ } 12 -> options("I will find the warlord and bring back the orbs.", "I'm sorry but I can't help.").also { stage++ } 13 -> when(buttonID) { 1 -> playerl("I will find the warlord and bring back the orbs.").also { stage = 15 } 2 -> playerl("I'm sorry but I can't help.").also { stage = 14 } } - 14 -> npcl("I understand, this isn't your battle.").also { stage = END_DIALOGUE } - 15 -> npcl("You are brave, but this task will be tough even for you. I wish you the best of luck. Once again you are our only hope.").also { stage++ } - 16 -> npcl("I will safeguard this orb and pray for your safe return. My assistant will guide you out.").also { + 14 -> npcl(FacialExpression.OLD_NORMAL, "I understand, this isn't your battle.").also { stage = END_DIALOGUE } + 15 -> npcl(FacialExpression.OLD_NORMAL, "You are brave, but this task will be tough even for you. I wish you the best of luck. Once again you are our only hope.").also { stage++ } + 16 -> npcl(FacialExpression.OLD_NORMAL, "I will safeguard this orb and pray for your safe return. My assistant will guide you out.").also { stage++ } 17 -> { if(removeItem(player!!,Items.ORB_OF_PROTECTION_587)){ teleport(player!!,mazeEntrance) setQuestStage(player!!, Quests.TREE_GNOME_VILLAGE, 40) - sendNPCDialogue(player!!, NPCs.ELKOY_5179, "Good luck friend.") + sendNPCDialogue(player!!, NPCs.ELKOY_5179, "Good luck friend.", FacialExpression.OLD_NORMAL) } stage = END_DIALOGUE } @@ -100,9 +101,9 @@ class KingBolrenDialogue : DialogueFile() { } else { when(stage) { 0 -> playerl("Hello Bolren.").also { stage++ } - 1 -> npcl("Do you have the orb?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Do you have the orb?").also { stage++ } 2 -> playerl("No, I'm afraid not.").also { stage++ } - 3 -> npcl("Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } } } } @@ -110,12 +111,12 @@ class KingBolrenDialogue : DialogueFile() { if(inInventory(player!!,Items.ORBS_OF_PROTECTION_588)){ when(stage) { 0 -> playerl("Bolren, I have returned.").also { stage++ } - 1 -> npcl("You made it back! Do you have the orbs?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "You made it back! Do you have the orbs?").also { stage++ } 2 -> playerl("I have them here.").also { stage++ } - 3 -> npcl("Hooray, you're amazing. I didn't think it was possible but you've saved us.").also { stage++ } - 4 -> npcl("Once the orbs are replaced we will be safe once more. We must begin the ceremony immediately.").also { stage++ } + 3 -> npcl(FacialExpression.OLD_HAPPY, "Hooray, you're amazing. I didn't think it was possible but you've saved us.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "Once the orbs are replaced we will be safe once more. We must begin the ceremony immediately.").also { stage++ } 5 -> playerl("What does the ceremony involve?").also { stage++ } - 6 -> npcl("The spirit tree has looked over us for centuries. Now we must pay our respects.").also { stage++ } + 6 -> npcl(FacialExpression.OLD_NORMAL, "The spirit tree has looked over us for centuries. Now we must pay our respects.").also { stage++ } 7 -> sendDialogue(player!!,"The gnomes begin to chant. Meanwhile, King Bolren holds the orbs of protection out in front of him.").also { stage++ } 8 -> { // Orbs fly up, gnomes chant, spirit tree animates @@ -166,20 +167,20 @@ class KingBolrenDialogue : DialogueFile() { } else { when(stage) { 0 -> playerl("Bolren, I have returned.").also { stage++ } - 1 -> npcl("You made it back! Do you have the orbs?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "You made it back! Do you have the orbs?").also { stage++ } 2 -> playerl("No, I'm afraid not.").also { stage++ } - 3 -> npcl("Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } } } } questStage == 99 -> { when(stage){ - 0 -> npcl("Now at last my people are safe once more. We can live in peace again.").also { stage++ } + 0 -> npcl(FacialExpression.OLD_NORMAL, "Now at last my people are safe once more. We can live in peace again.").also { stage++ } 1 -> playerl("I'm pleased I could help.").also { stage++ } - 2 -> npcl("You are modest brave traveller.").also { stage++ } - 3 -> npcl("Please, for your efforts take this amulet. It's made from the same sacred stone as the orbs of protection. It will help keep you safe on your journeys.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "You are modest brave traveller.").also { stage++ } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Please, for your efforts take this amulet. It's made from the same sacred stone as the orbs of protection. It will help keep you safe on your journeys.").also { stage++ } 4 -> playerl("Thank you King Bolren.").also { stage++ } - 5 -> npcl("The tree has many other powers, some of which I cannot reveal. As a friend of the gnome people, I can now allow you to use the tree's magic to teleport to other trees grown from related seeds.").also { + 5 -> npcl(FacialExpression.OLD_NORMAL, "The tree has many other powers, some of which I cannot reveal. As a friend of the gnome people, I can now allow you to use the tree's magic to teleport to other trees grown from related seeds.").also { finishQuest(player!!, Quests.TREE_GNOME_VILLAGE) stage = END_DIALOGUE } @@ -188,9 +189,9 @@ class KingBolrenDialogue : DialogueFile() { isQuestComplete(player!!, Quests.TREE_GNOME_VILLAGE) -> { when(stage) { 0 -> playerl("Hello again Bolren.").also { stage++ } - 1 -> npcl("Well hello, it's good to see you again.").also { stage = if (hasAnItem(player!!, Items.GNOME_AMULET_589).container != null) END_DIALOGUE else 2 } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Well hello, it's good to see you again.").also { stage = if (hasAnItem(player!!, Items.GNOME_AMULET_589).container != null) END_DIALOGUE else 2 } 2 -> playerl("I've lost my amulet.").also { stage++ } - 3 -> npcl("Oh dear. Here, take another. We are truly indebted to you.").also { + 3 -> npcl(FacialExpression.OLD_NORMAL, "Oh dear. Here, take another. We are truly indebted to you.").also { addItemOrDrop(player!!, Items.GNOME_AMULET_589) stage = END_DIALOGUE } diff --git a/Server/src/main/content/region/kandarin/quest/tree/LieutenantSchepburDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/LieutenantSchepburDialogue.kt index 7f29582d1..2571454a9 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/LieutenantSchepburDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/LieutenantSchepburDialogue.kt @@ -1,17 +1,18 @@ package content.region.kandarin.quest.tree import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class LieutenantSchepburDialogue : DialogueFile(){ override fun handle(componentID: Int, buttonID: Int) { when(stage) { - 0 -> npcl("Move into position lads! eh? Who are you and what do you want?").also { stage++ } + 0 -> npcl(FacialExpression.OLD_NORMAL, "Move into position lads! eh? Who are you and what do you want?").also { stage++ } 1 -> playerl("Who are you then?").also { stage++ } - 2 -> npcl("Lieutenant Schepbur, commanding officer of the new Armoured Tortoise Regiment.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_NORMAL, "Lieutenant Schepbur, commanding officer of the new Armoured Tortoise Regiment.").also { stage++ } 3 -> playerl("There's only two tortoises here, that's hardly a regiment.").also { stage++ } - 4 -> npcl("This is just the beginning! Gnome breeders and trainers are already working to expand the number of units. Soon we'll have hundreds of these beauties, nay thousands! And they will not only carry mages and").also { stage++ } - 5 -> npcl("archers but other fiendish weapons of destruction of gnome devising. An army of giant tortoises will march upon this battlefield and rain the fire of our wrath upon all our enemies! Nothing will be able to stop us!").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "This is just the beginning! Gnome breeders and trainers are already working to expand the number of units. Soon we'll have hundreds of these beauties, nay thousands! And they will not only carry mages and").also { stage++ } + 5 -> npcl(FacialExpression.OLD_NORMAL, "archers but other fiendish weapons of destruction of gnome devising. An army of giant tortoises will march upon this battlefield and rain the fire of our wrath upon all our enemies! Nothing will be able to stop us!").also { stage++ } 6 -> playerl("Oooookayy...... I'll leave you to it then....").also { stage = END_DIALOGUE } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/LocalGnomeDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/LocalGnomeDialogue.kt index b78813553..b6a0ff54c 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/LocalGnomeDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/LocalGnomeDialogue.kt @@ -1,13 +1,14 @@ package content.region.kandarin.quest.tree import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class LocalGnomeDialogue : DialogueFile() { override fun handle(componentID: Int, buttonID: Int) { when (stage) { 0 -> playerl("Hello little man.").also { stage++ } - 1 -> npcl("Little man stronger than big man. Hee hee, lardi dee, lardi da.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_LAUGH1, "Little man stronger than big man. Hee hee, lardi dee, lardi da.").also { stage = END_DIALOGUE } } } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt index 79b70b806..3038fed58 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/RemsaiDialogue.kt @@ -5,6 +5,7 @@ import core.api.inInventory import core.api.getQuestStage import org.rs09.consts.Items import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class RemsaiDialogue : DialogueFile(){ @@ -14,35 +15,35 @@ class RemsaiDialogue : DialogueFile(){ inInventory(player!!,Items.ORBS_OF_PROTECTION_588) -> { when(stage) { 0 -> playerl("I've returned.").also { stage++ } - 1 -> npcl("You're back, well done brave adventurer. Now the orbs are safe we can perform the ritual for the spirit tree. We can live in peace once again.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "You're back, well done brave adventurer. Now the orbs are safe we can perform the ritual for the spirit tree. We can live in peace once again.").also { stage = END_DIALOGUE } } } inInventory(player!!, Items.ORB_OF_PROTECTION_587) -> { when(stage) { 0 -> playerl("Hello Remsai.").also { stage++ } - 1 -> npcl("Hello, did you find the orb?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello, did you find the orb?").also { stage++ } 2 -> playerl("I have it here.").also { stage++ } - 3 -> npcl("You're our saviour.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_HAPPY, "You're our saviour.").also { stage = END_DIALOGUE } } } questStage < 40 -> { when(stage) { 0 -> playerl("Hello Remsai.").also { stage++ } - 1 -> npcl("Hello, did you find the orb?").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Hello, did you find the orb?").also { stage++ } 2 -> playerl("No, I'm afraid not.").also { stage++ } - 3 -> npcl("Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } + 3 -> npcl(FacialExpression.OLD_NORMAL, "Please, we must have the orb if we are to survive.").also { stage = END_DIALOGUE } } } questStage == 40 -> { when(stage) { 0 -> playerl("Are you ok?").also { stage++ } - 1 -> npcl("Khazard's men came. Without the orb we were defenceless. They killed many and then took our last hope, the other orbs. Now surely we're all doomed. Without them the spirit tree is useless.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_DISTRESSED, "Khazard's men came. Without the orb we were defenceless. They killed many and then took our last hope, the other orbs. Now surely we're all doomed. Without them the spirit tree is useless.").also { stage = END_DIALOGUE } } } questStage > 40 -> { when(stage) { 0 -> playerl("I've returned.").also { stage++ } - 1 -> npcl("You're back, well done brave adventurer. Now the orbs are safe we can perform the ritual for the spirit tree. We can live in peace once again.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "You're back, well done brave adventurer. Now the orbs are safe we can perform the ritual for the spirit tree. We can live in peace once again.").also { stage = END_DIALOGUE } } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt index 6ad5e3028..d4a4919fb 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeOneDialogue.kt @@ -4,6 +4,7 @@ import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class TrackerGnomeOneDialogue : DialogueFile(){ @@ -13,32 +14,32 @@ class TrackerGnomeOneDialogue : DialogueFile(){ questStage >= 40 -> { when (stage) { 0 -> playerl("Hello").also { stage++ } - 1 -> npcl("When will this battle end? I feel like I've been fighting forever.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_BOWS_HEAD_SAD, "When will this battle end? I feel like I've been fighting forever.").also { stage = END_DIALOGUE } } } questStage > 30 -> { if(inInventory(player!!, Items.ORB_OF_PROTECTION_587)){ when(stage) { 0 -> playerl("How are you tracker?").also { stage++ } - 1 -> npcl("Now we have the orb I'm much better. They won't stand a chance without it.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Now we have the orb I'm much better. They won't stand a chance without it.").also { stage = END_DIALOGUE } } } else { when(stage) { 0 -> playerl("Hello again.").also { stage++ } - 1 -> npcl("Well done, you've broken down their defences. This battle must be ours.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Well done, you've broken down their defences. This battle must be ours.").also { stage = END_DIALOGUE } } } } questStage == 30 -> { when (stage) { 0 -> playerl("Do you know the coordinates of the Khazard stronghold?").also { stage++ } - 1 -> npcl("I managed to get one, although it wasn't easy.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "I managed to get one, although it wasn't easy.").also { stage++ } 2 -> sendDialogue(player!!, "The gnome tells you the height coordinate.").also { setAttribute(player!!, "/save:treegnome:tracker1", true) stage++ } 3 -> playerl("Well done.").also { stage++ } - 4 -> npcl("The other two tracker gnomes should have the other coordinates if they're still alive.").also { stage++ } + 4 -> npcl(FacialExpression.OLD_NORMAL, "The other two tracker gnomes should have the other coordinates if they're still alive.").also { stage++ } 5 -> playerl("OK, take care.").also { stage = END_DIALOGUE } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt index 30070138b..de00880e0 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeThreeDialogue.kt @@ -3,6 +3,7 @@ package content.region.kandarin.quest.tree import content.data.Quests import core.api.* import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class TrackerGnomeThreeDialogue : DialogueFile(){ @@ -19,31 +20,31 @@ class TrackerGnomeThreeDialogue : DialogueFile(){ questStage == 30 -> { when(stage) { 0 -> playerl("Are you OK?").also { stage++ } - 1 -> npcl("OK? Who's OK? Not me! Hee hee!").also { stage++ } + 1 -> npcl(FacialExpression.OLD_LAUGH1, "OK? Who's OK? Not me! Hee hee!").also { stage++ } 2 -> playerl("What's wrong?").also { stage++ } - 3 -> npcl("You can't see me, no one can. Monsters, demons, they're all around me!").also { stage++ } + 3 -> npcl(FacialExpression.OLD_LAUGH1, "You can't see me, no one can. Monsters, demons, they're all around me!").also { stage++ } 4 -> playerl("What do you mean?").also { stage++ } - 5 -> npcl("They're dancing, all of them, hee hee.").also { stage++ } + 5 -> npcl(FacialExpression.OLD_LAUGH1, "They're dancing, all of them, hee hee.").also { stage++ } 6 -> sendDialogue(player!!,"He's clearly lost the plot.").also { stage++ } 7 -> playerl("Do you have the coordinate for the Khazard stronghold?").also { stage++ } - 8 -> npcl("Who holds the stronghold?").also { stage++ } + 8 -> npcl(FacialExpression.OLD_NORMAL, "Who holds the stronghold?").also { stage++ } 9 -> playerl("What?").also { stage++ } 10 -> { // Generate the x coordinate answer if(getAttribute(player!!,"treegnome:xcoord",0) == 0){ val answer = (1..4).random() - npcl(xcoordMap[answer]) + npcl(FacialExpression.OLD_NORMAL, xcoordMap[answer]) setAttribute(player!!,"/save:treegnome:xcoord",answer) } else { - npcl(xcoordMap[getAttribute(player!!,"treegnome:xcoord",1)]) + npcl(FacialExpression.OLD_NORMAL, xcoordMap[getAttribute(player!!,"treegnome:xcoord",1)]) } stage++ } 11 -> playerl("You're mad").also { stage++ } - 12 -> npcl("Dance with me, and Khazard's men are beat.").also { stage++ } + 12 -> npcl(FacialExpression.OLD_LAUGH1, "Dance with me, and Khazard's men are beat.").also { stage++ } 13 -> sendDialogue(player!!,"The toll of war has affected his mind.").also { stage++ } 14 -> playerl("I'll pray for you little man.").also { stage++ } - 15 -> npcl("All day we pray in the hay, hee hee.").also { + 15 -> npcl(FacialExpression.OLD_LAUGH1, "All day we pray in the hay, hee hee.").also { setAttribute(player!!, "/save:treegnome:tracker3", true) stage = END_DIALOGUE } @@ -52,13 +53,13 @@ class TrackerGnomeThreeDialogue : DialogueFile(){ questStage == 31 -> { when(stage) { 0 -> playerl("Hello again.").also { stage++ } - 1 -> npcl("Don't talk to me, you can't see me. No one can, just the demons.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_BOWS_HEAD_SAD, "Don't talk to me, you can't see me. No one can, just the demons.").also { stage = END_DIALOGUE } } } questStage > 31 -> { when(stage) { 0 -> playerl("Hello").also { stage++ } - 1 -> npcl("I feel dizzy, where am I? Oh dear, oh dear I need some rest.").also { stage++ } + 1 -> npcl(FacialExpression.OLD_NORMAL, "I feel dizzy, where am I? Oh dear, oh dear I need some rest.").also { stage++ } 2 -> playerl("I think you do.").also { stage = END_DIALOGUE } } } diff --git a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt index 6a845937d..d4bbd63c0 100644 --- a/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt +++ b/Server/src/main/content/region/kandarin/quest/tree/TrackerGnomeTwoDialogue.kt @@ -4,6 +4,7 @@ import content.data.Quests import core.api.* import org.rs09.consts.Items import core.game.dialogue.DialogueFile +import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE class TrackerGnomeTwoDialogue : DialogueFile(){ @@ -13,36 +14,36 @@ class TrackerGnomeTwoDialogue : DialogueFile(){ questStage == 30 -> { when (stage) { 0 -> playerl("Are you OK?").also { stage++ } - 1 -> npcl("They caught me spying on the stronghold. They beat and tortured me.").also { stage++ } - 2 -> npcl("But I didn't crack. I told them nothing. They can't break me!").also { stage++ } + 1 -> npcl(FacialExpression.OLD_DISTRESSED, "They caught me spying on the stronghold. They beat and tortured me.").also { stage++ } + 2 -> npcl(FacialExpression.OLD_LAUGH1, "But I didn't crack. I told them nothing. They can't break me!").also { stage++ } 3 -> playerl("I'm sorry little man.").also { stage++ } - 4 -> npcl("Don't be. I have the position of the stronghold!").also { stage++ } + 4 -> npcl(FacialExpression.OLD_LAUGH1, "Don't be. I have the position of the stronghold!").also { stage++ } 5 -> sendDialogue(player!!, "The gnome tells you the y coordinate.").also { setAttribute(player!!, "/save:treegnome:tracker2", true) stage++ } 6 -> playerl("Well done.").also { stage++ } - 7 -> npcl("Now leave before they find you and all is lost.").also { stage++ } + 7 -> npcl(FacialExpression.OLD_NORMAL, "Now leave before they find you and all is lost.").also { stage++ } 8 -> playerl("Hang in there.").also { stage++ } - 9 -> npcl("Go!").also { stage = END_DIALOGUE } + 9 -> npcl(FacialExpression.OLD_NORMAL, "Go!").also { stage = END_DIALOGUE } } } questStage >= 40 -> { when(stage) { 0 -> playerl("Hello").also { stage++ } - 1 -> npcl("When will this battle end? I feel like I've been locked up my whole life.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_DISTRESSED, "When will this battle end? I feel like I've been locked up my whole life.").also { stage = END_DIALOGUE } } } questStage > 30 -> { if(inInventory(player!!,Items.ORB_OF_PROTECTION_587)){ when(stage) { 0 -> playerl("How are you tracker?").also { stage++ } - 1 -> npcl("Now we have the orb I'm much better. Soon my comrades will come and free me.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Now we have the orb I'm much better. Soon my comrades will come and free me.").also { stage = END_DIALOGUE } } } else { when(stage) { 0 -> playerl("Hello again.").also { stage++ } - 1 -> npcl("Well done, you've broken down their defences. This battle must be ours.").also { stage = END_DIALOGUE } + 1 -> npcl(FacialExpression.OLD_NORMAL, "Well done, you've broken down their defences. This battle must be ours.").also { stage = END_DIALOGUE } } } } From 47ac5e93d662634a2e6a94d73c52aac61bdb2779 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Tue, 25 Mar 2025 09:48:27 +0000 Subject: [PATCH 271/306] Fixed issues causing pie crafting to stop or consume additional ingredients --- .../skill/cooking/CookingRecipePlugin.java | 18 ++++++++++-------- .../global/skill/cooking/recipe/Recipe.java | 3 +++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Server/src/main/content/global/skill/cooking/CookingRecipePlugin.java b/Server/src/main/content/global/skill/cooking/CookingRecipePlugin.java index 9ef36bcaf..067217358 100644 --- a/Server/src/main/content/global/skill/cooking/CookingRecipePlugin.java +++ b/Server/src/main/content/global/skill/cooking/CookingRecipePlugin.java @@ -44,29 +44,30 @@ public final class CookingRecipePlugin extends UseWithHandler { @Override public boolean handle(NodeUsageEvent event) { Recipe recipe = null; + Item part = null; // TODO: Transitioning to a Listener would save an O(n) pass through the recipes list on every use-with + recipeloop: for (Recipe temp : Recipe.RECIPES) { if (temp.isSingular()) { if (temp.getBase().getId() == event.getUsedItem().getId() || temp.getBase().getId() == event.getBaseItem().getId()) { for (Item ingredient : temp.getIngredients()) { if (ingredient.getId() == event.getBaseItem().getId() || ingredient.getId() == event.getUsedItem().getId()) { recipe = temp; - break; + break recipeloop; } } } } else { - Item part = null; - Item ingredient = null; for (int k = 0; k < temp.getParts().length; k++) { for (int i = 0; i < temp.getIngredients().length; i++) { - part = temp.getParts()[k]; - ingredient = temp.getIngredients()[i]; - if (part.getId() == event.getUsedItem().getId() && ingredient.getId() == event.getBaseItem().getId() || part.getId() == event.getBaseItem().getId() && ingredient.getId() == event.getUsedItem().getId()) { + Item tempPart = temp.getParts()[k]; + Item ingredient = temp.getIngredients()[i]; + if (tempPart.getId() == event.getUsedItem().getId() && ingredient.getId() == event.getBaseItem().getId() || tempPart.getId() == event.getBaseItem().getId() && ingredient.getId() == event.getUsedItem().getId()) { if (k == i) {// represents that this ingredient can // mix with the other. recipe = temp; - break; + part = tempPart; + break recipeloop; } } } @@ -76,6 +77,7 @@ public final class CookingRecipePlugin extends UseWithHandler { if (recipe != null) { final Player player = event.getPlayer(); final Recipe recipe_ = recipe; + final Item part_ = part; SkillDialogueHandler handler = new SkillDialogueHandler(player, SkillDialogue.ONE_OPTION, recipe.getProduct()) { @Override public void create(final int amount, int index) { @@ -91,7 +93,7 @@ public final class CookingRecipePlugin extends UseWithHandler { @Override public int getAll(int index) { - return player.getInventory().getAmount(recipe_.getBase()); + return player.getInventory().getAmount(part_ != null ? part_ : recipe_.getBase()); } }; if (player.getInventory().getAmount(recipe.getBase()) == 1) { diff --git a/Server/src/main/content/global/skill/cooking/recipe/Recipe.java b/Server/src/main/content/global/skill/cooking/recipe/Recipe.java index 2402a9772..3e2eff513 100644 --- a/Server/src/main/content/global/skill/cooking/recipe/Recipe.java +++ b/Server/src/main/content/global/skill/cooking/recipe/Recipe.java @@ -119,6 +119,9 @@ public abstract class Recipe { } } if (index != -1) { + if (!player.getInventory().containItems(event.getBaseItem().getId(), event.getUsedItem().getId())) { + return; + } if (player.getInventory().remove(event.getBaseItem()) && player.getInventory().remove(event.getUsedItem())) { player.getInventory().add(getParts()[index + 1]); String message = getMixMessage(event); From fc2247f4576e5a98c0724104004fda2d4fe7eb92 Mon Sep 17 00:00:00 2001 From: sirdabalot Date: Tue, 25 Mar 2025 09:49:09 +0000 Subject: [PATCH 272/306] Fixed teleport on logout for pest control landers --- Server/src/main/content/minigame/pestcontrol/PCLanderZone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/minigame/pestcontrol/PCLanderZone.java b/Server/src/main/content/minigame/pestcontrol/PCLanderZone.java index 21cc7fce5..5ace493bb 100644 --- a/Server/src/main/content/minigame/pestcontrol/PCLanderZone.java +++ b/Server/src/main/content/minigame/pestcontrol/PCLanderZone.java @@ -80,7 +80,7 @@ public final class PCLanderZone extends MapZone { for (PestControlActivityPlugin a : activities) { if (a.getWaitingPlayers().remove(e)) { if (logout) { - e.getProperties().setTeleportLocation(a.getLeaveLocation()); + e.setLocation(a.getLeaveLocation()); } break; } From 1b0a7d5fcacb9ab9c70fa0b3de7a4ed2fba08a27 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Tue, 25 Mar 2025 09:51:47 +0000 Subject: [PATCH 273/306] Fixed random events returning players to Lumbridge --- Server/src/main/content/global/ame/KidnapHelper.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Server/src/main/content/global/ame/KidnapHelper.kt b/Server/src/main/content/global/ame/KidnapHelper.kt index 2efc90f2d..5cef011ba 100644 --- a/Server/src/main/content/global/ame/KidnapHelper.kt +++ b/Server/src/main/content/global/ame/KidnapHelper.kt @@ -15,6 +15,11 @@ fun kidnapPlayer(player: Player, loc: Location, type: TeleportType) { } fun returnPlayer(player: Player) { + // Prevent returning more than once and sending the player back to HOME_LOCATION + if (getAttribute(player, "kidnapped-by-random", null) == null) { + return + } + player.locks.unlockTeleport() val destination = getAttribute(player, "/save:original-loc", ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) teleport(player, destination) From 7b1ebd460826476f3d8ffadd905112830ee7519c Mon Sep 17 00:00:00 2001 From: DeadlyGenga <19836947-matthewhurleychch@users.noreply.gitlab.com> Date: Tue, 25 Mar 2025 09:52:15 +0000 Subject: [PATCH 274/306] Added melee attack animation to Mystic Mud staff --- Server/data/configs/item_configs.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index c7da93ae9..34d0d7b90 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -59959,6 +59959,7 @@ "attack_speed": "5", "turn180_anim": "1206", "equipment_slot": "3", + "attack_anims": "419,419,419,419", "grand_exchange_price": "423100", "stand_anim": "813", "tradeable": "true", @@ -119757,18 +119758,18 @@ }, { "requirements": "{11,79}", - "destroy_message": "To get another pair of Flame Gloves, you need to keep ten beacons alight simultaneously and then talk to King Roald.", "shop_price": "200", "examine": "The hottest gloves in town.", "durability": null, - "name": "Flame gloves", "destroy": "true", - "archery_ticket_price": "0", "attack_speed": "4", - "id": "13660", "absorb": "0,0,0", - "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", - "equipment_slot": "9" + "equipment_slot": "9", + "destroy_message": "To get another pair of Flame Gloves, you need to keep ten beacons alight simultaneously and then talk to King Roald.", + "name": "Flame gloves", + "archery_ticket_price": "0", + "id": "13660", + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" }, { "requirements": "{11,92}", From 48bc0ffb281f979b0834660ba815c81a0260bd31 Mon Sep 17 00:00:00 2001 From: Player Name Date: Tue, 25 Mar 2025 09:55:37 +0000 Subject: [PATCH 275/306] Fixed requirement check issue with PoH portals checking for Plague City completion --- .../decoration/portalchamber/PortalChamberPlugin.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java b/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java index ad8c68db8..bf1f26c54 100644 --- a/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java +++ b/Server/src/main/content/global/skill/construction/decoration/portalchamber/PortalChamberPlugin.java @@ -90,7 +90,7 @@ public class PortalChamberPlugin extends OptionHandler { for (Locations l : Locations.values()) { if (l.name().contains(identifier)) { if (l == Locations.ARDOUGNE){ - if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){ + if (!player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)) { player.sendMessage("You do not have the requirements to direct the portal there"); return; } @@ -138,12 +138,6 @@ public class PortalChamberPlugin extends OptionHandler { case "enter": String objectName = object.getName(); for (Locations l : Locations.values()) { - if (l == Locations.ARDOUGNE){ - if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){ - player.sendMessage("You do not have the requirements to enter this portal."); - return false; - } - } if (objectName.toLowerCase().contains(l.name().toLowerCase())) { player.teleport(l.location); if (player.getHouseManager().isInHouse(player) && node.getId() == 13635) { From bcc3bc069e7c85311ba91ca00a8cb9334a43dd7d Mon Sep 17 00:00:00 2001 From: Lucid Enigma Date: Tue, 25 Mar 2025 09:58:27 +0000 Subject: [PATCH 276/306] Potentially fixed bank visuals when opening bank --- Server/src/main/core/game/container/impl/BankContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index 5fb95791b..2b1640293 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -130,8 +130,8 @@ public final class BankContainer extends Container { }); player.getInterfaceManager().openSingleTab(new Component(763)); super.refresh(); - player.getInventory().getListeners().add(listener); player.getInventory().refresh(); + player.getInventory().getListeners().add(listener); setVarp(player, 1249, lastAmountX); int settings = new IfaceSettingsBuilder().enableOptions(new IntRange(0, 5)).enableExamine().enableSlotSwitch().build(); player.getPacketDispatch().sendIfaceSettings(settings, 0, 763, 0, 27); From 45ee87e64e4cd8a1888db642ce344689477ee25e Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 27 Mar 2025 19:30:06 -0600 Subject: [PATCH 277/306] Blast Furnace improvements Shoving coke no longer requires intense clicking, the player will keep shoveling until the stove is full. Adding ore that requires coal to the conveyor belt will take the needed coal from the gold satchel, if carried. --- .../minigame/blastfurnace/BlastFurnace.kt | 26 ++++++++++++++++++- .../blastfurnace/BlastFurnaceListeners.kt | 9 +++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/minigame/blastfurnace/BlastFurnace.kt b/Server/src/main/content/minigame/blastfurnace/BlastFurnace.kt index 5bbdedef1..7c8386596 100644 --- a/Server/src/main/content/minigame/blastfurnace/BlastFurnace.kt +++ b/Server/src/main/content/minigame/blastfurnace/BlastFurnace.kt @@ -166,8 +166,32 @@ class BlastFurnace : MapArea, PersistPlayer, TickListener { maxAmt = maxAmt.coerceAtMost(amount).coerceAtLeast(0) if (maxAmt == 0) continue - if (removeItem(p, Item(oreId, maxAmt))) + if (removeItem(p, Item(oreId, maxAmt))) { + sendMessage(p, "You place ${maxAmt} ${Item(oreId).getName()} on the conveyor belt.") + addCoalSecondary(p, oreId, maxAmt) //The belt renders the most recent ore, so add the coal first addOreToBelt(p, oreId, maxAmt) + } + } + } + + //Snowscape feature: coal stored in the gold satchel is automatically added to the belt with ores that require coal. + fun addCoalSecondary (p: Player, oreId: Int, amount: Int) { + if (!inEquipmentOrInventory(p, Items.GOLD_SATCHEL_10881)) return + + var coalAmount = 0 + when(oreId) { + Items.IRON_ORE_440 -> coalAmount = amount + Items.MITHRIL_ORE_447 -> coalAmount = amount * 2 + Items.ADAMANTITE_ORE_449 -> coalAmount = amount * 3 + Items.RUNITE_ORE_451 -> coalAmount = amount * 4 + else -> return + } + + coalAmount = coalAmount.coerceAtMost(getOreContainer(p).getAvailableSpace(Items.COAL_453) - getAmountOnBelt(p, Items.COAL_453)) + + if (coalAmount > 0 && p.goldSatchel.remove(Item(Items.COAL_453, coalAmount))){ + addOreToBelt(p, Items.COAL_453, coalAmount) + sendMessage(p, "You take ${coalAmount} Coal from your gold satchel and place it on the belt.") } } diff --git a/Server/src/main/content/minigame/blastfurnace/BlastFurnaceListeners.kt b/Server/src/main/content/minigame/blastfurnace/BlastFurnaceListeners.kt index deaaae199..627f57d77 100644 --- a/Server/src/main/content/minigame/blastfurnace/BlastFurnaceListeners.kt +++ b/Server/src/main/content/minigame/blastfurnace/BlastFurnaceListeners.kt @@ -6,6 +6,7 @@ import core.game.dialogue.DialogueFile import core.game.dialogue.Topic import core.game.interaction.IntType import core.game.interaction.InteractionListener +import core.game.interaction.InteractionListeners import core.game.node.entity.skill.Skills import core.game.system.task.Pulse import core.game.world.map.Location @@ -128,6 +129,10 @@ class BlastFurnaceListeners : InteractionListener { lockInteractions(player,1) animate(player, 2441) } + queueScript(player, 0) { + val node = getScenery(1948,4963,0) + InteractionListeners.run(node!!.getId(), SCENERY, "refuel", player, node) + } } else { sendMessage(player, "You need a spade to do this!") } @@ -163,6 +168,10 @@ class BlastFurnaceListeners : InteractionListener { } } }) + queueScript(player, 0) { + val node = getScenery(1950,4964,0) + InteractionListeners.run(node!!.getId(), SCENERY, "collect", player, node) + } } else { sendMessage(player,"You need some coke to do that!") } From 08ffa6fee61e4d9f18b972e00170373a3fe2f564 Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 30 Mar 2025 15:53:05 -0600 Subject: [PATCH 278/306] Crafting Gold Jewellery will automatically take gems from the Gold Satchel --- .../global/handlers/iface/JewelleryInterface.java | 3 +++ .../skill/crafting/jewellery/JewelleryCrafting.java | 12 ++++++++++-- .../skill/crafting/jewellery/JewelleryPulse.java | 12 ++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/handlers/iface/JewelleryInterface.java b/Server/src/main/content/global/handlers/iface/JewelleryInterface.java index 11eb23415..ea45a538a 100644 --- a/Server/src/main/content/global/handlers/iface/JewelleryInterface.java +++ b/Server/src/main/content/global/handlers/iface/JewelleryInterface.java @@ -165,6 +165,7 @@ public final class JewelleryInterface extends ComponentPlugin { amount = 5; break; case 124: + /* No need to calculate the maximum amount here, because the make() function will perform that step if (data.name().contains("GOLD")) { amount = player.getInventory().getAmount(new Item(GOLD_BAR)); } else { @@ -178,6 +179,8 @@ public final class JewelleryInterface extends ComponentPlugin { amount = first; } } + */ + amount = 99; break; case 199: final JewelleryItem d = data; diff --git a/Server/src/main/content/global/skill/crafting/jewellery/JewelleryCrafting.java b/Server/src/main/content/global/skill/crafting/jewellery/JewelleryCrafting.java index 37304e77d..89358a5fc 100644 --- a/Server/src/main/content/global/skill/crafting/jewellery/JewelleryCrafting.java +++ b/Server/src/main/content/global/skill/crafting/jewellery/JewelleryCrafting.java @@ -5,6 +5,7 @@ import core.game.component.Component; import core.game.node.entity.skill.Skills; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import static core.api.ContentAPIKt.*; import java.util.HashMap; @@ -185,7 +186,9 @@ public class JewelleryCrafting { for (int i = 0; i < data.items.length; i++) { if (player.getInventory().contains(data.getItems()[i], 1)) { length++; - } + } else if (inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(data.getItems()[i], 1)){ + length++; + } } if (!player.getInventory().contains(mouldFor(data.name()), 1)) { length--; @@ -235,6 +238,9 @@ public class JewelleryCrafting { amt = player.getInventory().getAmount(new Item(GOLD_BAR)); } else { int first = player.getInventory().getAmount(new Item(data.getItems()[0])); + if (inEquipmentOrInventory(player, 10881, 1)) { + first += player.goldSatchel.getAmount(new Item(data.getItems()[0])); + } int second = player.getInventory().getAmount(new Item(data.getItems()[1])); if (first == second) { amt = first; @@ -250,7 +256,9 @@ public class JewelleryCrafting { for (int i = 0; i < data.items.length; i++) { if (player.getInventory().contains(data.getItems()[i], amount)) { length++; - } + } else if (data.getItems()[i] != GOLD_BAR && inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(data.getItems()[i], 1)){ + length++; + } } if (length != data.getItems().length) { player.getPacketDispatch().sendMessage("You don't have the required items to make this item."); diff --git a/Server/src/main/content/global/skill/crafting/jewellery/JewelleryPulse.java b/Server/src/main/content/global/skill/crafting/jewellery/JewelleryPulse.java index e69a7ee29..be2f7b58c 100644 --- a/Server/src/main/content/global/skill/crafting/jewellery/JewelleryPulse.java +++ b/Server/src/main/content/global/skill/crafting/jewellery/JewelleryPulse.java @@ -67,11 +67,19 @@ public final class JewelleryPulse extends SkillPulse { if (++ticks % 5 != 0) { return false; } - if (player.getInventory().remove(getItems())) { + Item items[] = getItems(); + for (int i = 0; i < items.length; i++) { + if (player.getInventory().remove(items[i]) || (items[i].getId() != 2357 && inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.remove(items[i]))) { + continue; + } else { + return true; + } + } + //if (player.getInventory().remove(getItems())) { final Item item = new Item(type.getSendItem()); player.getInventory().add(item); player.getSkills().addExperience(Skills.CRAFTING, type.getExperience(), true); - } + //} amount--; return amount < 1; } From 7538322006d3d42f420aff0bdfbabb5d3b073c7e Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 31 Mar 2025 13:03:41 -0600 Subject: [PATCH 279/306] Implemented Costume Room Bank Interacting with the fancy dress box in the costume room of a player owned house will allow access to this extra storage. Items stored in this bank count as "worn" when doing treasure trail emote clues. --- .../activity/ttrail/ClueScrollPlugin.java | 2 +- .../costume/SnowscapeFancyDressBox.kt | 30 +++++++++++++++++++ Server/src/main/core/api/utils/Permadeath.kt | 1 + .../game/container/impl/BankContainer.java | 2 ++ .../core/game/node/entity/player/Player.java | 5 ++++ .../player/info/login/PlayerSaveParser.kt | 3 ++ .../entity/player/info/login/PlayerSaver.kt | 2 ++ 7 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 Server/src/main/content/global/skill/construction/decoration/costume/SnowscapeFancyDressBox.kt diff --git a/Server/src/main/content/global/activity/ttrail/ClueScrollPlugin.java b/Server/src/main/content/global/activity/ttrail/ClueScrollPlugin.java index 13efad3c6..c049c6dab 100644 --- a/Server/src/main/content/global/activity/ttrail/ClueScrollPlugin.java +++ b/Server/src/main/content/global/activity/ttrail/ClueScrollPlugin.java @@ -192,7 +192,7 @@ public abstract class ClueScrollPlugin extends MapZone implements Plugin int hasAmt = 0; for (int i = 0; i < equipment.length; i++) { for (int k = 0; k < equipment[i].length; k++) { - if (player.getEquipment().contains(equipment[i][k], 1)) { + if (player.getEquipment().contains(equipment[i][k], 1) || player.costumeRoomBank.contains(equipment[i][k], 1)) { hasAmt++; break; } diff --git a/Server/src/main/content/global/skill/construction/decoration/costume/SnowscapeFancyDressBox.kt b/Server/src/main/content/global/skill/construction/decoration/costume/SnowscapeFancyDressBox.kt new file mode 100644 index 000000000..8306a1e41 --- /dev/null +++ b/Server/src/main/content/global/skill/construction/decoration/costume/SnowscapeFancyDressBox.kt @@ -0,0 +1,30 @@ +package content.global.skill.construction.decoration.costume + +import core.game.node.scenery.Scenery +import core.game.node.scenery.SceneryBuilder +import core.game.interaction.InteractionListener +import core.game.interaction.IntType +import core.api.* + +/** + * + * + */ +class SnowscapeCostumeRoomBank : InteractionListener { + + val IDs = intArrayOf(18772,18774,18776) + + override fun defineListeners() { + on(IDs, IntType.SCENERY, "open"){ player, node -> + if (!player.houseManager.isInHouse(player)) { + sendMessage(player, "You can only do that in your own house.") + return@on true + } + + setAttribute(player, "inCostumeRoomBank", true) + openBankAccount(player) + + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/core/api/utils/Permadeath.kt b/Server/src/main/core/api/utils/Permadeath.kt index cbd442bc7..d6b248c55 100644 --- a/Server/src/main/core/api/utils/Permadeath.kt +++ b/Server/src/main/core/api/utils/Permadeath.kt @@ -50,6 +50,7 @@ fun permadeath(target: Player) { target.runeSatchel.clear() target.blackSatchel.clear() target.summoningPouches.clear() + target.costumeRoomBank.clear() // Skills target.skills = Skills(target) diff --git a/Server/src/main/core/game/container/impl/BankContainer.java b/Server/src/main/core/game/container/impl/BankContainer.java index 68f1fb72c..8937c1e8d 100644 --- a/Server/src/main/core/game/container/impl/BankContainer.java +++ b/Server/src/main/core/game/container/impl/BankContainer.java @@ -143,6 +143,7 @@ public final class BankContainer extends Container { return; } player.getInterfaceManager().openComponent(762).setCloseEvent((player, c) -> { + removeAttribute(player, "inCostumeRoomBank"); BankContainer.this.close(); return true; }); @@ -168,6 +169,7 @@ public final class BankContainer extends Container { return; } player.getInterfaceManager().openComponent(762).setCloseEvent((player1, c) -> { + removeAttribute(player, "inCostumeRoomBank"); BankContainer.this.close(); return true; }); diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 6416acb37..52c286223 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -321,6 +321,8 @@ public class Player extends Entity { public final Container runeSatchel = new Container(30, ContainerType.ALWAYS_STACK); // The summoning pouch storage public final Container summoningPouches = new Container(30); + // The costume room bank + public final BankContainer costumeRoomBank = new BankContainer(this); /** * Constructs a new {@code Player} {@code Object}. @@ -1049,6 +1051,9 @@ public class Player extends Entity { * @return Current active bank. */ public BankContainer getBank() { + if (getAttribute("inCostumeRoomBank", false)) { + return costumeRoomBank; + } if (getAttribute("clanbank:enabled",false)) { Player target = Repository.getPlayerByName(this.getCommunication().getCurrentClan()); if (target != null) { diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index 2e661c782..fdf7419e0 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -389,6 +389,9 @@ class PlayerSaveParser(val player: Player) { val summoningPouches = snowscapeData["summoningPouches"] if (summoningPouches != null) player.summoningPouches.parse(summoningPouches as JSONArray) + + val costumeRoomBank = snowscapeData["costumeRoomBank"] + if (costumeRoomBank != null) player.costumeRoomBank.parse(costumeRoomBank as JSONArray) } } diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 15ab459af..48b084b2e 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -658,6 +658,8 @@ class PlayerSaver (val player: Player){ snowscapeData.put("summoningPouches", saveContainer(player.summoningPouches)) + snowscapeData.put("costumeRoomBank", saveContainer(player.costumeRoomBank)) + root.put("snowscape_data",snowscapeData) } } From 4d7f26bb472a500617be03d5de2b22dd105c9bcc Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 1 Apr 2025 08:38:50 -0600 Subject: [PATCH 280/306] Disabled Easter Event --- .../main/core/game/worldevents/holiday/easter/EasterEvent.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/worldevents/holiday/easter/EasterEvent.kt b/Server/src/main/core/game/worldevents/holiday/easter/EasterEvent.kt index 6b129b906..d64bb704b 100644 --- a/Server/src/main/core/game/worldevents/holiday/easter/EasterEvent.kt +++ b/Server/src/main/core/game/worldevents/holiday/easter/EasterEvent.kt @@ -100,7 +100,8 @@ class EasterEvent : WorldEvent("easter"), TickListener, InteractionListener, Log } override fun checkActive(cal: Calendar): Boolean { - return cal.get(Calendar.MONTH) == Calendar.APRIL || ServerConstants.FORCE_EASTER_EVENTS + return false + //return cal.get(Calendar.MONTH) == Calendar.APRIL || ServerConstants.FORCE_EASTER_EVENTS } private fun onEggBroken (player: Player) From 269eb8285072323ac0913657bd9e9630161edc6b Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 1 Apr 2025 08:46:49 -0600 Subject: [PATCH 281/306] Added bank tab handling for the Costume Room Bank --- .../entity/player/info/login/PlayerSaveParser.kt | 12 ++++++++++++ .../node/entity/player/info/login/PlayerSaver.kt | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt index fdf7419e0..38ec991fb 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -390,6 +390,18 @@ class PlayerSaveParser(val player: Player) { val summoningPouches = snowscapeData["summoningPouches"] if (summoningPouches != null) player.summoningPouches.parse(summoningPouches as JSONArray) + val costumeRoomBankTabs = snowscapeData["costumeRoomBankTabs"] + if (costumeRoomBankTabs != null) { + val tabData = costumeRoomBankTabs as JSONArray + for (i in tabData) { + i ?: continue + val tab = i as JSONObject + val index = tab["index"].toString().toInt() + val startSlot = tab["startSlot"].toString().toInt() + player.costumeRoomBank.tabStartSlot[index] = startSlot + } + } + val costumeRoomBank = snowscapeData["costumeRoomBank"] if (costumeRoomBank != null) player.costumeRoomBank.parse(costumeRoomBank as JSONArray) diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 48b084b2e..2709ae12a 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -658,6 +658,14 @@ class PlayerSaver (val player: Player){ snowscapeData.put("summoningPouches", saveContainer(player.summoningPouches)) + val costumeRoomBankTabs = JSONArray() + for(i in player.costumeRoomBank.tabStartSlot.indices){ + val tab = JSONObject() + tab.put("index",i.toString()) + tab.put("startSlot",player.costumeRoomBank.tabStartSlot[i].toString()) + costumeRoomBankTabs.add(tab) + } + snowscapeData.put("costumeRoomBankTabs",costumeRoomBankTabs) snowscapeData.put("costumeRoomBank", saveContainer(player.costumeRoomBank)) root.put("snowscape_data",snowscapeData) From 54055e36d0a6b834eea83e70e985cacaf0cd014c Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 1 Apr 2025 11:47:08 -0600 Subject: [PATCH 282/306] Runecrafting pouch improvements Using any of the essence pouches on a bank booth, bank chest, or banker npc will refill all the pouches in the player inventory, as well as their familiar. When runecrafting, if the player runs out of essence then essence will be withdrawn from the familiar and pouches. Both of the previous functions only work on pure essence, not rune essence. Also moved the Ourania teleport closer to the altar. --- .../skill/magic/lunar/LunarListeners.kt | 3 +- .../global/skill/runecrafting/PouchManager.kt | 4 +- .../skill/runecrafting/RuneCraftPulse.java | 3 +- .../runecrafting/SnowscapePouchListener.kt | 89 +++++++++++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100755 Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index a55a32bac..d88710205 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -93,7 +93,8 @@ class LunarListeners : SpellListener("lunar"), Commands { onCast(Lunar.OURANIA_TELEPORT, NONE) { player, _ -> requires(player, 71, arrayOf(Item(Items.ASTRAL_RUNE_9075, 2), Item(Items.LAW_RUNE_563, 1), Item(Items.EARTH_RUNE_557, 6))) if (!player.isTeleBlocked) playGlobalAudio(player.location, Sounds.TELEPORT_ALL_200) - sendTeleport(player, 69.0, Location.create(2469, 3247, 0)) + //sendTeleport(player, 69.0, Location.create(2469, 3247, 0)) + sendTeleport(player, 69.0, Location.create(3314, 4818, 0)) } // Level 71 diff --git a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt index 22cc1865f..6bb4020f0 100644 --- a/Server/src/main/content/global/skill/runecrafting/PouchManager.kt +++ b/Server/src/main/content/global/skill/runecrafting/PouchManager.kt @@ -29,7 +29,7 @@ class PouchManager(val player: Player) { * @param essence the ID of the essence item we are trying to add * @author Ceikry, Player Name */ - fun addToPouch(itemId: Int, amount: Int, essence: Int) { + fun addToPouch(itemId: Int, amount: Int, essence: Int, fromBank: Boolean = false) { val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId if (!checkRequirement(pouchId)) { sendMessage(player, "You lack the required level to use this pouch.") @@ -90,7 +90,7 @@ class PouchManager(val player: Player) { } } val essItem = Item(essence, amt) - if (!disappeared && removeItem(player, essItem)) { + if (!disappeared && (fromBank && player.getBank().remove(essItem)) || removeItem(player, essItem)) { pouch.container.add(essItem) } } diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 819337a57..017efe99c 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -173,6 +173,7 @@ public final class RuneCraftPulse extends SkillPulse { } else { combine(); } + SnowscapePouchListener.Companion.emptyPouches(player); return false; } @@ -326,7 +327,7 @@ public final class RuneCraftPulse extends SkillPulse { if (altar == Altar.SOUL) { tablet = new Item(8022, amount); } if (tablet != null && player.getInventory().remove(clay)) { player.getInventory().add(tablet); - player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * amount, true); + player.getSkills().addExperience(Skills.RUNECRAFTING, rune.getExperience() * amount * 2, true); player.getPacketDispatch().sendMessage("You bind the temple's power into teleport tablets."); } } diff --git a/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt b/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt new file mode 100755 index 000000000..549c4445e --- /dev/null +++ b/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt @@ -0,0 +1,89 @@ +package content.global.skill.runecrafting + +import core.api.* +import core.game.node.Node +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.interaction.InteractionListener +import core.game.interaction.IntType +import org.rs09.consts.Items +import content.global.handlers.scenery.BankBoothListener +import content.global.handlers.npc.BankerNPC +import content.global.skill.summoning.familiar.BurdenBeast +import content.global.skill.summoning.familiar.Forager + +/** + * Listener for using runecrafting pouches on banks for easier refilling. + * Using any pouch on a bank booth, chest, or banker will refill all the carried pouches as well as the familiar inventory. + * @author + */ +class SnowscapePouchListener : InteractionListener { + + companion object { + + val pouchIds = intArrayOf(5509,5510,5511,5512,5513,5514,5515) + + // Called by the runecraft pulse + fun emptyPouches(player: Player) { + if (amountInInventory(player, Items.PURE_ESSENCE_7936) > 0 || amountInInventory(player, Items.RUNE_ESSENCE_1436) > 0) return + + val familiar = player.getFamiliarManager().getFamiliar() + if (familiar.isBurdenBeast() && (familiar as BurdenBeast).getContainer().containsAtLeastOneItem(Items.PURE_ESSENCE_7936)) { + (familiar as BurdenBeast).transfer(Item(Items.PURE_ESSENCE_7936), 99, true) + } + + for (pouchId in pouchIds) { + if (inInventory(player, pouchId, 1)) { + player.pouchManager.withdrawFromPouch(pouchId) + } + } + } + } + + private fun fillPouchFromBank(player: Player) { + val playerBank = player.getBank() + for (pouchId in pouchIds) { + if (inInventory(player, pouchId, 1)) { + player.pouchManager.addToPouch(pouchId, playerBank.getAmount(Items.PURE_ESSENCE_7936), Items.PURE_ESSENCE_7936, true) + } + } + + if (player.getFamiliarManager().hasFamiliar()) { + val familiar = player.getFamiliarManager().getFamiliar() + if (familiar.isBurdenBeast() && (familiar !is Forager)) { + val familiarContainer = (familiar as BurdenBeast).getContainer() + val amount = kotlin.math.min(familiarContainer.getMaximumAdd(Item(Items.PURE_ESSENCE_7936)), playerBank.getAmount(Item(Items.PURE_ESSENCE_7936))) + val item = Item(Items.PURE_ESSENCE_7936, amount) + if (playerBank.remove(item)) familiarContainer.add(item) + if (familiarContainer.freeSlots() == 0) sendMessage(player, "Your familiar is full.") + + } + } + + sendMessage(player, "There is ${player.getBank().getAmount(Items.PURE_ESSENCE_7936)} Pure Essence remaining in your bank.") + } + + + + override fun defineListeners() { + + // BankBoothListener values are public but BankChestListener values are not, so rather than edit the BankChestListener file I have copied the IDs here. 12309 is the Culinomancer's chest. + val bankChests = intArrayOf(3194,4483,10562,14382,16695,16696,21301,27662,27663) + val bankUseWiths = intArrayOf(*BankBoothListener.BANK_BOOTHS, 12309, *bankChests) + + //6362 is the Ourania Altar banker. + val bankers = intArrayOf(*BankerNPC.NPC_IDS, *BankerNPC.SPECIAL_NPC_IDS, 6362) + + onUseWith(IntType.SCENERY, pouchIds, *bankUseWiths) { player, used, with -> + fillPouchFromBank(player) + return@onUseWith true + } + + onUseWith(IntType.NPC, pouchIds, *bankers) { player, used, with -> + fillPouchFromBank(player) + return@onUseWith true + } + } + + +} From 415aa512fbc0fec9fe4d8d6f407ab2d5c12fa2e5 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 1 Apr 2025 11:55:26 -0600 Subject: [PATCH 283/306] Satchels can now be emptied by using on a banker npc This is to address some banks (like zanaris) not having a bank booth --- .../global/handlers/item/SnowscapeSatchelListener.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt index d2fb6fbac..9f8709b6c 100755 --- a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -18,6 +18,7 @@ import core.game.component.Component import core.game.component.CloseEvent import core.game.container.access.InterfaceContainer import content.global.handlers.scenery.BankBoothListener +import content.global.handlers.npc.BankerNPC /** * Listener for satchels from Creature Creation, repurposed for Snowscape @@ -175,5 +176,13 @@ class SnowscapeSatchelListener : InteractionListener { return@onUseWith true } + //6362 is the Ourania Altar banker. + val bankers = intArrayOf(*BankerNPC.NPC_IDS, *BankerNPC.SPECIAL_NPC_IDS, 6362) + + onUseWith(IntType.NPC, satchelIds, *bankers) { player, used, with -> + emptySatchel(player, used.asItem().getId(), true) + return@onUseWith true + } + } } From 4053fdf43c09398154bb9403e6e652315addecc8 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 1 Apr 2025 11:58:25 -0600 Subject: [PATCH 284/306] Fixed null pointer exception when runecrafting without a familiar --- .../skill/runecrafting/SnowscapePouchListener.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt b/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt index 549c4445e..0c98a6268 100755 --- a/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt +++ b/Server/src/main/content/global/skill/runecrafting/SnowscapePouchListener.kt @@ -26,10 +26,12 @@ class SnowscapePouchListener : InteractionListener { // Called by the runecraft pulse fun emptyPouches(player: Player) { if (amountInInventory(player, Items.PURE_ESSENCE_7936) > 0 || amountInInventory(player, Items.RUNE_ESSENCE_1436) > 0) return - - val familiar = player.getFamiliarManager().getFamiliar() - if (familiar.isBurdenBeast() && (familiar as BurdenBeast).getContainer().containsAtLeastOneItem(Items.PURE_ESSENCE_7936)) { - (familiar as BurdenBeast).transfer(Item(Items.PURE_ESSENCE_7936), 99, true) + + if (player.getFamiliarManager().hasFamiliar()) { + val familiar = player.getFamiliarManager().getFamiliar() + if (familiar.isBurdenBeast() && (familiar as BurdenBeast).getContainer().containsAtLeastOneItem(Items.PURE_ESSENCE_7936)) { + (familiar as BurdenBeast).transfer(Item(Items.PURE_ESSENCE_7936), 99, true) + } } for (pouchId in pouchIds) { From b3196a282cd2de7860ac2b8901caf04f8b8c1d5b Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 2 Apr 2025 11:42:28 -0600 Subject: [PATCH 285/306] Implemented construction training in workshop As a temporary feature until making flatpacks is implemented, working at a workbench will simply consume planks for construction exp. Less clicking than creating and destroying tables over and over. Each plank type requires a specific construction level and workbench tier to use. --- .../decoration/workshop/SnowscapeWorkbench.kt | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Server/src/main/content/global/skill/construction/decoration/workshop/SnowscapeWorkbench.kt diff --git a/Server/src/main/content/global/skill/construction/decoration/workshop/SnowscapeWorkbench.kt b/Server/src/main/content/global/skill/construction/decoration/workshop/SnowscapeWorkbench.kt new file mode 100644 index 000000000..86974da72 --- /dev/null +++ b/Server/src/main/content/global/skill/construction/decoration/workshop/SnowscapeWorkbench.kt @@ -0,0 +1,104 @@ +package content.global.skill.construction.decoration.workshop + + + +import core.api.* +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.Node +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.node.scenery.Scenery +import core.game.node.item.Item +import org.rs09.consts.Items +import content.global.skill.construction.BuildingUtils + + +/** + * Simple replacement intil flatpacks are in. Using the workbench will consume planks in exchange for construction exp. + * + * + */ + +class SnowscapeWorkbench : InteractionListener { + + val workbenchIds = intArrayOf(13704,13705,13706,13707,13708) + val plankIds = intArrayOf(Items.PLANK_960, Items.OAK_PLANK_8778, Items.TEAK_PLANK_8780, Items.MAHOGANY_PLANK_8782) + + override fun defineListeners() { + defineInteraction( + IntType.SCENERY, + workbenchIds, + "work-at", + persistent = true, allowedDistance = 1, + handler = ::handlePlankConstruction + ) + } + + private fun handlePlankConstruction(player: Player, node: Node, state: Int) : Boolean { + if (!inInventory(player, Items.SAW_8794) || !inInventory(player, Items.HAMMER_2347)) { + sendMessage(player,"You need a hammer and saw to do that.") + player.scripts.reset() + return false + } + + for (plankId in plankIds) { + if (amountInInventory(player, plankId) > 0) { + if (node.id < getAllowedWorkbench(plankId)) { + sendMessage(player,"You need a better workbench to use ${Item(plankId).getName()}s.") + player.scripts.reset() + return false + } + if (getDynLevel(player, Skills.CONSTRUCTION) < getLevelRequirement(plankId)) { + sendMessage(player,"You need level ${getLevelRequirement(plankId)} construction to use ${Item(plankId).getName()}s.") + player.scripts.reset() + return false + } + + if (removeItem(player, Item(plankId, 1))) { + rewardXP(player, Skills.CONSTRUCTION, getExperience(plankId)) + animate(player, BuildingUtils.BUILD_MID_ANIM) //This animation has a sound effect built in + + return delayScript(player, 1) + } + } + } + + + sendMessage(player,"You have no planks in your inventory.") + player.scripts.reset() + return false + } + + // The following functions really should have been an enum class or something, but I don't know how to do that + + fun getAllowedWorkbench(plankId: Int) : Int { + return when (plankId) { + Items.PLANK_960 -> 13704 + Items.OAK_PLANK_8778 -> 13705 + Items.TEAK_PLANK_8780 -> 13706 + Items.MAHOGANY_PLANK_8782 -> 13707 + else -> 0 + } + } + + fun getExperience(plankId: Int) : Double { + return when (plankId) { + Items.PLANK_960 -> 30.0 + Items.OAK_PLANK_8778 -> 60.0 + Items.TEAK_PLANK_8780 -> 90.0 + Items.MAHOGANY_PLANK_8782 -> 140.0 + else -> 0.0 + } + } + + fun getLevelRequirement(plankId: Int) : Int { + return when (plankId) { + Items.PLANK_960 -> 1 + Items.OAK_PLANK_8778 -> 15 + Items.TEAK_PLANK_8780 -> 35 + Items.MAHOGANY_PLANK_8782 -> 40 + else -> 0 + } + } +} \ No newline at end of file From 3f0c44b1c3b9d6c6b8b96a5139dbe84c35e4bdf2 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 11 Apr 2025 12:07:51 -0600 Subject: [PATCH 286/306] Firemaking improments Improved the firemaking repeat pulse. Logs are now consumed after the space is verified, preventing loss of logs when running out of room. Additionally, the timing has changed to match the animation better. Firemaking now also repeats when done by using a log on a pyrelord. This requires a tinderbox in your inventory, so that the pulse can be interrupted by dropping it. Also fixed the bug where pyrelords could light logs you didn't have the firemaking level for. --- .../skill/firemaking/FireMakingPulse.java | 27 +++++----- .../skill/summoning/familiar/PyreLordNPC.java | 49 ++++++++++++------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java index a2612543d..7d9f0b35d 100644 --- a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java +++ b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java @@ -91,9 +91,14 @@ public final class FireMakingPulse extends SkillPulse { if (player.getAttribute("remove-log", false)) { player.removeAttribute("remove-log"); if (inInventory(player, node.getId(), 1)) { - replaceSlot(player, node.getSlot(), new Item(node.getId(), (node.getAmount() - 1)), node, Container.INVENTORY); + //replaceSlot(player, node.getSlot(), new Item(node.getId(), (node.getAmount() - 1)), node, Container.INVENTORY); + // Snowscape, remove any item instead of specific slot, and update the grounditem with our new location. + removeItem(player, new Item(node.getId(), 1), Container.INVENTORY); + this.groundItem = new GroundItem(node, player.getLocation(), player); GroundItemManager.create(groundItem); - } + } else { + return false; + } } return true; } @@ -110,25 +115,21 @@ public final class FireMakingPulse extends SkillPulse { return true; } */ - if (ticks == 0) { + if (ticks % 5 == 0) { player.animate(ANIMATION); } - if (++ticks % 3 != 0) { + if (++ticks % 5 != 0) { return false; } - if (ticks % 12 == 0) { - player.animate(ANIMATION); - } + if (!success()) { return false; } createFire(); - // Snowscape: attempt to remove another log. If successful, the pulse continues and the player makes another fire - if (removeItem(player, new Item(node.getId(), 1), Container.INVENTORY)) { - return false; - } else { - return true; - } + // Snowscape: return with the remove-log attribute, so the next pulse attempts to remove another log and start over + player.setAttribute("remove-log", true); + return false; + } diff --git a/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java b/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java index c4672b643..1e96d0229 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java @@ -23,6 +23,8 @@ import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Plugin; import core.plugin.ClassScanner; +import org.rs09.consts.Items; +import static core.api.ContentAPIKt.inInventory; /** * Represents the Pyrelord familiar. @@ -117,30 +119,41 @@ public class PyreLordNPC extends Familiar { player.getPacketDispatch().sendMessage("You can't light a fire here."); return false; } - familiar.lock(ticks); - familiar.animate(FIREMAKE_ANIMATION); - if (player.getInventory().remove(event.getUsedItem())) { - final GroundItem ground = GroundItemManager.create(event.getUsedItem(), familiar.getLocation(), player); + if (player.getSkills().getLevel(Skills.FIREMAKING) < log.getLevel()) { + player.getPacketDispatch().sendMessage("You need a firemaking level of " + log.getLevel() + " to light this log."); + return false; + } + familiar.lock(ticks); + familiar.animate(FIREMAKE_ANIMATION); + // Snowscape: reworked this pulse to repeat GameWorld.getPulser().submit(new Pulse(ticks, player, familiar) { @Override public boolean pulse() { - if (!ground.isActive()) { - return true; - } - final Scenery object = new Scenery(log.getFireId(), familiar.getLocation()); - familiar.moveStep(); - GroundItemManager.destroy(ground); - player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10); - familiar.faceLocation(object.getFaceLocation(familiar.getLocation())); - SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object)); - if (player.getViewport().getRegion().getId() == 10806) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9); - } - return true; + if (player.getInventory().remove(event.getUsedItem())) { + //familiar.lock(ticks-1); + familiar.animate(FIREMAKE_ANIMATION); + //final GroundItem ground = GroundItemManager.create(event.getUsedItem(), familiar.getLocation(), player); + //if (!ground.isActive()) { + // return false; + //} + final Scenery object = new Scenery(log.getFireId(), familiar.getLocation()); + //familiar.moveStep(); + //GroundItemManager.destroy(ground); + player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10); + familiar.faceLocation(object.getFaceLocation(familiar.getLocation())); + SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object)); + if (player.getViewport().getRegion().getId() == 10806) { + player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9); + } + if (inInventory(player, Items.TINDERBOX_590, 1)) { + return false; + } + } + return true; } }); - } return true; + } } From fa429edc03a101e07f7b756c12544f2a5015d365 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 12 Apr 2025 07:43:03 -0600 Subject: [PATCH 287/306] Fixed Ibis familiar foraging raw fish instead of cooked fish --- .../main/content/global/skill/summoning/familiar/IbisNPC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java b/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java index 43fc3702a..443268ff6 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java @@ -40,7 +40,7 @@ public class IbisNPC extends Forager { * @param id The id. */ public IbisNPC(Player owner, int id) { - super(owner, id, 3800, 12531, 12, new Item(361), new Item(373)); + super(owner, id, 3800, 12531, 12, new Item(359), new Item(371)); boosts.add(new SkillBonus(Skills.FISHING, 3)); } From 67990205b48f0eb01bf4725eaeb1479c80020106 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 12 Apr 2025 08:31:36 -0600 Subject: [PATCH 288/306] Fixed Ibis not rewarding exp when catching swordfish --- .../main/content/global/skill/summoning/familiar/IbisNPC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java b/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java index 443268ff6..7e0c82d73 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/IbisNPC.java @@ -54,7 +54,7 @@ public class IbisNPC extends Forager { @Override public boolean produceItem(Item item) { if (super.produceItem(item)) { - if (item.getId() == 373) { + if (item.getId() == 371) { owner.getSkills().addExperience(Skills.FISHING, 10); } return true; From af446a4c2799b2764561cf93b32533db5e57b925 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 17 Apr 2025 09:47:30 -0600 Subject: [PATCH 289/306] Changed Construction Workbenches to no longer require upgrading Since hotspot upgrading is not in, they were requiring an unobtainable item in order to craft. They now only require oak planks and steel bars. The ammounts have been increased to compensate for the lack of upgrade mechanic. --- .../main/content/global/skill/construction/Decoration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/Decoration.java b/Server/src/main/content/global/skill/construction/Decoration.java index 6229dff82..95ad2c9b3 100644 --- a/Server/src/main/content/global/skill/construction/Decoration.java +++ b/Server/src/main/content/global/skill/construction/Decoration.java @@ -214,8 +214,8 @@ public enum Decoration { WORKBENCH_WOODEN (13704, 8375, 17, 143, new Item[] { new Item(Items.PLANK_960, 5) }), WORKBENCH_OAK (13705, 8376, 32, 300, new Item[] { new Item(Items.OAK_PLANK_8778, 5) }), WORKBENCH_STEEL_FRAME(13706, 8377, 46, 440, new Item[] { new Item(Items.OAK_PLANK_8778, 6), new Item(Items.STEEL_BAR_2353, 4) }), - WORKBENCH_WITH_VICE (13707, 8378, 62, 750, new Item[] { new Item(Items.STEEL_FRAMED_BENCH_8377), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), - WORKBENCH_WITH_LATHE (13708, 8379, 77, 1000, new Item[] { new Item(Items.OAK_WORKBENCH_8376), new Item(Items.OAK_PLANK_8778, 2), new Item(Items.STEEL_BAR_2353) }), + WORKBENCH_WITH_VICE (13707, 8378, 62, 750, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.STEEL_BAR_2353, 5) }), + WORKBENCH_WITH_LATHE (13708, 8379, 77, 1000, new Item[] { new Item(Items.OAK_PLANK_8778, 8), new Item(Items.STEEL_BAR_2353, 6) }), /** * Workshop repair benches/stands From 7e8c2d8883ec5e7d1f36da98fe9f4239224b7080 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 21 Apr 2025 11:36:02 -0600 Subject: [PATCH 290/306] Herblore makes potions with 4 doses instead of 3. --- .../global/skill/herblore/FinishedPotion.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Server/src/main/content/global/skill/herblore/FinishedPotion.java b/Server/src/main/content/global/skill/herblore/FinishedPotion.java index e78d80432..38a71f84d 100644 --- a/Server/src/main/content/global/skill/herblore/FinishedPotion.java +++ b/Server/src/main/content/global/skill/herblore/FinishedPotion.java @@ -8,34 +8,34 @@ import org.rs09.consts.Items; * @author 'Vexia */ public enum FinishedPotion { - ATTACK_POTION(UnfinishedPotion.GUAM, new Item(221), 3, 25, new Item(121)), - ANTIPOISON_POTION(UnfinishedPotion.MARRENTILL, new Item(235), 5, 37.5, new Item(175)), - STRENGTH_POTION(UnfinishedPotion.TARROMIN, new Item(225), 12, 50, new Item(115)), - RESTORE_POTION(UnfinishedPotion.HARRALANDER, new Item(223), 22, 62.5, new Item(127)), - ENERGY_POTION(UnfinishedPotion.HARRALANDER, new Item(1975), 26, 67.5, new Item(3010)), - DEFENCE_POTION(UnfinishedPotion.RANARR, new Item(239), 30, 45, new Item(133)), - AGILITY_POTION(UnfinishedPotion.TOADFLAX, new Item(2152), 34, 80, new Item(3034)), - COMBAT_POTION(UnfinishedPotion.HARRALANDER, new Item(9736), 36, 84, new Item(9741)), - PRAYER_POTION(UnfinishedPotion.RANARR, new Item(231), 38, 87.5, new Item(139)), - SUMMONING_POTION(UnfinishedPotion.SPIRIT_WEED, new Item(12109), 40, 92, new Item(12142)), - SUPER_ATTACK(UnfinishedPotion.IRIT, new Item(221), 45, 100, new Item(145)), - SUPER_ANTIPOISON(UnfinishedPotion.IRIT, new Item(235), 48, 106.3, new Item(181)), - FISHING_POTION(UnfinishedPotion.AVANTOE, new Item(231), 50, 112.5, new Item(151)), - SUPER_ENERGY(UnfinishedPotion.AVANTOE, new Item(2970), 52, 117.5, new Item(3018)), - HUNTING_POTION(UnfinishedPotion.AVANTOE, new Item(Items.KEBBIT_TEETH_DUST_10111), 53, 120, new Item(10000)), - SUPER_STRENGTH(UnfinishedPotion.KWUARM, new Item(225), 55, 125, new Item(157)), + ATTACK_POTION(UnfinishedPotion.GUAM, new Item(221), 3, 25, new Item(2428)), + ANTIPOISON_POTION(UnfinishedPotion.MARRENTILL, new Item(235), 5, 37.5, new Item(2446)), + STRENGTH_POTION(UnfinishedPotion.TARROMIN, new Item(225), 12, 50, new Item(113)), + RESTORE_POTION(UnfinishedPotion.HARRALANDER, new Item(223), 22, 62.5, new Item(2430)), + ENERGY_POTION(UnfinishedPotion.HARRALANDER, new Item(1975), 26, 67.5, new Item(3008)), + DEFENCE_POTION(UnfinishedPotion.RANARR, new Item(239), 30, 45, new Item(2432)), + AGILITY_POTION(UnfinishedPotion.TOADFLAX, new Item(2152), 34, 80, new Item(3032)), + COMBAT_POTION(UnfinishedPotion.HARRALANDER, new Item(9736), 36, 84, new Item(9739)), + PRAYER_POTION(UnfinishedPotion.RANARR, new Item(231), 38, 87.5, new Item(2434)), + SUMMONING_POTION(UnfinishedPotion.SPIRIT_WEED, new Item(12109), 40, 92, new Item(12140)), + SUPER_ATTACK(UnfinishedPotion.IRIT, new Item(221), 45, 100, new Item(2436)), + SUPER_ANTIPOISON(UnfinishedPotion.IRIT, new Item(235), 48, 106.3, new Item(2448)), + FISHING_POTION(UnfinishedPotion.AVANTOE, new Item(231), 50, 112.5, new Item(2438)), + SUPER_ENERGY(UnfinishedPotion.AVANTOE, new Item(2970), 52, 117.5, new Item(3016)), + HUNTING_POTION(UnfinishedPotion.AVANTOE, new Item(Items.KEBBIT_TEETH_DUST_10111), 53, 120, new Item(9998)), + SUPER_STRENGTH(UnfinishedPotion.KWUARM, new Item(225), 55, 125, new Item(2440)), WEAPON_POISON(UnfinishedPotion.KWUARM, new Item(241), 60, 137.5, new Item(187)), - SUPER_RESTORE(UnfinishedPotion.SNAPDRAGON, new Item(223), 63, 142.5, new Item(3026)), - SUPER_DEFENCE(UnfinishedPotion.CADANTINE, new Item(239), 66, 160, new Item(163)), - ANTIFIRE(UnfinishedPotion.LANTADYME, new Item(241), 69, 157.5, new Item(2454)), - SUPER_RANGING_POTION(UnfinishedPotion.DWARF_WEED, new Item(245), 72, 162.5, new Item(169)), - SUPER_MAGIC(UnfinishedPotion.LANTADYME, new Item(3138), 76, 172.5, new Item(3042)), - ZAMORAK_BREW(UnfinishedPotion.TORSTOL, new Item(247), 78, 175, new Item(189)), - SARADOMIN_BREW(UnfinishedPotion.TOADFLAX, GrindingItem.BIRDS_NEST.getProduct(), 81, 180, new Item(6687)), + SUPER_RESTORE(UnfinishedPotion.SNAPDRAGON, new Item(223), 63, 142.5, new Item(3024)), + SUPER_DEFENCE(UnfinishedPotion.CADANTINE, new Item(239), 66, 160, new Item(2442)), + ANTIFIRE(UnfinishedPotion.LANTADYME, new Item(241), 69, 157.5, new Item(2452)), + SUPER_RANGING_POTION(UnfinishedPotion.DWARF_WEED, new Item(245), 72, 162.5, new Item(2444)), + SUPER_MAGIC(UnfinishedPotion.LANTADYME, new Item(3138), 76, 172.5, new Item(3040)), + ZAMORAK_BREW(UnfinishedPotion.TORSTOL, new Item(247), 78, 175, new Item(2450)), + SARADOMIN_BREW(UnfinishedPotion.TOADFLAX, GrindingItem.BIRDS_NEST.getProduct(), 81, 180, new Item(6685)), STRONG_WEAPON_POISON(UnfinishedPotion.STRONG_WEAPON_POISON, new Item(223), 73, 165, new Item(5937)), SUPER_STRONG_WEAPON_POISON(UnfinishedPotion.SUPER_STRONG_WEAPON_POISON, new Item(6018), 82, 190, new Item(5940)), - STRONG_ANTIPOISON(UnfinishedPotion.STRONG_ANTIPOISON, new Item(6049), 68, 155, new Item(5945)), - SUPER_STRONG_ANTIPOISON(UnfinishedPotion.SUPER_STRONG_ANTIPOISON, new Item(6051), 79, 177.5, new Item(5954)), + STRONG_ANTIPOISON(UnfinishedPotion.STRONG_ANTIPOISON, new Item(6049), 68, 155, new Item(5943)), + SUPER_STRONG_ANTIPOISON(UnfinishedPotion.SUPER_STRONG_ANTIPOISON, new Item(6051), 79, 177.5, new Item(5952)), BLAMISH_OIL(UnfinishedPotion.HARRALANDER, new Item(1581), 25, 80, new Item(1582)); /** From 52185005aa1005c435c9c01b0c53717bda9b856d Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 6 May 2025 10:57:31 -0600 Subject: [PATCH 291/306] Enchanting spells repeat if there are more of the same item in the player inventory --- Server/src/main/content/minigame/mta/EnchantSpell.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Server/src/main/content/minigame/mta/EnchantSpell.kt b/Server/src/main/content/minigame/mta/EnchantSpell.kt index fc8878a27..07cebf2a6 100644 --- a/Server/src/main/content/minigame/mta/EnchantSpell.kt +++ b/Server/src/main/content/minigame/mta/EnchantSpell.kt @@ -14,6 +14,7 @@ import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Graphics import core.plugin.Plugin import org.rs09.consts.Items +import core.api.* /** * Represents the enchant spells. @@ -46,11 +47,12 @@ class EnchantSpell : MagicSpell { if (target !is Item || entity !is Player) { return false } - entity.interfaceManager.setViewedTab(6) + //entity.interfaceManager.setViewedTab(6) val enchanted = jewellery?.getOrDefault(target.id,null) if (enchanted == null) { entity.packetDispatch.sendMessage("You can't use this spell on this item.") + entity.interfaceManager.setViewedTab(6) return false } if (!meetsRequirements(entity, true, true)) { @@ -89,6 +91,13 @@ class EnchantSpell : MagicSpell { content.minigame.mta.impl.EnchantingZone.ZONE.incrementPoints(entity, MTAType.ENCHANTERS.ordinal, pizazz) } } + + // Snowscape: if there are more items to enchant, run the spell again + if (entity.inventory.containsAtLeastOneItem(target)) { + runTask(entity, 2){ + castSpell(entity as Player, super.book, super.spellId, target) + } + } return true } From cecdb97b195529437d0e4c2b0d2eb81c1d841b0b Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 13 May 2025 14:29:51 -0600 Subject: [PATCH 292/306] Several Housing improvements Can enter house from any house portal in the world, and can exit to any portal the owner has the construction level to move their house to. Can enter house even if owner is not home. House is no longer unloaded when the owner leaves, instead is unloaded when the last player leaves. Guests are kicked when owner logs out. Locking house persists after logout/login. Using the Building mode buttons when outside the house allows remotely locking/unlocking the house. Teleport to House and Tablet now teleport to the last house that was entered through a house portal, if it is online and unlocked. Falls back to your own house if that fails. --- .../item/HouseTeleTabOptionListener.kt | 24 +++- .../skill/construction/HouseManager.java | 7 +- .../global/skill/construction/HouseZone.java | 4 +- .../construction/PortalOptionPlugin.java | 121 +++++++++++++++++- .../skill/magic/modern/ModernListeners.kt | 24 +++- .../core/game/node/entity/player/Player.java | 1 + .../entity/player/info/login/PlayerSaver.kt | 1 + 7 files changed, 165 insertions(+), 17 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt b/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt index 61ac1b029..ee6e3f1b8 100644 --- a/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt +++ b/Server/src/main/content/global/handlers/item/HouseTeleTabOptionListener.kt @@ -5,24 +5,34 @@ import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.player.link.TeleportManager import core.game.node.item.Item +import core.game.node.entity.player.Player +import core.game.world.repository.Repository class HouseTeleTabOptionListener : InteractionListener { override fun defineListeners() { val homeTabID = 8013 on(homeTabID, IntType.ITEM, "break") {player, node -> - var hasHouse = player.houseManager.location.exitLocation != null - if (!hasHouse) { - sendMessage( player, "You must have a house to teleport to before attempting that.") - return@on false + //Snowscape: teleport to the last house you entered, if possible + var owner: Player + val lastHouseOwner = Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)) + if (lastHouseOwner != null && !lastHouseOwner.getHouseManager().isLocked()) { + owner = lastHouseOwner + } else { + var hasHouse = player.houseManager.location.exitLocation != null + if (!hasHouse) { + sendMessage( player, "You must have a house to teleport to before attempting that.") + return@on false + } + owner = player } closeInterface(player) lock(player, 5) if (inInventory(player, node.id)) { - player.houseManager.preEnter(player, false) - val location = player.houseManager.getEnterLocation() + owner.houseManager.preEnter(player, false) + val location = owner.houseManager.getEnterLocation() if (teleport(player, location, TeleportManager.TeleportType.TELETABS)) { removeItem(player, Item(node.id, 1)) - player.houseManager.postEnter(player, false) + owner.houseManager.postEnter(player, false) } } return@on true diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 01a37f377..65ee6c3d9 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -101,6 +101,9 @@ public final class HouseManager { public void parse(JSONObject data){ location = HouseLocation.values()[Integer.parseInt( data.get("location").toString())]; style = HousingStyle.values()[Integer.parseInt( data.get("style").toString())]; + if (data.get("locked") != null) { + locked = true; + } Object servRaw = data.get("servant"); if(servRaw != null){ servant = Servant.parse((JSONObject) servRaw); @@ -225,7 +228,9 @@ public final class HouseManager { */ public void toggleBuildingMode(Player player, boolean enable) { if (!isInHouse(player)) { - player.getPacketDispatch().sendMessage("Building mode really only helps if you're in a house."); + //player.getPacketDispatch().sendMessage("Building mode really only helps if you're in a house."); + setLocked(enable); + player.sendMessage("Your house is now "+(player.getHouseManager().isLocked() ? "locked." : "unlocked." )); return; } if (buildingMode != enable) { diff --git a/Server/src/main/content/global/skill/construction/HouseZone.java b/Server/src/main/content/global/skill/construction/HouseZone.java index ccd426c19..33f875362 100644 --- a/Server/src/main/content/global/skill/construction/HouseZone.java +++ b/Server/src/main/content/global/skill/construction/HouseZone.java @@ -92,7 +92,9 @@ public final class HouseZone extends MapZone { if (e instanceof Player) { Player p = (Player) e; // The below tears down the house if the owner was the one who left - if (house == p.getHouseManager()) { + //if (house == p.getHouseManager()) { + // Snowscape: tear down the house when the last person leaves, allowing guests to stay in the house without the owner. + if (!house.getHouseRegion().isViewed() && (!house.hasDungeon() || !house.getDungeonRegion().isViewed())) { house.expelGuests(p); int toRemove = previousRegion; int dungRemove = previousDungeon; diff --git a/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java b/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java index 23d951dac..23d9621a2 100644 --- a/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java +++ b/Server/src/main/content/global/skill/construction/PortalOptionPlugin.java @@ -8,6 +8,7 @@ import core.game.dialogue.DialoguePlugin; import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.player.Player; +import core.game.node.entity.skill.Skills; import core.game.node.scenery.Scenery; import core.plugin.Initializable; import core.plugin.Plugin; @@ -33,6 +34,7 @@ public final class PortalOptionPlugin extends OptionHandler { SceneryDefinition.forId(13405).getHandlers().put("option:lock", this); SceneryDefinition.forId(13405).getHandlers().put("option:enter", this); ClassScanner.definePlugin(new PortalDialogue()); + ClassScanner.definePlugin(new PortalExitDialogue()); return this; } @@ -40,7 +42,8 @@ public final class PortalOptionPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { Scenery object = node.asScenery(); if (object.getId() == 13405 && option.equals("enter")) { - HouseManager.leave(player); + player.getDialogueInterpreter().open("houseExitDialogue"); + //HouseManager.leave(player); return true; } if (option.equals("lock")) { @@ -111,11 +114,14 @@ public final class PortalOptionPlugin extends OptionHandler { break; } //If the Player has a house, but does not have their house moved to the portal they are interacting with + /* Snowscape: allow entering house from anywhere if (player.getHouseManager().getLocation().getPortalId() != player.getAttribute("con:portal", -1)) { player.getPacketDispatch().sendMessage("Your house is in " + player.getHouseManager().getLocation().getName() + "."); player.sendMessage("Speak with an estate agent to change your house location."); break; } + */ + player.removeAttribute("lasthouseentered"); player.getHouseManager().enter(player, buttonId == 2); break; case 3: @@ -134,10 +140,12 @@ public final class PortalOptionPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("You aren't a friend of yourself!"); return Unit.INSTANCE; } + /* Snowscape: allow entering house if host is not home. if (!p.getHouseManager().isLoaded()) { player.getPacketDispatch().sendMessage("This player is not at home right now."); return Unit.INSTANCE; } + */ if (p.getHouseManager().isBuildingMode()) { player.getPacketDispatch().sendMessage("This player is in building mode."); return Unit.INSTANCE; @@ -146,6 +154,7 @@ public final class PortalOptionPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("The other player has locked their house."); return Unit.INSTANCE; } + player.setAttribute("/save:lasthouseentered", (String) value); p.setAttribute("poh_owner", (String) value); p.getHouseManager().enter(player, false); return Unit.INSTANCE; @@ -162,4 +171,114 @@ public final class PortalOptionPlugin extends OptionHandler { return new int[] { DialogueInterpreter.getDialogueKey("con:portal") }; } } + + + + /** + * Snowscape: select destination via dialogue when leaving the house + * + */ + @PluginManifest(type= PluginType.DIALOGUE) + private class PortalExitDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code PortalExitDialogue} {@code Object} + */ + public PortalExitDialogue() { + + } + + /** + * Constructs a new {@code PortalExitDialogue} {@code Object} + * @param player The player. + */ + public PortalExitDialogue(Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new PortalExitDialogue(player); + } + + @Override + public boolean open(Object... args) { + options("Leave house (home location)", "Rimmington", "Taverly", "Pollnivneach", "Next Page"); + stage = 1; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 1: + switch (buttonId) { + case 1: + HouseManager.leave(player); + end(); + break; + case 2: + attemptHouseExit(HouseLocation.RIMMINGTON); + end(); + break; + case 3: + attemptHouseExit(HouseLocation.TAVERLY); + end(); + break; + case 4: + attemptHouseExit(HouseLocation.POLLNIVNEACH); + end(); + break; + case 5: + options("Rellekka", "Brimhaven","Yanille", "Cancel"); + stage = 2; + break; + } + break; + case 2: + switch (buttonId) { + case 1: + attemptHouseExit(HouseLocation.RELLEKKA); + end(); + break; + case 2: + attemptHouseExit(HouseLocation.BRIMHAVEN); + end(); + break; + case 3: + attemptHouseExit(HouseLocation.YANILLE); + end(); + break; + case 4: + end(); + break; + } + } + return true; + } + + @Override + public int[] getIds() { + return new int[] { DialogueInterpreter.getDialogueKey("houseExitDialogue") }; + } + + public void attemptHouseExit(HouseLocation targetLocation){ + int level = 0; + String message = null; + if (player.getHouseManager().isInHouse(player)) { + level = getStatLevel(player, Skills.CONSTRUCTION); + message = "You need "; + } else { + level = getStatLevel(Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)), Skills.CONSTRUCTION); + message = "The house owner needs "; + } + + if (targetLocation.getLevelRequirement() <= level){ + //player.animate(Animation.RESET); + player.getProperties().setTeleportLocation(targetLocation.getExitLocation()); + } else { + player.sendMessage(message + targetLocation.getLevelRequirement() + " Construction to for you to teleport to " + targetLocation.getName() + "."); + } + } + } } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 16c7f8fbe..6b96e386a 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -33,6 +33,7 @@ import org.rs09.consts.Scenery import org.rs09.consts.Sounds import core.game.system.task.Pulse +import core.game.world.repository.Repository class ModernListeners : SpellListener("modern"){ override fun defineListeners() { @@ -370,17 +371,26 @@ class ModernListeners : SpellListener("modern"){ player.sendMessage("A magical force prevents you from teleporting.") return } - val hasHouse = player.houseManager.location.exitLocation != null - if(!hasHouse){ - player.sendMessage("You do not have a house you can teleport to.") - return + + //Snowscape: teleport to the last house you entered, if possible + var houseOwner: Player + val lastHouseOwner = Repository.getPlayerByName(player.getAttribute("lasthouseentered", null)) + if (lastHouseOwner != null && !lastHouseOwner.getHouseManager().isLocked()) { + houseOwner = lastHouseOwner + } else { + val hasHouse = player.houseManager.location.exitLocation != null + if(!hasHouse){ + player.sendMessage("You do not have a house you can teleport to.") + return + } + houseOwner = player } - player.houseManager.preEnter(player, false) + houseOwner.houseManager.preEnter(player, false) val teleType = TeleportManager.TeleportType.NORMAL - val loc = player.houseManager.getEnterLocation() + val loc = houseOwner.houseManager.getEnterLocation() player.teleporter.send(loc, teleType) - player.houseManager.postEnter(player, false) //this actually runs when the teleport is SUBMITTED rather than EXECUTED, but this is fine + houseOwner.houseManager.postEnter(player, false) //this actually runs when the teleport is SUBMITTED rather than EXECUTED, but this is fine removeRunes(player) addXP(player,30.0) setDelay(player,true) diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 52c286223..436e83475 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -378,6 +378,7 @@ public class Player extends Entity { interfaceManager.closeSingleTab(); super.clear(); getZoneMonitor().clear(); + houseManager.expelGuests(this); HouseManager.leave(this); UpdateSequence.getRenderablePlayers().remove(this); sendLogoutEvents(); diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 2709ae12a..56d018d9a 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -191,6 +191,7 @@ class PlayerSaver (val player: Player){ fun saveHouseData(root: JSONObject){ val manager = player.houseManager val houseData = JSONObject() + if (manager.isLocked) houseData.put("locked", true) houseData.put("location",manager.location.ordinal.toString()) houseData.put("style",manager.style.ordinal.toString()) if(manager.hasServant()){ From 2ad90e9ed86869a2b1210d90a9240c74927778bf Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 14 Aug 2025 16:47:56 -0600 Subject: [PATCH 293/306] Fixed Combiniation rune consumption and rebalanced rune satchel Combination runes have been fixed. A spell using 1 air and 1 earth rune will now only use 1 dust rune instead of 2. Rune satchel has been changed. Instead of allowing only catalytic runes, it now allows all runes but only has 6 slots. In addition, combination runes can be used from the satchel. --- Server/data/configs/item_configs.json | 2 +- .../handlers/item/SnowscapeSatchelListener.kt | 7 +-- .../content/global/skill/magic/SpellUtils.kt | 42 ++++++++++++++++- .../node/entity/combat/spell/MagicSpell.java | 46 +++++++++++++++++++ .../core/game/node/entity/player/Player.java | 2 +- 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 6e08c6501..982b254a1 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -93970,7 +93970,7 @@ "equipment_slot": "5" }, { - "examine": "I can keep my catalytic runes in here.", + "examine": "I can keep my runes in here.", "durability": null, "name": "Rune satchel", "weight": "0.1", diff --git a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt index 9f8709b6c..872c94341 100755 --- a/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt +++ b/Server/src/main/content/global/handlers/item/SnowscapeSatchelListener.kt @@ -37,10 +37,6 @@ class SnowscapeSatchelListener : InteractionListener { val runeSatchelId = 10882 val satchelIds = intArrayOf(plainSatchelId,greenSatchelId,redSatchelId,blackSatchelId,goldSatchelId,runeSatchelId) - //val runeSatchelAllowed = intArrayOf(558,559,564,562,9075,561,563,560,565,566) - //val runesForbidden = intArrayOf(556,555,557,554,4695,4696,4698,4697,4694,4699) - - @@ -103,7 +99,6 @@ class SnowscapeSatchelListener : InteractionListener { // This is called by BurdenInterfacePlugin.java when the player interacts with the familiar interface and the "openSatchel" attribute exists fun satchelInterfaceAction(player: Player, component: Component, opcode: Int, button: Int, slot: Int, itemId: Int) { - //player.sendMessage("Button:" + button.toString() + ". Opcode:" + opcode.toString()) val satchelId = getAttribute(player, "openSatchel", 0) val withdraw = component.getId() == 671 val container = if (withdraw) getSatchel(player, satchelId) else player.getInventory() @@ -142,7 +137,7 @@ class SnowscapeSatchelListener : InteractionListener { redSatchelId -> return itemId in intArrayOf(*(12158..12168).toList().toIntArray()) || Item(itemId).getName().equals("Clue scroll") blackSatchelId -> return itemId in intArrayOf(995) goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892,2349,2351,2353,2355,2357,2359,2361,2363,2365,1601,1603,1605,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625,1627,1629,1631,6571,6573) - runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566) || (getAttribute(player,"snowscape:boostedmode",false) && itemId in intArrayOf(556,555,557,554,4694,4695,4696,4697,4698,4699)) + runeSatchelId -> return itemId in intArrayOf(556,555,557,554,558,559,564,562,9075,561,563,560,565,566,4694,4695,4696,4697,4698,4699) } return false } diff --git a/Server/src/main/content/global/skill/magic/SpellUtils.kt b/Server/src/main/content/global/skill/magic/SpellUtils.kt index ce84d606f..2f44a37e0 100644 --- a/Server/src/main/content/global/skill/magic/SpellUtils.kt +++ b/Server/src/main/content/global/skill/magic/SpellUtils.kt @@ -21,7 +21,45 @@ object SpellUtils { return false } - // Snowscape modifications: check the runeStachel container for the base runes if the player is carrying one + // Snowscape modifications: replaced entire "hasrune" function to only check the inventory once per rune, so the rune satchel has less overhead. + fun hasRune(p:Player,rune:Item):Boolean{ + if(usingStaff(p,rune.id)) return true + val removeItems = p.getAttribute("spell:runes",ArrayList()) + + val baseAmt = kotlin.math.max(p.inventory.getAmount(rune.id),(if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(rune.id) else 0)) + + if(baseAmt >= 0){ + removeItems.add(Item(rune.getId(),kotlin.math.min(baseAmt,rune.getAmount()))) + p.setAttribute("spell:runes",removeItems) + } + + var amtRemaining = rune.amount - baseAmt + val possibleComboRunes = CombinationRune.eligibleFor(Runes.forId(rune.id)) + for (r in possibleComboRunes) { + // Check if this combination rune was already added for a different element + for (alreadyListed in removeItems){ + if (alreadyListed.getId() == r.id){ + amtRemaining -= alreadyListed.getAmount() + } + } + + val amt = kotlin.math.max(p.inventory.getAmount(r.id),(if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(r.id) else 0)) + if (amt > 0 && amtRemaining > 0) { + + if (amtRemaining <= amt) { + removeItems.add(Item(r.id,amtRemaining)) + amtRemaining = 0 + break + } + removeItems.add(Item(r.id,amt)) + amtRemaining -= amt + } + } + p.setAttribute("spell:runes",removeItems) + return amtRemaining <= 0 + } + +/* Snowscape: Original function left here for easier merging of updates. fun hasRune(p:Player,rune:Item):Boolean{ val removeItems = p.getAttribute("spell:runes",ArrayList()) if(usingStaff(p,rune.id)) return true @@ -83,7 +121,7 @@ object SpellUtils { } return true } - +*/ fun attackableNPC(npc: NPC): Boolean{ return npc.definition.hasAction("attack") } diff --git a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java index 250e9489d..aee3cbf05 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/MagicSpell.java @@ -278,6 +278,51 @@ public abstract class MagicSpell implements Plugin { * @param message the message. * @return {@code True} if so. */ + // Snowscape modifications: replaced entire "hasrune" function to only check the inventory once per rune, so the rune satchel has less overhead. + public boolean hasRune(Player p, Item item, List toRemove, boolean message) { + if (!usingStaff(p, item.getId())) { + boolean hasBaseRune = p.getInventory().contains(item.getId(),item.getAmount()) || (inEquipmentOrInventory(p, 10882,1) && p.runeSatchel.contains(item.getId(),item.getAmount())); + if(!hasBaseRune){ + int baseAmt = Math.max(p.getInventory().getAmount(item.getId()),((inEquipmentOrInventory(p, 10882,1)) ? p.runeSatchel.getAmount(item.getId()) : 0)); + if(baseAmt > 0){ + toRemove.add(new Item(item.getId(),Math.min(baseAmt,item.getAmount()))); + } + int amtRemaining = item.getAmount() - baseAmt; + List possibleComboRunes = CombinationRune.eligibleFor(Runes.forId(item.getId())); + for(CombinationRune r : possibleComboRunes){ + // Check if this combination rune was already added for a different element + for(Item alreadyListed : toRemove){ + if (alreadyListed.getId() == r.id){ + amtRemaining -= alreadyListed.getAmount(); + } + } + + int amt = Math.max(p.getInventory().getAmount(r.id),((inEquipmentOrInventory(p, 10882,1)) ? p.runeSatchel.getAmount(r.id) : 0)); + if(amt > 0 && amtRemaining > 0){ + + if(amtRemaining < amt){ + toRemove.add(new Item(r.id,amtRemaining)); + amtRemaining = 0; + continue; + } + amtRemaining -= amt; + toRemove.add(new Item(r.id,amt)); + } + } + if(amtRemaining <= 0){ + return true; + } else { + p.getPacketDispatch().sendMessage("You don't have enough " + item.getName() + "s to cast this spell."); + return false; + } + } + toRemove.add(item); + return true; + } + return true; + } + +/* Snowscape: Original function left here for easier merging of updates. public boolean hasRune(Player p, Item item, List toRemove, boolean message) { if (!usingStaff(p, item.getId())) { // Snowscape modification: check the rune satchel for the base runes if the player is carrying one @@ -313,6 +358,7 @@ public abstract class MagicSpell implements Plugin { } return true; } +*/ /** * Adds the experience for casting this spell. diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 436e83475..883a188a4 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -318,7 +318,7 @@ public class Player extends Entity { public final Container redSatchel = new Container(30, ContainerType.ALWAYS_STACK); public final Container blackSatchel = new Container(30, ContainerType.ALWAYS_STACK); public final Container goldSatchel = new Container(30, ContainerType.ALWAYS_STACK); - public final Container runeSatchel = new Container(30, ContainerType.ALWAYS_STACK); + public final Container runeSatchel = new Container(6, ContainerType.ALWAYS_STACK); // The summoning pouch storage public final Container summoningPouches = new Container(30); // The costume room bank From a9065d763b2353dd648a0be854d6e59f28748a09 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 14 Aug 2025 16:56:30 -0600 Subject: [PATCH 294/306] Even more steps to remove random events --- Server/src/main/core/game/system/timer/impl/AntiMacro.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt index 8968827b7..35d3ca2cc 100644 --- a/Server/src/main/core/game/system/timer/impl/AntiMacro.kt +++ b/Server/src/main/core/game/system/timer/impl/AntiMacro.kt @@ -20,6 +20,10 @@ class AntiMacro : PersistTimer(0, "antimacro", isAuto = true), Commands { var nextRandom: RandomEvents? = null override fun run(entity: Entity): Boolean { + //Snowscape: prevent random events entirely + entity.timers.removeTimer(this) + return false + if (entity !is Player) return false setNextExecution() From 6e91725d588850fb8686227123914c21711e0a45 Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 15 Aug 2025 11:03:21 -0600 Subject: [PATCH 295/306] Ghostly Robes now also prevent NPC aggro when the full set is worn This is shared with the Protect from Summoning prayer. In addition, the effect was improved so a hidden player cannot shield another player from aggro by standing between them and the NPC Fixed missing animations and sounds for the Shadow Sword --- Server/data/configs/item_configs.json | 3 +++ .../entity/npc/agg/AggressiveBehavior.java | 21 +++++++++++++++++++ .../entity/npc/agg/AggressiveHandler.java | 5 ----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 982b254a1..3c29faaa8 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -93782,6 +93782,9 @@ "archery_ticket_price": "0", "id": "10858", "stand_turn_anim": "7040", + "defence_anim": "7050", + "attack_anims": "7041,7041,7048,7049", + "attack_audios": "2503,0,2504,0", "bonuses": "-4,27,21,4,0,0,0,0,4,-1,0,26,0,0,0" }, { diff --git a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java index 50f93be3f..ae740b8f4 100644 --- a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java +++ b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java @@ -10,6 +10,9 @@ import core.game.world.map.RegionManager; import java.util.ArrayList; import java.util.List; +import core.game.node.entity.player.link.prayer.PrayerType; +import static core.api.ContentAPIKt.allInEquipment; + /** * Handles an NPC's aggressive behaviour. * @author Emperor @@ -41,6 +44,9 @@ public class AggressiveBehavior { return false; } if (target instanceof Player) { + if (ignorePlayer((Player) target)) { + return false; + } return ((Player) target).getSkullManager().isWilderness(); } return true; @@ -70,6 +76,9 @@ public class AggressiveBehavior { return false; } if (entity instanceof NPC && target instanceof Player) { + if (ignorePlayer((Player) target)) { + return false; + } NPC npc = (NPC) entity; if (npc.getAggressiveHandler() != null && npc.getAggressiveHandler().isAllowTolerance() && !WildernessZone.isInZone(npc)) { if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) { @@ -88,6 +97,18 @@ public class AggressiveBehavior { return false; } + //Snowscape: allow players to hide from aggressive mobs with the protect from summoning prayer, or full ghostly robe set + public boolean ignorePlayer(Player player) { + if (player.getPrayer().get(PrayerType.PROTECT_FROM_SUMMONING)) { + return true; + } + //Check if player is wearing full ghostly robe set + if (allInEquipment(player, 6106, 6107, 6108, 6109, 6110, 6111)) { + return true; + } + return false; + } + /** * Gets the priority flag. * @param target The target. diff --git a/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java b/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java index 5ee281bb4..c2a49842d 100644 --- a/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java +++ b/Server/src/main/core/game/node/entity/npc/agg/AggressiveHandler.java @@ -9,8 +9,6 @@ import core.game.node.entity.player.info.Rights; import core.game.world.GameWorld; import core.tools.RandomFunction; -import core.game.node.entity.player.link.prayer.PrayerType; - /** * Used to handle entity aggressiveness. * @author Emperor @@ -83,9 +81,6 @@ public final class AggressiveHandler { } Entity target = behavior.getLogicalTarget(entity, behavior.getPossibleTargets(entity, radius)); if (target instanceof Player) { - if (((Player) target).getPrayer().get(PrayerType.PROTECT_FROM_SUMMONING)) { - return false; - } if (target.getAttribute("ignore_aggression", false)) { return false; } From 06055c0ff80043ca2ef6c0cd579e878d4191561a Mon Sep 17 00:00:00 2001 From: randy Date: Fri, 15 Aug 2025 11:41:12 -0600 Subject: [PATCH 296/306] Remove another check preventing Ancient magick teleport spells from working in the wilderness for non-admins. --- .../main/core/game/world/map/zone/impl/WildernessZone.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/core/game/world/map/zone/impl/WildernessZone.java b/Server/src/main/core/game/world/map/zone/impl/WildernessZone.java index c06ba08ce..f6882e52b 100644 --- a/Server/src/main/core/game/world/map/zone/impl/WildernessZone.java +++ b/Server/src/main/core/game/world/map/zone/impl/WildernessZone.java @@ -233,6 +233,10 @@ public final class WildernessZone extends MapZone { if (p.getDetails().getRights() == Rights.ADMINISTRATOR) { return true; } + // Snowscape: one of the checks needed to allow Ancient spells to work deeper in the wilderness. + if (type == 0 && p.getSpellBookManager().getSpellBook() == 193 && checkTeleport(p, 48)) { + return true; + } if (!checkTeleport(p, (node != null && node instanceof Item && (((Item) node).getName().contains("glory") || ((Item) node).getName().contains("slaying")) ? 30 : 20))) { return false; } From cd8cce30a0512521fa3be558b804f1cfe021be43 Mon Sep 17 00:00:00 2001 From: randy Date: Sat, 16 Aug 2025 20:06:07 -0600 Subject: [PATCH 297/306] Fixed Plain Satchel not looting noted items --- .../src/main/core/game/node/entity/npc/drop/NPCDropTables.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 4f55c9bd1..5b3567364 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -275,7 +275,7 @@ public final class NPCDropTables { private boolean handleSatchel(Player player, Item item) { for (int satchelId = 10877; satchelId <= 10882; satchelId++) { if (inEquipmentOrInventory(player,satchelId,1) && SnowscapeSatchelListener.Companion.isAllowed(player,satchelId,unnote(item).getId())){ - if (satchelId == 10877 && !player.plainSatchel.contains(item.getId(),1)) { + if (satchelId == 10877 && !player.plainSatchel.contains(unnote(item).getId(),1)) { continue; } if (SnowscapeSatchelListener.Companion.getSatchel(player, satchelId).add(unnote(item))) { From 2ecdde1011bea3c7babe4e1509cd32747c6e184b Mon Sep 17 00:00:00 2001 From: randy Date: Sun, 17 Aug 2025 09:21:30 -0600 Subject: [PATCH 298/306] The Fairy Ring interface now shows all destinations, not just the ones you have visited before. --- .../main/content/global/handlers/iface/FairyRingInterface.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt index 69bba13d7..69ad63e21 100644 --- a/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt +++ b/Server/src/main/content/global/handlers/iface/FairyRingInterface.kt @@ -77,9 +77,11 @@ class FairyRingInterface : InterfaceListener { private fun drawLog (player: Player) { for (i in FairyRing.values().indices) { + /* Snowscape: show all fairy ring destinations, whether they have been there or not. if (!player.savedData.globalData.hasTravelLog(i)) { continue } + */ val ring = FairyRing.values()[i] if (ring.childId == -1) { continue From e046f46ed2595ddff511314d159ef6a129308c29 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 18 Aug 2025 08:29:34 -0600 Subject: [PATCH 299/306] Slower melee weapons now do a minimum damage on successful hits to compensate for the lower dps. The minimum damage is 10% of the max hit for each tick below scimitar speeds (rounded down). This leads to a maximum dps increase of 10% for 5 tick weapons, 22% for 6 tick, and 40% for 7 tick. Usually less though, due to the rounding. Also added the formula to the ::calcmaxhit command so players can see the minimum hit in game. --- .../core/game/node/entity/combat/MeleeSwingHandler.kt | 9 ++++++++- .../core/game/system/command/sets/MiscCommandSet.kt | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt index 90c30e728..c70d760f9 100644 --- a/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/MeleeSwingHandler.kt @@ -73,7 +73,14 @@ open class MeleeSwingHandler (vararg flags: SwingHandlerFlag) if (entity is NPC && state.armourEffect == ArmourSet.VERAC && victim.hasProtectionPrayer(CombatStyle.MELEE)) max = max * 2 / 3 } state.maximumHit = max - hit = RandomFunction.random(max + 1) + + // Snowscape: Give slower weapons a minimum damage on hit to compensate for their lower DPS + // While the exact math varies due to enemy defence, this brings the average time to kill for slow weapons closer to the scimitar + // This formula is copied to MiscCommandSet.kt for the ::calcmaxhit command. + var speedMod = (entity.getProperties().getAttackSpeed() - 4) + var min = floor(speedMod * 0.1 * max).toInt() + + hit = RandomFunction.random(min, max + 1) } state.estimatedHit = hit if(victim != null) { diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index b959495bd..f62d8e87b 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -35,6 +35,9 @@ import java.awt.HeadlessException import java.awt.Toolkit import java.awt.datatransfer.StringSelection +import core.game.node.entity.combat.CombatStyle +import kotlin.math.floor + @Initializable class MiscCommandSet : CommandSet(Privilege.ADMIN){ override fun defineCommands() { @@ -126,6 +129,13 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ val swingHandler = player.getSwingHandler(false) val hit = swingHandler.calculateHit(player, player, 1.0) notify(player, "max hit: ${hit} (${(swingHandler as Object).getClass().getName()})") + + // Snowescape: calculate the min damage on hit for melee attacks (see MeleeSwingHandler.swing() for the custom minimum damage). + if (swingHandler.type == CombatStyle.MELEE) { + val speedMod = (player.getProperties().getAttackSpeed() - 4) + val min = floor(speedMod * 0.1 * hit).toInt() + notify(player, "min hit: ${min} (on successful hits)") + } } /** From 5a896cecb4a0c6e0c1ee0b40ac53db1a6ffc6e93 Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 18 Aug 2025 14:26:19 -0600 Subject: [PATCH 300/306] Alchemy Improvements Experimental note spell that replaced low level alchemy was removed. Now, Low level alchemy casts faster and alchemizes 10 items per cast, making it a viable alternative to alchemize cheap items in bulk. Both alchemy spells continuous cast time was reduced from 90 to 60 seconds, but can be refreshed at any time by manually casting again. Explorer's ring was improved. It no longer has a dialogue prompt and also alchemizes 10 items per cast, same as the spell version. --- .../handlers/item/ExplorersRingPlugin.kt | 8 +- .../skill/magic/modern/ModernListeners.kt | 84 +++++-------------- 2 files changed, 27 insertions(+), 65 deletions(-) diff --git a/Server/src/main/content/global/handlers/item/ExplorersRingPlugin.kt b/Server/src/main/content/global/handlers/item/ExplorersRingPlugin.kt index 586967573..79208d80f 100644 --- a/Server/src/main/content/global/handlers/item/ExplorersRingPlugin.kt +++ b/Server/src/main/content/global/handlers/item/ExplorersRingPlugin.kt @@ -53,9 +53,9 @@ class ExplorersRingPlugin : InteractionListener { sendMessage(player, "You have used up all of your charges for the day.") return@on true } - sendDialogue(player, "Choose the item that you wish to convert to coins.") - addDialogueAction (player) {_,_ -> - sendItemSelect (player, "Choose") { slot, optionIndex -> + //sendDialogue(player, "Choose the item that you wish to convert to coins.") + //addDialogueAction (player) {_,_ -> + sendItemSelect (player, "Cast Low Level Alchemy on:") { slot, optionIndex -> val item = player.inventory[slot] if (item == null) return@sendItemSelect @@ -63,7 +63,7 @@ class ExplorersRingPlugin : InteractionListener { return@sendItemSelect getStoreFile()[player.username.lowercase() + ":alchs"] = remaining - 1 } - } + //} return@on true } diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 6b96e386a..8c0eb276f 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -110,7 +110,7 @@ class ModernListeners : SpellListener("modern"){ onCast(Modern.LOW_ALCHEMY, ITEM){ player, node -> val item = node?.asItem() ?: return@onCast requires(player,21, arrayOf(Item(Items.FIRE_RUNE_554,3),Item(Items.NATURE_RUNE_561))) - notespell(player,item) + alchemize(player,item,high = false) } onCast(Modern.HIGH_ALCHEMY, ITEM){ player, node -> @@ -224,51 +224,7 @@ class ModernListeners : SpellListener("modern"){ setDelay(player,false) } - //Snowscape custom: Low Alch spell replaced with Note spell. This spell converts up to 10 items to notes. - public fun notespell(player: Player, item: Item) : Boolean { - if (item.definition.isUnnoted) { - if (item.definition.noteId < 0) { - player.sendMessage("This item cannot be noted.") - return false - } - val amount = kotlin.math.min(player.inventory.getAmount(item.id), 10) - player.inventory.remove(Item(item.id, amount)) - player.inventory.add(note(Item(item.id, amount))) - //player.sendMessage("The Bank of Gielinor appreciates your business.") - } else { - player.sendMessage("This item is already noted!") - return false - /* Unnoting is too strong, allowing runecrafting to happen at breakneck speeds and allowing infinite food to be brought along. Leaving the code here in case we want to enable it again someday. - val startingamount = player.inventory.getAmount(item.id) - val freespace = player.inventory.freeSlots() - var amount = minOf(startingamount, freespace) - if (startingamount - amount == 1) amount++ - if (amount == 0) { - player.sendMessage("You do not have enough inventory space to unnote this item.") - return false - } - player.inventory.remove(Item(item.id, amount)) - player.inventory.add(unnote(Item(item.id, amount))) - */ - } - - - val weapon = player.equipment.getItem(getItemFromEquipment(player, EquipmentSlot.WEAPON)) - if (weapon != null && !weapon.equals(MagicStaff.FIRE_RUNE)) { - player.animate(Animation(9625)) - player.graphics(Graphics(1692)) - } else { - player.animate(Animation(712)) - player.graphics(Graphics(112)) - } - playAudio(player,Sounds.LOW_ALCHEMY_98) - - removeRunes(player) - addXP(player, 31.0) - showMagicTab(player) - //setDelay(player, 5) - return true - } + // Snowscape: Alchemy spells have been modified. Spells now repeat, and low alchemy converts up to 100 items at a time for bulk pricing. fun alchemize(player: Player, item: Item, high: Boolean, explorersRing: Boolean = false): Boolean { if(item.name == "Coins") player.sendMessage("You can't alchemize something that's already gold!").also { return false } if((!item.definition.isTradeable) && (!item.definition.isAlchemizable)) player.sendMessage("You can't cast this spell on something like that.").also { return false } @@ -290,7 +246,7 @@ class ModernListeners : SpellListener("modern"){ if(high && ringOfWealth.contains(item.id)){ if (getAttribute(player, "ringofwealth:unlocked", false)) { player.sendMessage("You have already unlocked the permanent Wealth effect and can no longer ") - player.sendMessage("alchemize this ring.") + player.sendMessage("high alchemize this ring.") return false } else { player.setAttribute("/save:ringofwealth:unlocked", true) @@ -305,13 +261,15 @@ class ModernListeners : SpellListener("modern"){ player.pulseManager.clear() } - player.pulseManager.run(object : Pulse(){ + player.setAttribute("alchemyspelltime", getWorldTicks() + 100) + + player.pulseManager.run(object : Pulse(){ var counter = 0 override fun pulse(): Boolean { - if (amountInInventory(player, item.id) == 0 || counter >= 150) + if (amountInInventory(player, item.id) == 0 || getAttribute(player, "alchemyspelltime", 0) <= getWorldTicks()) return true - removeAttribute(player, "spell:runes") - if (counter % 5 == 0) { + + if (counter % (if (high) 5 else 2) == 0) { if (explorersRing) { visualize(player, LOW_ALCH_ANIM, EXPLORERS_RING_GFX) } else { @@ -324,19 +282,23 @@ class ModernListeners : SpellListener("modern"){ } playAudio(player, if (high) Sounds.HIGH_ALCHEMY_97 else Sounds.LOW_ALCHEMY_98) player.dispatch(ItemAlchemizationEvent(item.id, high)) - if (high) - requires(player,55, arrayOf(Item(Items.FIRE_RUNE_554,5),Item(Items.NATURE_RUNE_561,1))) - else - requires(player,21, arrayOf(Item(Items.FIRE_RUNE_554,3),Item(Items.NATURE_RUNE_561))) - removeRunes(player, false) - addXP(player, if (high) 65.0 else 31.0) - if (player.inventory.remove(Item(item.id, 1)) && coins.amount > 0) { - player.inventory.add(coins) + if (!explorersRing) { + removeAttribute(player, "spell:runes") + if (high) + requires(player,55, arrayOf(Item(Items.FIRE_RUNE_554,5),Item(Items.NATURE_RUNE_561,1))) + else + requires(player,21, arrayOf(Item(Items.FIRE_RUNE_554,3),Item(Items.NATURE_RUNE_561))) + removeRunes(player, false) + addXP(player, if (high) 65.0 else 31.0) + } + val amount = if (high) 1 else kotlin.math.min(10, amountInInventory(player, item.id)) + if (player.inventory.remove(Item(item.id, amount)) && coins.amount > 0) { + player.inventory.add(Item(coins.id, coins.amount * amount)) } //showMagicTab(player) - setDelay(player, 5) + //setDelay(player, 2) } - if (loop) { + if (loop && !explorersRing) { counter++ return false } else { From 59c55708a6a13fc21a1cac3e03e05ada4cbd266b Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 19 Aug 2025 11:53:24 -0600 Subject: [PATCH 301/306] Improvements to autolooting blacklist. Since player names are shorter than many item names, items will now be prevented from being looted if the beginning of the name is in the block list. The blocklist now also prevents satchels and the ring of wealth from looting items, not just familiars as it did previously. --- .../node/entity/npc/drop/NPCDropTables.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index 5b3567364..dc3b2aacd 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -105,12 +105,15 @@ public final class NPCDropTables { if (handleBoneCrusher(player, item)) { return; } - if (handleSatchel(player, item)) { - return; - } - if (handleCurrency(player, item)) { - return; - } + boolean blocked = isBlockedItem(player, item); + if (!blocked) { + if (handleSatchel(player, item)) { + return; + } + if (handleCurrency(player, item)) { + return; + } + } if (item.hasItemPlugin() && player != null) { if (!item.getPlugin().createDrop(item, player, npc, l)) { return; @@ -118,7 +121,7 @@ public final class NPCDropTables { item = item.getPlugin().getItem(item, npc); } if (!item.getDefinition().isStackable() && item.getAmount() > 1) { - if (hasValidFamiliar(player)) { + if (!blocked && hasValidFamiliar(player)) { for (int i = 0; i < item.getAmount(); i++) { if (!addItemFamiliar(player, new Item(item.getId()))) { GroundItemManager.create(new Item(item.getId()), l, player); @@ -142,7 +145,7 @@ public final class NPCDropTables { } } else { Player looter = getLooter(player, npc, item); - if (hasValidFamiliar(looter) && addItemFamiliar(looter, item)) { + if (!blocked && hasValidFamiliar(looter) && addItemFamiliar(looter, item)) { return; } GroundItem groundItem = GroundItemManager.create(item, l, looter); @@ -158,7 +161,7 @@ public final class NPCDropTables { } } - /** Snowlab custom looting + /** Snowscape: custom looting * Check if the player has a valid familiar that can loot. * @param player The player * @return true if they have a valid familiar. @@ -170,15 +173,12 @@ public final class NPCDropTables { return false; } } - /** Snowlab custom looting + /** Snowscape: custom looting * Attempt adding item to familiar inventory. * @param player The player * @return true if item was successfully added. */ private boolean addItemFamiliar(Player player, Item item) { - if (player.getCommunication().getBlocked().contains(item.getName().toLowerCase().replace(" ","_"))) { - return false; - } if ((player.getFamiliarManager().getFamiliar() instanceof PackYakNPC) && ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().contains(12435, 1) && player.getBank().add(item)) { ((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().remove(new Item(12435, 1)); player.sendMessage("Your familiar picked up and banked " + item.getAmount() + " " + item.getName() + "."); @@ -305,6 +305,18 @@ public final class NPCDropTables { } return false; } + + //Snowscape: check if the item is in the player's ignore list + private boolean isBlockedItem(Player player, Item item) { + // Format the item name to match the block list formatting. Then check if the item name starts with any of the blocked names. + String formattedName = item.getName().toLowerCase().replace(" ","_"); + for (String blocked : player.getCommunication().getBlocked()) { + if (blocked.length() > 0 && formattedName.startsWith(blocked)) { + return true; + } + } + return false; + } /** * Gets the ratio for stabilizing NPC combat difficulty & drop rates. From 590e9fe44f75882eb8351ef62864d7e65542d521 Mon Sep 17 00:00:00 2001 From: randy Date: Wed, 20 Aug 2025 13:23:00 -0600 Subject: [PATCH 302/306] Telekinetic grab now grabs all matching items within 10 tiles of the target item If casting without line of sight, the player will now walk closer rather than simply being unable to cast --- .../minigame/mta/TelekineticGrabSpell.java | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java index 72728d1e6..9c3174d1f 100644 --- a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java +++ b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java @@ -25,6 +25,9 @@ import core.game.global.action.PickupHandler; import core.game.world.GameWorld; import org.rs09.consts.Sounds; +import core.game.world.map.Location; +import core.game.interaction.MovementPulse; + import static core.api.ContentAPIKt.*; /** @@ -106,9 +109,22 @@ public final class TelekineticGrabSpell extends MagicSpell { if (!canCast(entity, ground)) { return false; } + + //Snowscape: pick up all items of the target type within a square centered on the target + int radius = 10; + for (int x = target.getLocation().getX() - radius; x <= target.getLocation().getX() + radius; x++) { + for (int y = target.getLocation().getY() - radius; y <= target.getLocation().getY() + radius; y++) { + GroundItem targetItem = GroundItemManager.get(target.getId(), new Location(x,y), (Player) entity); + if (targetItem != null) { + GameWorld.getPulser().submit(getGrabPulse(entity, targetItem)); + visualize(entity, targetItem); + } + } + } + entity.lock(2); - visualize(entity, target); - GameWorld.getPulser().submit(getGrabPulse(entity, ground)); + //visualize(entity, target); + //GameWorld.getPulser().submit(getGrabPulse(entity, ground)); return true; } @@ -149,11 +165,15 @@ public final class TelekineticGrabSpell extends MagicSpell { } playAudio(player, Sounds.VULNERABILITY_IMPACT_3008); if (!teleZone) { - player.getInventory().add(new Item(g.getId(), g.getAmount(), g.getCharge())); + if (hasSpaceFor(player, g)) { + player.getInventory().add(new Item(g.getId(), g.getAmount(), g.getCharge())); + } else { + return true; + } } else { TelekineticZone zone = TelekineticZone.getZone(player); zone.moveStatue(); - player.lock(getDelay()); + //player.lock(getDelay()); } player.getPacketDispatch().sendPositionedGraphics(END_GRAPHIC, ground.getLocation()); } @@ -178,7 +198,27 @@ public final class TelekineticGrabSpell extends MagicSpell { if (entity instanceof Player) { final Player player = (Player) entity; if (!CombatSwingHandler.isProjectileClipped(player, item, false)) { - sendMessage(player, "I can't reach that."); //TODO authentic message? + //Move to the target, stopping and recasting when within line of sight. + player.getPulseManager().run(new MovementPulse(player, item) { + @Override + public boolean pulse() { + castSpell(player, SpellBook.MODERN, SPELL_ID, item); + return true; + } + + @Override + public boolean update() { + if (CombatSwingHandler.isProjectileClipped(player, item, false)) { + player.getWalkingQueue().reset(); + pulse(); + stop(); + return true; + } + return super.update(); + } + }); + + //sendMessage(player, "I can't reach that."); //TODO authentic message? return false; } if (!hasSpaceFor(player, item)) { From b372d5e963201555767740569ebd9b0a355060fe Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 25 Aug 2025 10:55:37 -0600 Subject: [PATCH 303/306] Players can now freely swap between unlocked spellbooks with the magic interface sort buttons. The "Level Order" button is the Modern spellbook, "Combat First" is Ancient, and "Teleports first" is Lunar. This makes the ability to swap spellbooks with the Mage's book obsolete, so that feature has been removed. --- .../handlers/iface/MagicBookInterface.java | 38 ++++++++ .../handlers/item/SnowscapeMagesBook.kt | 91 ------------------- 2 files changed, 38 insertions(+), 91 deletions(-) delete mode 100644 Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt diff --git a/Server/src/main/content/global/handlers/iface/MagicBookInterface.java b/Server/src/main/content/global/handlers/iface/MagicBookInterface.java index af5c87baa..6832efb43 100644 --- a/Server/src/main/content/global/handlers/iface/MagicBookInterface.java +++ b/Server/src/main/content/global/handlers/iface/MagicBookInterface.java @@ -14,6 +14,9 @@ import core.game.node.entity.player.link.SpellBookManager.SpellBook; import core.game.world.GameWorld; import core.plugin.Plugin; +import content.data.Quests; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents the magic book interface handling of non-combat spells. * @author 'Vexia @@ -42,9 +45,44 @@ public final class MagicBookInterface extends ComponentPlugin { ? SpellBook.ANCIENT : SpellBook.LUNAR; + // Snowscape: Allow switching between unlocked spellbooks with the magic interface sort buttons + if (spellBook == SpellBook.MODERN) { + if (button == 65 && swapSpellBook(player, SpellBook.ANCIENT)) { + return true; + } else if (button == 66 && swapSpellBook(player, SpellBook.LUNAR)) { + return true; + } + } else if (spellBook == SpellBook.ANCIENT) { + if (button == 29 && swapSpellBook(player, SpellBook.MODERN)) { + return true; + } else if (button == 31 && swapSpellBook(player, SpellBook.LUNAR)) { + return true; + } + } else if (spellBook == SpellBook.LUNAR) { + if (button == 40 && swapSpellBook(player, SpellBook.MODERN)) { + return true; + } else if (button == 41 && swapSpellBook(player, SpellBook.ANCIENT)) { + return true; + } + } + + SpellListeners.run(button, SpellListener.NONE, SpellUtils.getBookFromInterface(component.getId()),player,null); boolean result = MagicSpell.castSpell(player, spellBook, button, player); return result; } + + // Snowscape custom function + private boolean swapSpellBook(final Player player, SpellBook spellBook) { + if (spellBook == SpellBook.ANCIENT && !hasRequirement(player, Quests.DESERT_TREASURE)) { + return false; + } else if (spellBook == SpellBook.LUNAR && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) { + return false; + } + player.getSpellBookManager().setSpellBook(spellBook); + player.getSpellBookManager().update(player); + return true; + } } + diff --git a/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt b/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt deleted file mode 100644 index 886d0a3a0..000000000 --- a/Server/src/main/content/global/handlers/item/SnowscapeMagesBook.kt +++ /dev/null @@ -1,91 +0,0 @@ -package content.global.handlers.item - -import core.api.* -import core.game.node.Node -import core.game.node.entity.player.Player -import core.game.node.entity.player.link.SpellBookManager.SpellBook -//import core.game.node.item.Item -import core.game.interaction.InteractionListener -import core.game.interaction.IntType -import core.game.world.update.flag.context.Animation -import core.game.world.update.flag.context.Graphics -import core.game.dialogue.* -import core.tools.START_DIALOGUE -import org.rs09.consts.Items -import org.rs09.consts.Sounds -import org.rs09.consts.Scenery -import org.rs09.consts.Animations -import content.data.Quests - -//import core.game.component.Component - -/** - * Listener for the Mage's Book from Mage Training Arena. The other spellbooks can be inscribed into the book by using it on the respective altar. - * Operate the book to switch to spellbooks that have been added. - * - */ -class SnowscapeMagesBook : InteractionListener { - - - override fun defineListeners() { - on(Items.MAGES_BOOK_6889, IntType.ITEM, "operate") { player, node -> - if (player.inCombat()) { - player.sendMessage("You cannot concentrate on the book during combat.") - } else { - player.animate(Animation(6299)) - player.graphics(Graphics(1062)) - openDialogue(player, SnowscapeMagesBookDialogue()) - } - return@on true - } - - val altars = intArrayOf(Scenery.ALTAR_6552,Scenery.ALTAR_17010) - - onUseWith(IntType.SCENERY, Items.MAGES_BOOK_6889, *altars) { player, used, with -> - val ancient = (with.getId() == Scenery.ALTAR_6552) - val quest = if (ancient) Quests.DESERT_TREASURE else Quests.LUNAR_DIPLOMACY - val attribute = if (ancient) "/save:snowscape:magesbook:2" else "/save:snowscape:magesbook:3" - - if (hasRequirement(player, quest)){ - setAttribute(player, attribute, true) - sendDialogue(player, "You carefully focus on the magic in the altar, and inscribe it into the book.") - playAudio(player, Sounds.LUNAR_STAT_SPY_3620) - playAudio(player, Sounds.LUNAR_STAT_SPY_IMPACT_3621) - animate(player, Animations.LUNAR_SPELLBOOK_STATSPY_6293) - } - return@onUseWith true - } - } -} - - - - -class SnowscapeMagesBookDialogue : DialogueFile() { - - - override fun handle(componentID: Int, buttonID: Int) { - when (stage) { - START_DIALOGUE -> options("Modern","Ancient","Lunar").also {stage++} - - 1 -> { - end() - if (player == null) return - // This is ordered a little strange, but checking the quest comes first so that access to the spellbook is lost when the quest is released, until it's completed. - if (buttonID == 2 && !hasRequirement(player!!, Quests.DESERT_TREASURE)) return - if (buttonID == 3 && !hasRequirement(player!!, Quests.LUNAR_DIPLOMACY)) return - if (buttonID > 1 && !getAttribute(player!!, "snowscape:magesbook:$buttonID", false)) { - val altarDescription = if (buttonID == 2) "altar in the Pyramid" else "Astral altar" - sendDialogue(player!!, "The book does not contain the knowledge of those spells. Use the book on the $altarDescription to inscribe it.") - return - } - player!!.spellBookManager.setSpellBook(SpellBook.values()[buttonID - 1]) - player!!.spellBookManager.update(player!!) - playAudio(player!!, Sounds.PRAYER_RECHARGE_2674) - sendMessage(player!!, "You retrieve the inscribed knowledge and let it fill your mind.") - - } - - } - } -} From bfa62864faa949d1955e327ff27af922eeacd66e Mon Sep 17 00:00:00 2001 From: randy Date: Mon, 25 Aug 2025 16:00:14 -0600 Subject: [PATCH 304/306] Implemented custom ::dps command to combine the information from ::calcmaxhit and ::calcaccuracy --- .../system/command/sets/MiscCommandSet.kt | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index f62d8e87b..5e3a5a39b 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -36,6 +36,7 @@ import java.awt.Toolkit import java.awt.datatransfer.StringSelection import core.game.node.entity.combat.CombatStyle +import core.game.node.entity.combat.equipment.WeaponInterface import kotlin.math.floor @Initializable @@ -130,7 +131,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ val hit = swingHandler.calculateHit(player, player, 1.0) notify(player, "max hit: ${hit} (${(swingHandler as Object).getClass().getName()})") - // Snowescape: calculate the min damage on hit for melee attacks (see MeleeSwingHandler.swing() for the custom minimum damage). + // Snowscape: calculate the min damage on hit for melee attacks (see MeleeSwingHandler.swing() for the custom minimum damage). if (swingHandler.type == CombatStyle.MELEE) { val speedMod = (player.getProperties().getAttackSpeed() - 4) val min = floor(speedMod * 0.1 * hit).toInt() @@ -648,6 +649,53 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ notify(player, "Setting plaques read to: ${args[1]}") } + + //Snowscape custom commands + define("dps", Privilege.STANDARD, "::dps NPC ID", "Calculates and prints your current damage, accuracy, and DPS against the given NPC ID."){ player, args -> + // If NPC ID is specified, save as attribute. If unspecified, use last saved ID (defaults to Chicken) + if (args.size > 1) { + setAttribute(player, "snowscape:dpscalc", args[1].toInt()) + } + val npcId: Int = getAttribute(player, "snowscape:dpscalc", 41) + val npc = NPC(npcId) + npc.initConfig() + + val handler = player.getSwingHandler(false) + var attackSpeed = player.getProperties().getAttackSpeed() + var maxHit = handler.calculateHit(player, npc, 1.0) + var minHit = 0 + if (handler.type == CombatStyle.MELEE) { + minHit = floor((attackSpeed - 4) * 0.1 * maxHit).toInt() + } else if (handler.type == CombatStyle.RANGE) { + if (player.getProperties().getAttackStyle().getStyle() == WeaponInterface.STYLE_RAPID) { + attackSpeed-- + } + } else if (handler.type == CombatStyle.MAGIC) { + val spell = player.getProperties().getAutocastSpell() + maxHit = if (spell != null) spell.getMaximumImpact(player, npc, null) else 0 + } + val avgHit = ((maxHit + 1) * maxHit) / 2 / (maxHit - minHit + 1) + + val accuracy = handler.calculateAccuracy(player) + val defence = handler.calculateDefence(npc, player) + + val hitChance: Double = if (accuracy > defence) { + 1.0 - ((defence + 2.0) / (2.0 * (accuracy + 1.0))) + } else { + accuracy / (2.0 * (defence + 1.0)) + } + + val dps = (1/(attackSpeed * 0.6)) * hitChance * avgHit + + + val color = "00fffff" + player.sendMessage("------ DPS vs ${npc.name} ------") + player.sendMessage("Attack Style: ${handler.type}") + player.sendMessage("Attack Speed: ${attackSpeed}") + player.sendMessage("Damage: ${minHit} - ${maxHit}") + player.sendMessage("Chance to hit: ${floor(hitChance*100).toInt()}%") + player.sendMessage("Average DPS: ${floor(dps*100)/100}") + } } fun setPlaqueReadStatus(player: Player, status: Boolean){ From e9085a8270ef1a5996a900ae0428a37a0dd1d464 Mon Sep 17 00:00:00 2001 From: randy Date: Tue, 26 Aug 2025 21:15:55 -0600 Subject: [PATCH 305/306] Fixed ::dps command taking the melee attack speed of the staff instead of the autocast speed when using magic. Also shortened the command description so it fits on the ::commands list. --- .../src/main/core/game/system/command/sets/MiscCommandSet.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 5e3a5a39b..28f63e1cc 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -651,7 +651,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ } //Snowscape custom commands - define("dps", Privilege.STANDARD, "::dps NPC ID", "Calculates and prints your current damage, accuracy, and DPS against the given NPC ID."){ player, args -> + define("dps", Privilege.STANDARD, "::dps NPC ID", "Calculates current DPS against the given NPC target."){ player, args -> // If NPC ID is specified, save as attribute. If unspecified, use last saved ID (defaults to Chicken) if (args.size > 1) { setAttribute(player, "snowscape:dpscalc", args[1].toInt()) @@ -671,6 +671,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ attackSpeed-- } } else if (handler.type == CombatStyle.MAGIC) { + attackSpeed = 5 val spell = player.getProperties().getAutocastSpell() maxHit = if (spell != null) spell.getMaximumImpact(player, npc, null) else 0 } From 3cdf7767eb1fa3be7d85c32ab4f09620609b0c87 Mon Sep 17 00:00:00 2001 From: randy Date: Thu, 25 Dec 2025 21:10:40 -0700 Subject: [PATCH 306/306] Updated Crumble Undead and created Snowscape API New API will allow creating new global functions without conflicting with upstream changes. Crumble undead now works on more undead, including Barrows brothers and revenants. --- .../skill/magic/modern/CrumbleUndead.java | 4 ++- Server/src/main/core/api/SnowscapeAPI.kt | 31 +++++++++++++++++++ .../node/entity/combat/spell/SpellType.java | 8 +++-- 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Server/src/main/core/api/SnowscapeAPI.kt diff --git a/Server/src/main/content/global/skill/magic/modern/CrumbleUndead.java b/Server/src/main/content/global/skill/magic/modern/CrumbleUndead.java index ec23e258f..0c9f896b1 100644 --- a/Server/src/main/content/global/skill/magic/modern/CrumbleUndead.java +++ b/Server/src/main/content/global/skill/magic/modern/CrumbleUndead.java @@ -17,6 +17,8 @@ import core.plugin.Initializable; import core.plugin.Plugin; import org.rs09.consts.Sounds; +import static core.api.SnowscapeAPIKt.*; + /** * Handles the crumble undead spell. * @author Emperor @@ -35,7 +37,7 @@ public final class CrumbleUndead extends CombatSpell { @Override public boolean cast(Entity entity, Node target) { NPC npc = target instanceof NPC ? (NPC) target : null; - if (npc == null || npc.getTask() == null || !npc.getTask().undead) { + if (npc == null || !isUndead(npc)) { ((Player) entity).getPacketDispatch().sendMessage("This spell only affects the undead."); return false; } diff --git a/Server/src/main/core/api/SnowscapeAPI.kt b/Server/src/main/core/api/SnowscapeAPI.kt new file mode 100644 index 000000000..62f397272 --- /dev/null +++ b/Server/src/main/core/api/SnowscapeAPI.kt @@ -0,0 +1,31 @@ +package core.api + +import core.game.node.Node +import core.game.node.entity.Entity +import core.game.node.entity.npc.NPC + +/** + Separate API for Snowscape customizations to reduce impact on upstream code. + +*/ + + + +/** Checks if a given entity is classified as undead. Used for Crumble Undead. + Includes more undead than the default game, notably the Barrows Brothers. +*/ +fun isUndead (entity: Entity): Boolean { + if (entity.getId() in 2025..2030) return true // Barrows brothers + + // Includes any enemy that can be part of an undead slayer task. + val slayerTask = (entity as NPC).getTask() + if (slayerTask != null && slayerTask.undead) return true + + // Final slower check using name. Most cases should be caught by the slayer tasks, but this should guarantee the rest. + val entityName = entity.getName().lowercase() + val undeadNames = arrayOf("zombie","spirit","revenant","ghast","ghost","mummy","shade","skeleton","skogre","zogre","undead","tortured soul","spectre","ankou","banshee","crawling hand") + for (undeadName in undeadNames) { + if (entityName.contains(undeadName)) return true + } + return false +} \ No newline at end of file diff --git a/Server/src/main/core/game/node/entity/combat/spell/SpellType.java b/Server/src/main/core/game/node/entity/combat/spell/SpellType.java index d58dd2887..cd0fb91e8 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/SpellType.java +++ b/Server/src/main/core/game/node/entity/combat/spell/SpellType.java @@ -8,6 +8,7 @@ import core.game.node.entity.player.Player; import core.game.node.item.Item; import static core.api.ContentAPIKt.*; +import static core.api.SnowscapeAPIKt.*; /** * Represents the spell types. @@ -47,11 +48,12 @@ public enum SpellType { CRUMBLE_UNDEAD(1.2) { @Override public int getImpactAmount(Entity e, Entity victim, int base) { - if (((NPC) victim).getTask() != null && ((NPC) victim).getTask().undead) { + // The check in CrumbleUndead.cast() only fires when manual casting. Check again here so that no damage is dealt when autocasting. + if (isUndead(victim)) { return 12 + (e.getSkills().getLevel(Skills.MAGIC) / 10); } - ((Player) e).sendMessage("Your spell does almost no damage, as your target is not undead."); - return 1; + ((Player) e).sendMessage("This spell only affects the undead."); + return 0; } },