diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 2b39735cb..508b21b17 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -18342,7 +18342,7 @@ { "minAmount": "1", "weight": "5.0", - "id": "5733", + "id": "12070", "maxAmount": "1" }, { diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json index 727fe50bc..d0c035733 100644 --- a/Server/data/configs/ground_spawns.json +++ b/Server/data/configs/ground_spawns.json @@ -145,7 +145,7 @@ }, { "item_id": "444", - "loc_data": "{1,3231,3739,0,250}-{1,3236,3741,0,250}-{1,3195,9821,0,150}-" + "loc_data": "{1,3231,3739,0,250}-{1,3236,3741,0,250}-{1,3195,9821,0,150}-{1,2732,3224,0,250}-" }, { "item_id": "480", diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 56b44322e..106281883 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -85880,6 +85880,12 @@ "id": "8065", "name": "Pumpkin" }, + { + "id": "8077", + "name": "Pumpkin", + "examine": "What's black and white and smells of pumpkin?", + "end_height": "" + }, { "id": "8078", "name": "Maggie" @@ -85982,11 +85988,13 @@ }, { "id": "8104", - "name": "Barrel" + "name": "Barrel", + "examine": "What's black and white and smells like beer?" }, { "id": "8105", - "name": "Bush" + "name": "Bush", + "examine": "What's black and white and down to earth?" }, { "id": "8106", @@ -85994,19 +86002,23 @@ }, { "id": "8107", - "name": "Cactus" + "name": "Cactus", + "examine": "What's black and white and covered in spines?" }, { "id": "8108", - "name": "Crate" + "name": "Crate", + "examine": "What's black and white and on a sneaking mission?" }, { "id": "8109", - "name": "Rock" + "name": "Rock", + "examine": "What's black and white and looks like a rock hopper?" }, { "id": "8110", - "name": "Toadstool" + "name": "Toadstool", + "examine": "What's black and white and covered in mushroom?" }, { "id": "8111", @@ -87755,43 +87767,53 @@ }, { "id": "8502", - "name": "Cactus" + "name": "Cactus", + "examine": "Are those spines or feathers? Either way, it looks delicious." }, { "id": "8503", - "name": "Cactus" + "name": "Cactus", + "examine": "Prickly, but strangely tasty-looking..." }, { "id": "8504", - "name": "Bush" + "name": "Bush", + "examine": "It rustles deliciously." }, { "id": "8505", - "name": "Toadstool" + "name": "Toadstool", + "examine": "A horrible fungus, but there is something strangely tasty about it." }, { "id": "8506", - "name": "Barrel" + "name": "Barrel", + "examine": "The most delicious barrel you have ever seen." }, { "id": "8507", - "name": "Bush" + "name": "Bush", + "examine": "Who would have thought that leaves could smell so edible?" }, { "id": "8508", - "name": "Crate" + "name": "Crate", + "examine": "A crate. But delicious." }, { "id": "8509", - "name": "Bush" + "name": "Bush", + "examine": "You feel a strange urge to pour gravy on that bush." }, { "id": "8510", - "name": "Rock" + "name": "Rock", + "examine": "Now that's a rock I'd try to make into soup!" }, { "id": "8511", - "name": "Bush" + "name": "Bush", + "examine": "Did that bush just pour sauce on itself?" }, { "id": "8512", 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 d42743118..c3c1ab7f4 100644 --- a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt +++ b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt @@ -76,6 +76,20 @@ class MazeInterface : InteractionListener, EventHook, MapArea { WeightedItem(Items.DEFENCE_POTION2_135,1,1,1.0), ) + private val ONE_WAY_WALL = mapOf( + Location.create(2904, 4573, 0) to setOf( // Diagonal entries + Location.create(2904, 4573, 0), + Location.create(2904, 4572, 0), + Location.create(2904, 4574, 0), + ), + Location.create(2906, 4586, 0) to setOf( // Diagonal entries + Location.create(2906, 4586, 0), + Location.create(2907, 4586, 0), + ), + Location.create(2902, 4575, 0) to setOf(Location.create(2903, 4575, 0)), + Location.create(2924, 4583, 0) to setOf(Location.create(2923, 4583, 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) @@ -190,10 +204,25 @@ class MazeInterface : InteractionListener, EventHook, MapArea { 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) + on( + intArrayOf( + Scenery.WALL_3628, + Scenery.WALL_3629, + Scenery.WALL_3630, + Scenery.WALL_3631, + Scenery.WALL_3632, + ), + IntType.SCENERY, + "open" + ) { player, node -> + val scenery = node as core.game.node.scenery.Scenery + + if (ONE_WAY_WALL[scenery.location]?.contains(player.location) == true) { + sendDialogue(player, "I don't think that's the right way.") + } else { + DoorActionHandler.handleAutowalkDoor(player, scenery) + } + return@on true } diff --git a/Server/src/main/content/global/dialogue/TownCrierDialogue.java b/Server/src/main/content/global/dialogue/TownCrierDialogue.java index e740fbfa2..f330bda86 100644 --- a/Server/src/main/content/global/dialogue/TownCrierDialogue.java +++ b/Server/src/main/content/global/dialogue/TownCrierDialogue.java @@ -2,6 +2,7 @@ package content.global.dialogue; import content.global.handlers.item.book.GeneralRuleBook; import core.game.dialogue.DialoguePlugin; +import core.game.diary.DiaryLevel; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.diary.DiaryType; @@ -10,6 +11,10 @@ import core.game.world.GameWorld; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.tools.RandomFunction; +import org.rs09.consts.NPCs; + +import static content.region.misthalin.lumbridge.diary.LumbridgeAchivementDiary.Companion.BeginnerTasks.DRAYNOR_TALK_TO_TOWNCRIER_ABOUT_RULES; +import static core.api.ContentAPIKt.finishTask; /** * Represents the town crier dialogue plugin. @@ -127,9 +132,8 @@ public final class TownCrierDialogue extends DialoguePlugin { return true; } }); - // Find out about the Rules of Conduct from the Draynor

Town Crier - if (npc.getId() == 6136) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 10); + if (npc.getId() == NPCs.TOWN_CRIER_6136) { + finishTask(player, DiaryType.LUMBRIDGE, DiaryLevel.BEGINNER, DRAYNOR_TALK_TO_TOWNCRIER_ABOUT_RULES); } stage = 71; break; diff --git a/Server/src/main/content/global/handlers/iface/TanningInterface.java b/Server/src/main/content/global/handlers/iface/TanningInterface.java deleted file mode 100644 index aa15e4b11..000000000 --- a/Server/src/main/content/global/handlers/iface/TanningInterface.java +++ /dev/null @@ -1,90 +0,0 @@ -package content.global.handlers.iface; - -import static core.api.ContentAPIKt.*; -import core.game.component.Component; -import core.game.component.ComponentDefinition; -import core.game.component.ComponentPlugin; -import content.global.skill.crafting.TanningProduct; -import core.game.node.entity.player.Player; -import core.game.node.item.Item; -import core.plugin.Initializable; -import core.plugin.Plugin; -import kotlin.Unit; - -/** - * @author Vexia - * @version 1.2 - */ -@Initializable -public class TanningInterface extends ComponentPlugin { - - /** - * Method used to create a new instance. - * @param arg - * @return - * @throws Throwable - */ - @Override - public Plugin newInstance(Object arg) throws Throwable { - ComponentDefinition.put(324, this); - return this; - } - - @Override - public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { - TanningProduct def = null; - switch (button) { - case 1: - def = TanningProduct.SOFT_LEATHER; - break; - case 2: - def = TanningProduct.HARD_LEATHER; - break; - case 3: - def = TanningProduct.SNAKESKIN; - break; - case 4: - def = TanningProduct.SNAKESKIN2; - break; - case 5: - def = TanningProduct.GREEN_DHIDE; - break; - case 6: - def = TanningProduct.BLUEDHIDE; - break; - case 7: - def = TanningProduct.REDDHIDE; - break; - case 8: - def = TanningProduct.BLACKDHIDE; - break; - } - if (def == null) { - return true; - } - int amount = 0; - final TanningProduct deff = def; - switch (opcode){ - case 155: - amount = 1; - break; - case 196: - amount = 5; - break; - case 124: - amount = 10; - case 199: - sendInputDialogue(player, true, "Enter the amount:", (value) -> { - TanningProduct.tan(player, (int) value, deff); - return Unit.INSTANCE; - }); - break; - case 234: - amount = player.getInventory().getAmount(new Item(def.getItem(), 1)); - break; - } - TanningProduct.tan(player, amount, def); - return true; - } - -} diff --git a/Server/src/main/content/global/handlers/iface/TanningInterface.kt b/Server/src/main/content/global/handlers/iface/TanningInterface.kt new file mode 100644 index 000000000..278e991bf --- /dev/null +++ b/Server/src/main/content/global/handlers/iface/TanningInterface.kt @@ -0,0 +1,25 @@ +package content.global.handlers.iface + +import content.global.skill.crafting.TanningProduct +import core.api.amountInInventory +import core.api.sendInputDialogue +import core.game.interaction.InterfaceListener + +class TanningInterface : InterfaceListener { + override fun defineInterfaceListeners() { + on(324) { player, _, opcode, buttonID, _, _ -> + val product = TanningProduct.forId(buttonID) + + when (opcode) { + 155 -> TanningProduct.tan(player, 1, product) + 196 -> TanningProduct.tan(player, 5, product) + 124 -> TanningProduct.tan(player, 10, product) + 199 -> sendInputDialogue(player, true, "Enter the amount:") { value -> + TanningProduct.tan(player, value as Int, product) + } + 234 -> TanningProduct.tan(player, amountInInventory(player, product.item), product) + } + return@on true + } + } +} diff --git a/Server/src/main/content/global/handlers/iface/ThessaliaInterface.kt b/Server/src/main/content/global/handlers/iface/ThessaliaInterface.kt index 4c98f7e0b..feb6cc5c0 100644 --- a/Server/src/main/content/global/handlers/iface/ThessaliaInterface.kt +++ b/Server/src/main/content/global/handlers/iface/ThessaliaInterface.kt @@ -127,7 +127,7 @@ private const val F_FLARES = 72 private const val F_PLAIN_TROUSERS = 70 private const val F_SHORTS = 77 -private val femaleLegIDs = intArrayOf(F_FINE_SKIRT, F_FRILLED_SKIRT, F_LAYERED_SKIRT, F_LONG_NARROW_SKIRT, F_RAGGED_SKIRT, F_TATTERED_SKIRT, F_SHORT_SKIRT, F_SASHED_SKIRT, F_FITTED_SKIRT, F_TORN_TROUSERS, F_LONG_SKIRT, F_TURN_UPS, F_FLARES, F_FLARES, F_PLAIN_TROUSERS, F_SHORTS) +private val femaleLegIDs = intArrayOf(F_FINE_SKIRT, F_FRILLED_SKIRT, F_LAYERED_SKIRT, F_LONG_NARROW_SKIRT, F_RAGGED_SKIRT, F_TATTERED_SKIRT, F_SHORT_SKIRT, F_SASHED_SKIRT, F_FITTED_SKIRT, F_TORN_TROUSERS, F_LONG_SKIRT, F_TURN_UPS, F_FLARES, F_PLAIN_TROUSERS, F_SHORTS) private val COINS = Item(995,1000) diff --git a/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java b/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java index af9e253f3..b11f3845c 100644 --- a/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java +++ b/Server/src/main/content/region/asgarnia/dialogue/ThuroDialogue.java @@ -155,7 +155,7 @@ public final class ThuroDialogue extends DialoguePlugin { stage = 14; return true; } - player.getInventory().add(player.getSkills().getMasteredSkills() >= 1 ? ITEMS[1] : ITEMS[0]); + player.getInventory().add(player.getSkills().getMasteredSkills() > 1 ? ITEMS[1] : ITEMS[0]); player.getInventory().add(ITEMS[2]); interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "There you go! You're truley a master of Smithing."); stage = 16; @@ -488,7 +488,7 @@ public final class ThuroDialogue extends DialoguePlugin { stage = 14; return true; } - player.getInventory().add(player.getSkills().getMasteredSkills() >= 1 ? ITEMS[1] : ITEMS[0]); + player.getInventory().add(player.getSkills().getMasteredSkills() > 1 ? ITEMS[1] : ITEMS[0]); player.getInventory().add(ITEMS[2]); interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "There you go! You're truley a master of Smithing."); stage = 16; 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 f953d2783..399daecc7 100644 --- a/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java +++ b/Server/src/main/content/region/asgarnia/taverley/dialogue/PikkupstixDialogue.java @@ -148,7 +148,11 @@ public final class PikkupstixDialogue extends DialoguePlugin { } break; case 100: - npc("Welcome to my humble abode. How can I help", "you?"); + if (player.getSkills().getStaticLevel(Skills.SUMMONING) == 99) { + npc(FacialExpression.AMAZED, "Why, I've never seen such raw Summoning power", "before! If anyone has the right to own a Skillcape of", "Summoning, then it is you!"); + } else { + npc("Welcome to my humble abode. How can I help", "you?"); + } break; } return true; @@ -631,7 +635,7 @@ public final class PikkupstixDialogue extends DialoguePlugin { switch (stage) { case 0: if (player.getSkills().getStaticLevel(Skills.SUMMONING) == 99) { - options("So, what's Summoning all about, then?", "Can I buy some Summoning supplies?", "Can I buy a Summoning skillcape?"); + options("Yes, please sell me a Skillcape of Summoning.", "So, what's Summoning all about then?", "Can I buy some Summoning supplies?", "Please tell me about skillcapes."); stage = 600; } else { options("So, what's Summoning all about, then?", "Can I buy some Summoning supplies?", "Please tell me about skillcapes."); @@ -756,35 +760,40 @@ public final class PikkupstixDialogue extends DialoguePlugin { case 600: switch (buttonId) { case 1: + player(FacialExpression.ASKING, "May I buy a Skillcape of Summoning, please?"); + stage = 599; + break; + case 2: player("So, what's summoning all about, then?"); stage = 10; break; - case 2: + case 3: player("Can I buy some summoning supplies, please?"); stage = 34; break; - case 3: - player("Can I buy a Skillcape of Summoning?"); - stage = 599; + case 4: + player("Please tell me about skillcapes."); + stage = 400; break; } break; case 599: - npc("Why yes you can! I must warn you that they cost", "a total of 99000 coins. Do you wish to still", "buy a skillcape of Summoning?"); + npc(FacialExpression.NEUTRAL, "That is a pretty tall order, even for someone with your", "skills, " + player.getUsername() + ". You'll have to pay a fee of 99000 coins", "to get the cape."); stage = 601; break; case 601: - options("Yes.", "No."); + options("99000 coins? I think not!", "I'll take one!"); stage = 602; break; case 602: switch (buttonId) { case 1: - player("Yes, please."); - stage = 603; + player(FacialExpression.AMAZED, "99000 coins? I think not!"); + stage = 605; break; case 2: - end(); + player(FacialExpression.HAPPY, "I'll take one!"); + stage = 603; break; } break; @@ -804,13 +813,17 @@ public final class PikkupstixDialogue extends DialoguePlugin { return true; } if (player.getInventory().add(ITEMS[player.getSkills().getMasteredSkills() > 1 ? 1 : 0], ITEMS[2])) { - player("There you go, enjoy!"); + npc(FacialExpression.HAPPY, "Excellent! Wear that cape with pride my friend."); stage = 604; } break; case 604: end(); break; + case 605: + npc(FacialExpression.NEUTRAL, "Well, keep that in mind the next time you ask. These", "things are not cheap to make you know!"); + stage = 604; + break; } break; } diff --git a/Server/src/main/content/region/desert/dialogue/ShantayDialogue.java b/Server/src/main/content/region/desert/dialogue/ShantayDialogue.java index be8dde907..fcbf3077f 100644 --- a/Server/src/main/content/region/desert/dialogue/ShantayDialogue.java +++ b/Server/src/main/content/region/desert/dialogue/ShantayDialogue.java @@ -47,11 +47,11 @@ public final class ShantayDialogue extends DialoguePlugin { } if (args.length == 2) { player.getPacketDispatch().sendMessage("Shantay saunters over to talk with you."); - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "If you want to be let out, you have to pay a fine of", "five gold. Do you want to pay now?"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "If you want to be let out, you have to pay a fine of", "five gold. Do you want to pay now?"); stage = 703; return true; } - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "Hello effendi, I am Shantay."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Hello effendi, I am Shantay."); stage = 0; return true; } @@ -60,11 +60,11 @@ public final class ShantayDialogue extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "I see you're new. Please read the billboard poster", "before going into the desert. It'll give yer details on the", "dangers you can face."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "I see you're new. Please read the billboard poster", "before going into the desert. It'll give yer details on the", "dangers you can face."); stage = 1; break; case 1: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "There is a heartbroken mother just past the gates and", "in the desert. Her name is Irena and she mourns her", "lost daughter. Such a shame."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "There is a heartbroken mother just past the gates and", "in the desert. Her name is Irena and she mourns her", "lost daughter. Such a shame."); stage = 2; break; case 2: @@ -74,19 +74,19 @@ public final class ShantayDialogue extends DialoguePlugin { case 3: switch (buttonId) { case 1: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What is this place?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "What is this place?"); stage = 10; break; case 2: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Can I see what you have to sell please?"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Can I see what you have to sell please?"); stage = 20; break; case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I must be going."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "I must be going."); stage = 30; break; case 4: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I want to buy a Shantay pass for 5 gold coins."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "I want to buy a Shantay pass for 5 gold coins."); stage = 40; break; @@ -101,7 +101,7 @@ public final class ShantayDialogue extends DialoguePlugin { player.getInventory().add(new Item(1854)); interpreter.sendItemMessage(1854, "You purchase a Shantay Pass."); } else { - interpreter.sendDialogues(player, null, "Sorry, I don't seem to have enough money."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Sorry, I don't seem to have enough money."); } stage = 41; break; @@ -109,18 +109,18 @@ public final class ShantayDialogue extends DialoguePlugin { end(); break; case 30: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "So long..."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "So long..."); stage = 31; break; case 31: end(); break; case 10: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "This is the pass of Shantay. I guard this area with my", "men. I am responsible for keeping this pass open and", "repaired."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "This is the pass of Shantay. I guard this area with my", "men. I am responsible for keeping this pass open and", "repaired."); stage = 11; break; case 11: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "My men and I prevent outlaws from getting out of the", "desert. And we stop the inexeperienced from a dry death", "in the sands. Which would you say you were?"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "My men and I prevent outlaws from getting out of the", "desert. And we stop the inexeperienced from a dry death", "in the sands. Which would you say you were?"); stage = 12; break; case 12: @@ -130,21 +130,21 @@ public final class ShantayDialogue extends DialoguePlugin { case 13: switch (buttonId) { case 1: - interpreter.sendDialogues(player, null, "I am definitely an outlaw, prepare to die."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "I am definitely an outlaw, prepare to die."); stage = 700; break; case 2: - interpreter.sendDialogues(player, null, "I am a little inexperienced."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "I am a little inexperienced."); stage = 710; break; case 3: - interpreter.sendDialogues(player, null, "Er, neither, I'm an adventurer."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Er, neither, I'm an adventurer."); stage = 720; break; } break; case 20: - interpreter.sendDialogues(836, FacialExpression.HALF_GUILTY, "Absolutely Effendi!"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Absolutely Effendi!"); stage = 21; break; case 21: @@ -152,11 +152,11 @@ public final class ShantayDialogue extends DialoguePlugin { npc.openShop(player); break; case 700: - interpreter.sendDialogues(836, null, "Ha, very funny....."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Ha, very funny....."); stage = 701; break; case 701: - interpreter.sendDialogues(836, null, "Guards arrest him!"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Guards arrest him!"); stage = 702; break; case 702: @@ -168,7 +168,7 @@ public final class ShantayDialogue extends DialoguePlugin { public boolean pulse() { player.setAttribute("/save:shantay-jail", true); player.getProperties().setTeleportLocation(Location.create(3298, 3123, 0)); - interpreter.sendDialogues(836, null, "You'll have to stay in there until you pay the fine of", "five gold pieces. Do you want to pay now?"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "You'll have to stay in there until you pay the fine of", "five gold pieces. Do you want to pay now?"); stage = 703; return true; } @@ -181,11 +181,11 @@ public final class ShantayDialogue extends DialoguePlugin { case 704: switch (buttonId) { case 1: - interpreter.sendDialogues(player, null, "Yes, okay."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Yes, okay."); stage = 705; break; case 2: - interpreter.sendDialogues(player, null, "No thanks, you're not having my money."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "No thanks, you're not having my money."); stage = 800; break; } @@ -194,20 +194,20 @@ public final class ShantayDialogue extends DialoguePlugin { if (player.getInventory().remove(new Item(995, 5))) { player.getPacketDispatch().sendMessage("You hand over the five gold pieces to Shantay."); player.getPacketDispatch().sendMessage("Shantay unlocks the door to the cell."); - interpreter.sendDialogues(836, null, "Great, Effendi, now please try to keep the peace."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Great, Effendi, now please try to keep the peace."); player.removeAttribute("shantay-jail"); stage = 822; } else { - interpreter.sendDialogues(player, null, "Sorry, I don't seem to have enough money."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Sorry, I don't seem to have enough money."); stage = 825; } break; case 800: - interpreter.sendDialogues(836, null, "You have a choice. You can either pay five gold pieces", "or... You can be transported to a maximum security", "prision in Port Sarim"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "You have a choice. You can either pay five gold pieces", "or... You can be transported to a maximum security", "prison in Port Sarim"); stage = 801; break; case 801: - interpreter.sendDialogues(836, null, "Will you pay the five gold pieces?"); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Will you pay the five gold pieces?"); stage = 802; break; case 802: @@ -217,17 +217,17 @@ public final class ShantayDialogue extends DialoguePlugin { case 803: switch (buttonId) { case 1: - interpreter.sendDialogues(player, null, "Yes, okay."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Yes, okay."); stage = 820; break; case 2: - interpreter.sendDialogues(player, null, "No, do your worst!"); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "No, do your worst!"); stage = 804; break; } break; case 804: - interpreter.sendDialogues(836, null, "You are to be transported to a maximum security", "prision in Port Sarim. I hope you've learn an important", "lesson from this."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "You are to be transported to a maximum security", "prison in Port Sarim. I hope you've learnt an important", "lesson from this."); stage = 805; break; case 805: @@ -237,17 +237,17 @@ public final class ShantayDialogue extends DialoguePlugin { end(); break; case 820: - interpreter.sendDialogues(836, null, "Good, I see that you have come to your senses."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Good, I see that you have come to your senses."); stage = 821; break; case 821: if (player.getInventory().remove(new Item(995, 5))) { player.getPacketDispatch().sendMessage("You hand over the five gold pieces to Shantay."); player.getPacketDispatch().sendMessage("Shantay unlocks the door to the cell."); - interpreter.sendDialogues(836, null, "Great, Effendi, now please try to keep the peace."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Great, Effendi, now please try to keep the peace."); stage = 822; } else { - interpreter.sendDialogues(player, null, "Sorry, I don't seem to have enough money."); + interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Sorry, I don't seem to have enough money."); stage = 825; } break; @@ -258,26 +258,26 @@ public final class ShantayDialogue extends DialoguePlugin { end(); break; case 710: - interpreter.sendDialogues(836, null, "Can I recommend that you purchase a full waterskin", "and a knife! These items will no doubt save your life. A", "waterskin will keep water from evaporating in the desert."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Can I recommend that you purchase a full waterskin", "and a knife! These items will no doubt save your life. A", "waterskin will keep water from evaporating in the desert."); stage = 711; break; case 711: - interpreter.sendDialogues(836, null, "And a keen woodsman with a knife can extract juice", "from a cactus. Before you go into the desert, it's", "advisable to wear desert clothes. It's very hot in the", "desert and you'll surely cook if you wear amour."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "And a keen woodsman with a knife can extract juice", "from a cactus. Before you go into the desert, it's", "advisable to wear desert clothes. It's very hot in the", "desert and you'll surely cook if you wear amour."); stage = 712; break; case 712: end(); break; case 720: - interpreter.sendDialogues(836, null, "Great, I have just the thing for you the desert adventurer.", "I sell desert clothes which will keep you cool in the heat", "of the desert. I also sell waterskins so that you won't", "die in the desert."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "Great, I have just the thing for you the desert adventurer.", "I sell desert clothes which will keep you cool in the heat", "of the desert. I also sell waterskins so that you won't", "die in the desert."); stage = 721; break; case 721: - interpreter.sendDialogues(836, null, "A waterskin and a knife help you survive from the juice", "of a cactus. Use the chest to store your items, we'll take", "them to the bank. It's hot in the desert, you'll bake in", "all that armour."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "A waterskin and a knife help you survive from the juice", "of a cactus. Use the chest to store your items, we'll take", "them to the bank. It's hot in the desert, you'll bake in", "all that armour."); stage = 722; break; case 722: - interpreter.sendDialogues(836, null, "To keep the pass open we ask for 5 gold pieces. And", "we give you a Shantay Pass, just ask to see what I sell", "to buy one."); + interpreter.sendDialogues(836, FacialExpression.NEUTRAL, "To keep the pass open we ask for 5 gold pieces. And", "we give you a Shantay Pass, just ask to see what I sell", "to buy one."); stage = 723; break; case 723: diff --git a/Server/src/main/core/ServerConstants.kt b/Server/src/main/core/ServerConstants.kt index 2959ccb0c..4e40457f4 100644 --- a/Server/src/main/core/ServerConstants.kt +++ b/Server/src/main/core/ServerConstants.kt @@ -336,6 +336,12 @@ class ServerConstants { @JvmField var FORCE_EASTER_EVENTS = false + @JvmField + var APRIL_FOOLS_EVENT = false + + @JvmField + var FORCE_APRIL_FOOLS = false + @JvmField var RUNECRAFTING_FORMULA_REVISION = 530 diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 8dc6ed47e..99b1e924a 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -25,6 +25,7 @@ import core.game.consumable.* import core.game.container.impl.EquipmentContainer import core.game.dialogue.DialogueFile import core.game.dialogue.SkillDialogueHandler +import core.game.diary.DiaryLevel import core.game.ge.GrandExchangeRecords import core.game.interaction.* import core.game.node.Node @@ -42,6 +43,7 @@ import core.game.node.entity.player.link.HintIconManager import core.game.node.entity.player.link.IronmanMode import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.player.link.audio.Audio +import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.player.link.emote.Emotes import core.game.node.entity.player.link.prayer.PrayerType import core.game.node.entity.player.link.quest.Quest @@ -3354,4 +3356,33 @@ fun openSingleTab(player: Player, component: Int) { player.interfaceManager.openSingleTab(Component(component)) } +/** + * Finish an achievement diary task for the player. + * @param player the player who just finished the task. + * @param diary the diary the task belongs to. + * @param level the level of the task. + * @param task The task that was just finished. + */ +fun finishTask(player: Player, diary: DiaryType, level: DiaryLevel, task: Int) { + player.achievementDiaryManager.finishTask(player, diary, getDiaryLevelIndex(diary, level), task) +} + +/** + * Resolves a [DiaryLevel] to an index for a specific diary. + * @param diary The diary the task belongs to. + * @param level The task level in the diary. + * @throws IllegalArgumentException if the level is not present in the diary. + * @return the index of the level that can be used with [core.game.node.entity.player.link.diary.AchievementDiaryManager.finishTask]. + */ +fun getDiaryLevelIndex(diary: DiaryType, level: DiaryLevel): Int { + val levelName = level.name.lowercase().replaceFirstChar { c -> c.uppercase() } + val levelIndex = diary.levelNames.indexOf(levelName) + + if (levelIndex < 0) { + throw IllegalArgumentException("'$levelName' was not found in diary '$diary'.") + } + + return levelIndex +} + private class ContentAPI diff --git a/Server/src/main/core/game/diary/DiaryEventHookBase.kt b/Server/src/main/core/game/diary/DiaryEventHookBase.kt index 4fb85b0cd..692759fd9 100644 --- a/Server/src/main/core/game/diary/DiaryEventHookBase.kt +++ b/Server/src/main/core/game/diary/DiaryEventHookBase.kt @@ -180,16 +180,7 @@ abstract class DiaryEventHookBase(private val diaryType: DiaryType) : MapArea, L ) } - private fun findIndexFor(level: DiaryLevel): Int { - val levelName = level.name.lowercase().replaceFirstChar { c -> c.uppercase() } - val levelIndex = diaryType.levelNames.indexOf(levelName) - - if (levelIndex < 0) { - throw IllegalArgumentException("'$levelName' was not found in diary '$diaryType'.") - } - - return levelIndex - } + private fun findIndexFor(level: DiaryLevel): Int = getDiaryLevelIndex(diaryType, level) protected open fun onAreaVisited(player: Player) { areaTasks.forEach { 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 c545ed949..06a978589 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -1,34 +1,32 @@ package core.game.node.entity.skill; +import content.global.handlers.item.equipment.brawling_gloves.BrawlingGloves; +import content.global.handlers.item.equipment.brawling_gloves.BrawlingGlovesManager; 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; -import content.global.handlers.item.equipment.brawling_gloves.BrawlingGlovesManager; import core.game.node.entity.Entity; import core.game.node.entity.combat.ImpactHandler; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import core.game.node.entity.player.info.PlayerMonitor; import core.game.node.entity.player.link.request.assist.AssistSession; import core.game.node.item.Item; +import core.game.world.GameWorld; +import core.game.world.repository.Repository; import core.net.packet.PacketRepository; import core.net.packet.context.SkillContext; import core.net.packet.out.SkillLevel; +import core.plugin.CorePluginTypes.XPGainPlugins; import kotlin.Pair; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import core.game.node.entity.player.info.PlayerMonitor; -import core.game.world.GameWorld; -import core.game.world.repository.Repository; -import core.plugin.CorePluginTypes.XPGainPlugins; import org.rs09.consts.Items; -import org.rs09.consts.Sounds; import java.util.ArrayList; import static core.api.ContentAPIKt.getWorldTicks; -import static core.api.ContentAPIKt.playAudio; import static java.lang.Math.floor; import static java.lang.Math.max; @@ -828,7 +826,7 @@ public final class Skills { */ public int getMasteredSkills() { int count = 0; - for (int i = 0; i < 23; i++) { + for (int i = 0; i < staticLevels.length; i++) { if (getStaticLevel(i) >= 99) { count++; } 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 65ffe1369..25ef32fef 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -232,18 +232,35 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { writer.close() } - define("rolldrops", Privilege.ADMIN, "::rolldrops NPC ID AMOUNT", "Rolls the given NPC drop table AMOUNT times.") { player: Player, args: Array -> - if(args.size < 2){ - reject(player,"Usage: ::rolldrops npcid amount") + define( + "rolldrops", + Privilege.ADMIN, + "::rolldrops NPC ID AMOUNT [true|false]", + "Rolls the given NPC drop table AMOUNT times. Add true to persist the items in your bank." + ) { player: Player, args: Array -> + if (args.size < 3) { + reject(player, "Usage: ::rolldrops npcid amount [true|false]") } - val container = player.dropLog val npcId = args[1].toInt() val amount = args[2].toInt() + val container = when (args.getOrNull(3)) { + "true" -> player.bank + "false", null -> { + player.dropLog.clear() + player.dropLog + } + + else -> { + reject(player, "Usage: ::rolldrops npcid amount [true|false]") + return@define + } + + } - container.clear() val drops = NPCDefinition.forId(npcId).dropTables.table.roll(player, amount) - for(drop in drops) container.add(drop, false) + + for (drop in drops) container.add(drop, false) container.open(player) } diff --git a/Server/src/main/core/game/system/config/ServerConfigParser.kt b/Server/src/main/core/game/system/config/ServerConfigParser.kt index 273b36531..ebacf36a1 100644 --- a/Server/src/main/core/game/system/config/ServerConfigParser.kt +++ b/Server/src/main/core/game/system/config/ServerConfigParser.kt @@ -164,6 +164,8 @@ object ServerConfigParser { ServerConstants.FORCE_HALLOWEEN_EVENTS = data.getBoolean("world.force_halloween_randoms", false) ServerConstants.FORCE_CHRISTMAS_EVENTS = data.getBoolean("world.force_christmas_randoms", false) ServerConstants.FORCE_EASTER_EVENTS = data.getBoolean("world.force_easter_randoms", false) + ServerConstants.APRIL_FOOLS_EVENT = data.getBoolean("world.april_fools_event", false) + ServerConstants.FORCE_APRIL_FOOLS = data.getBoolean("world.force_april_fools", false) ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 530).toInt() ServerConstants.ENHANCED_DEEP_WILDERNESS = data.getBoolean("world.enhanced_deep_wilderness", false) ServerConstants.WILDERNESS_EXCLUSIVE_LOOT = data.getBoolean("world.wilderness_exclusive_loot", false) diff --git a/Server/src/main/core/game/worldevents/holiday/HolidayRandoms.kt b/Server/src/main/core/game/worldevents/holiday/HolidayRandoms.kt index cf63a2e6d..e1108a473 100644 --- a/Server/src/main/core/game/worldevents/holiday/HolidayRandoms.kt +++ b/Server/src/main/core/game/worldevents/holiday/HolidayRandoms.kt @@ -155,7 +155,7 @@ class HolidayRandoms() : PersistTimer(0, "holiday", isAuto = true), Commands { define("forcehrevents", Privilege.ADMIN, "::forcehrevents [eventname]", "Force enable holiday random events.") { player, args -> if (args.size == 1) { - notify(player, "Holidays: halloween, christmas") + notify(player, "Holidays: halloween, christmas, aprilfools") return@define } val event = args[1] @@ -183,6 +183,12 @@ class HolidayRandoms() : PersistTimer(0, "holiday", isAuto = true), Commands { registerTimer(p, HolidayRandoms()) } } + "aprilfools" -> { + ServerConstants.FORCE_APRIL_FOOLS = true + for (p in Repository.players) { + notify(p, colorize("%GApril Fools is now active!")) + } + } else -> reject(player, "Invalid event!") } } diff --git a/Server/src/main/core/game/worldevents/holiday/aprilfools/AprilFoolsEvent.kt b/Server/src/main/core/game/worldevents/holiday/aprilfools/AprilFoolsEvent.kt new file mode 100644 index 000000000..4a4f11a72 --- /dev/null +++ b/Server/src/main/core/game/worldevents/holiday/aprilfools/AprilFoolsEvent.kt @@ -0,0 +1,40 @@ +package core.game.worldevents.holiday.aprilfools + +import core.ServerConstants +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.emote.Emotes +import core.game.system.command.Privilege +import core.tools.colorize +import java.util.Calendar + +class AprilFoolsEvent : Commands, LoginListener { + private fun isActive(): Boolean { + if (ServerConstants.FORCE_APRIL_FOOLS) return true + if (!ServerConstants.APRIL_FOOLS_EVENT) return false + val cal = Calendar.getInstance() + return cal.get(Calendar.MONTH) == Calendar.APRIL && cal.get(Calendar.DAY_OF_MONTH) == 1 + } + + override fun login(player: Player) { + if (!isActive()) return + sendMessage(player, colorize("Use command ::wheel to spin the new prize wheel!", "00ffff")) + } + + override fun defineCommands() { + define("wheel", Privilege.STANDARD) { player, args -> + if (!isActive()) { + sendMessage(player, colorize("-->%R${args[0]}: command not found")) + return@define + } + if (getAttribute(player, "aprilfools:wheelspun", false)) { + sendMessage(player, "I'm not falling for that again.") + return@define + } + sendNews("${player.username} just tried to spin the wheel!") + sendChat(player, "I'm spinning!") + emote(player, Emotes.SPIN) + setAttribute(player, "aprilfools:wheelspun", true) + } + } +} \ No newline at end of file diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index fcb90f72b..ecf6da0bf 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -105,6 +105,9 @@ holiday_event_randoms = false #force holiday randoms (can only force one at a time) force_halloween_randoms = false force_christmas_randoms = false +#enables inauthentic april fools event +april_fools_event = false +force_april_fools = false #runecrafting formula revision (573 introduced probabilistic multiple runes, 581 extrapolated probabilistic runes past 99) runecrafting_formula_revision = 530 #enables the enhanced deep wilderness, where the area past the members' fence applies a red skull that boosts brawler/pvp drop rates