From d023b3ccea320443d96ffee119a7e5eaff7d6902 Mon Sep 17 00:00:00 2001 From: skelsoft <9147770-skelsoft@users.noreply.gitlab.com> Date: Sat, 31 Jul 2021 23:22:59 +0000 Subject: [PATCH 01/44] Add: Summoning Scroll Update --- Server/data/configs/item_configs.json | 151 ++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 8 deletions(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 166d0d42d..2fc325c31 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -111586,9 +111586,11 @@ "requirements": "{23,41}", "ge_buy_limit": "5000", "grand_exchange_price": "96", + "examine": "A scroll for a macaw familiar.", "durability": null, "name": "Herbcall scroll", "low_alchemy": "94", + "tradeable": "true", "high_alchemy": "142", "archery_ticket_price": "0", "id": "12422" @@ -111597,9 +111599,11 @@ "requirements": "{23,69}", "ge_buy_limit": "5000", "grand_exchange_price": "258", + "examine": "A scroll for a fruit bat familiar.", "durability": null, "name": "Fruitfall scroll", "low_alchemy": "146", + "tradeable": "true", "high_alchemy": "220", "archery_ticket_price": "0", "id": "12423" @@ -111608,9 +111612,11 @@ "requirements": "{23,56}", "ge_buy_limit": "5000", "grand_exchange_price": "146", + "examine": "A scroll for an ibis familiar.", "durability": null, "name": "Fish rain scroll", "low_alchemy": "125", + "tradeable": "true", "high_alchemy": "188", "archery_ticket_price": "0", "id": "12424" @@ -111618,9 +111624,11 @@ { "ge_buy_limit": "5000", "grand_exchange_price": "7", + "examine": "A scroll for a spirit wolf familiar.", "durability": null, "name": "Howl scroll", "low_alchemy": "23", + "tradeable": "true", "high_alchemy": "35", "archery_ticket_price": "0", "id": "12425" @@ -111629,9 +111637,11 @@ "requirements": "{23,47}", "ge_buy_limit": "5000", "grand_exchange_price": "97", + "examine": "A scroll for a magpie familiar.", "durability": null, "name": "Thieving fingers scroll", "low_alchemy": "104", + "tradeable": "true", "high_alchemy": "157", "archery_ticket_price": "0", "id": "12426" @@ -111640,20 +111650,24 @@ "requirements": "{23,62}", "ge_buy_limit": "5000", "grand_exchange_price": "533", + "examine": "A scroll for an abyssal lurker familiar.", "durability": null, "name": "Abyssal stealth scroll", "low_alchemy": "135", + "tradeable": "true", "high_alchemy": "203", "archery_ticket_price": "0", "id": "12427" }, { - "requirements": "{10,23}", + "requirements": "{23,10}", "ge_buy_limit": "5000", "grand_exchange_price": "237", + "examine": "A scroll for a spirit spider familiar.", "durability": null, "name": "Egg spawn scroll", "low_alchemy": "24", + "tradeable": "true", "high_alchemy": "37", "archery_ticket_price": "0", "id": "12428" @@ -111662,9 +111676,11 @@ "requirements": "{23,33}", "ge_buy_limit": "5000", "grand_exchange_price": "97", + "examine": "A scroll for a beaver familiar.", "durability": null, "name": "Multichop scroll", "low_alchemy": "88", + "tradeable": "true", "high_alchemy": "133", "archery_ticket_price": "0", "id": "12429" @@ -111673,9 +111689,11 @@ "requirements": "{23,23}", "ge_buy_limit": "5000", "grand_exchange_price": "121", + "examine": "A scroll for an albino rat familiar.", "durability": null, "name": "Cheese feast scroll", "low_alchemy": "91", + "tradeable": "true", "high_alchemy": "137", "archery_ticket_price": "0", "id": "12430" @@ -111684,20 +111702,24 @@ "requirements": "{23,40}", "ge_buy_limit": "5000", "grand_exchange_price": "39", + "examine": "A scroll for a bull ant familiar.", "durability": null, "name": "Unburden scroll", "low_alchemy": "27", + "tradeable": "true", "high_alchemy": "41", "archery_ticket_price": "0", "id": "12431" }, { - "requirements": "{19,23}", + "requirements": "{23,19}", "ge_buy_limit": "5000", "grand_exchange_price": "72", + "examine": "A scroll for a spirit scorpion familiar.", "durability": null, "name": "Venom shot scroll", "low_alchemy": "73", + "tradeable": "true", "high_alchemy": "110", "archery_ticket_price": "0", "id": "12432" @@ -111706,9 +111728,11 @@ "requirements": "{23,32}", "ge_buy_limit": "5000", "grand_exchange_price": "99", + "examine": "A scroll for a honey badger familiar.", "durability": null, "name": "Insane ferocity scroll", "low_alchemy": "100", + "tradeable": "true", "high_alchemy": "151", "archery_ticket_price": "0", "id": "12433" @@ -111717,9 +111741,11 @@ "requirements": "{23,88}", "ge_buy_limit": "5000", "grand_exchange_price": "299", + "examine": "A scroll for a unicorn stallion familiar.", "durability": null, "name": "Healing aura scroll", "low_alchemy": "156", + "tradeable": "true", "high_alchemy": "235", "archery_ticket_price": "0", "id": "12434" @@ -111728,9 +111754,11 @@ "requirements": "{23,96}", "ge_buy_limit": "5000", "grand_exchange_price": "428", + "examine": "A scroll for a pack yak familiar.", "durability": null, "name": "Winter storage scroll", "low_alchemy": "227", + "tradeable": "true", "high_alchemy": "341", "archery_ticket_price": "0", "id": "12435" @@ -111739,9 +111767,11 @@ "requirements": "{23,63}", "ge_buy_limit": "5000", "grand_exchange_price": "223", + "examine": "A scroll for a spirit cobra familiar.", "durability": null, "name": "Oph. incubation scroll", "low_alchemy": "132", + "tradeable": "true", "high_alchemy": "199", "archery_ticket_price": "0", "id": "12436" @@ -111750,9 +111780,11 @@ "requirements": "{23,92}", "ge_buy_limit": "5000", "grand_exchange_price": "419", + "examine": "A scroll for a wolpertinger familiar.", "durability": null, "name": "Magic focus scroll", "low_alchemy": "219", + "tradeable": "true", "high_alchemy": "329", "archery_ticket_price": "0", "id": "12437" @@ -111761,9 +111793,11 @@ "requirements": "{23,68}", "ge_buy_limit": "5000", "grand_exchange_price": "220", + "examine": "A scroll for a bunyip familiar.", "durability": null, "name": "Swallow whole scroll", "low_alchemy": "126", + "tradeable": "true", "high_alchemy": "190", "archery_ticket_price": "0", "id": "12438" @@ -111772,9 +111806,11 @@ "requirements": "{23,67}", "ge_buy_limit": "5000", "grand_exchange_price": "269", + "examine": "A scroll for a war tortoise familiar.", "durability": null, "name": "Testudo scroll", "low_alchemy": "17", + "tradeable": "true", "high_alchemy": "26", "archery_ticket_price": "0", "id": "12439" @@ -111783,9 +111819,11 @@ "requirements": "{23,28}", "ge_buy_limit": "5000", "grand_exchange_price": "47", + "examine": "A scroll for a compost mound familiar.", "durability": null, "name": "Generate compost scroll", "low_alchemy": "63", + "tradeable": "true", "high_alchemy": "95", "archery_ticket_price": "0", "id": "12440" @@ -111794,9 +111832,11 @@ "requirements": "{23,52}", "ge_buy_limit": "5000", "grand_exchange_price": "35", + "examine": "A scroll for a spirit terrorbird familiar.", "durability": null, "name": "Tireless run scroll", "low_alchemy": "28", + "tradeable": "true", "high_alchemy": "43", "archery_ticket_price": "0", "id": "12441" @@ -111805,9 +111845,11 @@ "requirements": "{23,80}", "ge_buy_limit": "5000", "grand_exchange_price": "174", + "examine": "A scroll for a hydra familiar.", "durability": null, "name": "Regrowth scroll", "low_alchemy": "144", + "tradeable": "true", "high_alchemy": "217", "archery_ticket_price": "0", "id": "12442" @@ -111816,9 +111858,11 @@ "requirements": "{23,34}", "ge_buy_limit": "5000", "grand_exchange_price": "1118", + "examine": "A scroll for a Pest Control familiar.", "durability": null, "name": "Call to arms scroll", "low_alchemy": "90", + "tradeable": "true", "high_alchemy": "136", "archery_ticket_price": "0", "id": "12443" @@ -111827,20 +111871,24 @@ "requirements": "{23,49}", "ge_buy_limit": "5000", "grand_exchange_price": "148", + "examine": "A scroll for a bloated leech familiar.", "durability": null, "name": "Blood drain scroll", "low_alchemy": "133", + "tradeable": "true", "high_alchemy": "200", "archery_ticket_price": "0", "id": "12444" }, { - "requirements": "{4,23}", + "requirements": "{23,4}", "ge_buy_limit": "5000", "grand_exchange_price": "7", + "examine": "A scroll for a dreadfowl familiar.", "durability": null, "name": "Dreadfowl strike scroll", "low_alchemy": "24", + "tradeable": "true", "high_alchemy": "37", "archery_ticket_price": "0", "id": "12445" @@ -111849,9 +111897,11 @@ "requirements": "{23,25}", "ge_buy_limit": "5000", "grand_exchange_price": "122", + "examine": "A scroll for a spirit kalphite familiar.", "durability": null, "name": "Sandstorm scroll", "low_alchemy": "67", + "tradeable": "true", "high_alchemy": "101", "archery_ticket_price": "0", "id": "12446" @@ -111860,9 +111910,11 @@ "requirements": "{23,31}", "ge_buy_limit": "1000", "grand_exchange_price": "98", + "examine": "A scroll for a vampire bat familiar.", "durability": null, "name": "Vampire touch scroll", "low_alchemy": "97", + "tradeable": "true", "high_alchemy": "146", "archery_ticket_price": "0", "id": "12447" @@ -111871,9 +111923,11 @@ "requirements": "{23,42}", "ge_buy_limit": "5000", "grand_exchange_price": "123", + "examine": "A scroll for an evil turnip familiar.", "durability": null, "name": "Evil flames scroll", "low_alchemy": "120", + "tradeable": "true", "high_alchemy": "181", "archery_ticket_price": "0", "id": "12448" @@ -111882,9 +111936,11 @@ "requirements": "{23,74}", "ge_buy_limit": "5000", "grand_exchange_price": "219", + "examine": "A scroll for a granite lobster familiar.", "durability": null, "name": "Crushing claw scroll", "low_alchemy": "182", + "tradeable": "true", "high_alchemy": "274", "archery_ticket_price": "0", "id": "12449" @@ -111893,8 +111949,10 @@ "requirements": "{23,75}", "ge_buy_limit": "5000", "grand_exchange_price": "221", + "examine": "A scroll for a praying mantis familiar.", "durability": null, "name": "Mantis strike scroll", + "tradeable": "true", "archery_ticket_price": "0", "id": "12450" }, @@ -111902,9 +111960,11 @@ "requirements": "{23,71}", "ge_buy_limit": "5000", "grand_exchange_price": "12", + "examine": "A scroll for an arctic bear familiar.", "durability": null, "name": "Arctic blast scroll", "low_alchemy": "30", + "tradeable": "true", "high_alchemy": "46", "archery_ticket_price": "0", "id": "12451" @@ -111913,9 +111973,11 @@ "requirements": "{23,66}", "ge_buy_limit": "5000", "grand_exchange_price": "10", + "examine": "A scroll for a barker toad familiar.", "durability": null, "name": "Toad bark scroll", "low_alchemy": "27", + "tradeable": "true", "high_alchemy": "41", "archery_ticket_price": "0", "id": "12452" @@ -111924,9 +111986,11 @@ "requirements": "{23,55}", "ge_buy_limit": "5000", "grand_exchange_price": "202", + "examine": "A scroll for a spirit jelly familiar.", "durability": null, "name": "Dissolve scroll", "low_alchemy": "167", + "tradeable": "true", "high_alchemy": "251", "archery_ticket_price": "0", "id": "12453" @@ -111935,9 +111999,11 @@ "requirements": "{23,54}", "ge_buy_limit": "5000", "grand_exchange_price": "163", + "examine": "A scroll for an abyssal parasite familiar.", "durability": null, "name": "Abyssal drain scroll", "low_alchemy": "122", + "tradeable": "true", "high_alchemy": "183", "archery_ticket_price": "0", "id": "12454" @@ -111946,9 +112012,11 @@ "requirements": "{23,58}", "ge_buy_limit": "5000", "grand_exchange_price": "198", + "examine": "A scroll for a karamthulhu overlord familiar.", "durability": null, "name": "Doomsphere scroll", "low_alchemy": "160", + "tradeable": "true", "high_alchemy": "241", "archery_ticket_price": "0", "id": "12455" @@ -111957,9 +112025,11 @@ "requirements": "{23,83}", "ge_buy_limit": "5000", "grand_exchange_price": "9", + "examine": "A scroll for a spirit dagannoth familiar.", "durability": null, "name": "Spike shot scroll", "low_alchemy": "17", + "tradeable": "true", "high_alchemy": "26", "archery_ticket_price": "0", "id": "12456" @@ -111968,9 +112038,11 @@ "requirements": "{23,78}", "ge_buy_limit": "5000", "grand_exchange_price": "146", + "examine": "A scroll for a giant ent familiar.", "durability": null, "name": "Acorn missile scroll", "low_alchemy": "140", + "tradeable": "true", "high_alchemy": "211", "archery_ticket_price": "0", "id": "12457" @@ -111979,31 +112051,37 @@ "requirements": "{23,43}", "ge_buy_limit": "5000", "grand_exchange_price": "97", + "examine": "A scroll for a cockatrice variant familiar.", "durability": null, "name": "Petrifying gaze scroll", "low_alchemy": "104", + "tradeable": "true", "high_alchemy": "157", "archery_ticket_price": "0", "id": "12458" }, { - "requirements": "{13,23}", + "requirements": "{23,13}", "ge_buy_limit": "5000", "grand_exchange_price": "10", + "examine": "A scroll for a thorny snail familiar.", "durability": null, "name": "Slime spray scroll", "low_alchemy": "184", + "tradeable": "true", "high_alchemy": "277", "archery_ticket_price": "0", "id": "12459" }, { - "requirements": "{18,23}", + "requirements": "{23,18}", "ge_buy_limit": "5000", "grand_exchange_price": "47", + "examine": "A scroll for a desert wyrm familiar.", "durability": null, "name": "Electric lash scroll", "low_alchemy": "61", + "tradeable": "true", "high_alchemy": "92", "archery_ticket_price": "0", "id": "12460" @@ -112012,9 +112090,11 @@ "requirements": "{23,36}", "ge_buy_limit": "5000", "grand_exchange_price": "135", + "examine": "A scroll for a bronze minotaur familiar.", "durability": null, "name": "Bronze bull rush scroll", "low_alchemy": "118", + "tradeable": "true", "high_alchemy": "178", "archery_ticket_price": "0", "id": "12461" @@ -112023,9 +112103,11 @@ "requirements": "{23,46}", "ge_buy_limit": "5000", "grand_exchange_price": "180", + "examine": "A scroll for an iron minotaur familiar.", "durability": null, "name": "Iron bull rush scroll", "low_alchemy": "141", + "tradeable": "true", "high_alchemy": "212", "archery_ticket_price": "0", "id": "12462" @@ -112034,9 +112116,11 @@ "requirements": "{23,56}", "ge_buy_limit": "5000", "grand_exchange_price": "182", + "examine": "A scroll for a steel minotaur familiar.", "durability": null, "name": "Steel bull rush scroll", "low_alchemy": "157", + "tradeable": "true", "high_alchemy": "236", "archery_ticket_price": "0", "id": "12463" @@ -112045,9 +112129,11 @@ "requirements": "{23,66}", "ge_buy_limit": "5000", "grand_exchange_price": "198", + "examine": "A scroll for a mithril minotaur familiar.", "durability": null, "name": "Mith bull rush scroll", "low_alchemy": "168", + "tradeable": "true", "high_alchemy": "253", "archery_ticket_price": "0", "id": "12464" @@ -112056,9 +112142,11 @@ "requirements": "{23,76}", "ge_buy_limit": "5000", "grand_exchange_price": "203", + "examine": "A scroll for an adamant minotaur familiar.", "durability": null, "name": "Addy bull rush scroll", "low_alchemy": "160", + "tradeable": "true", "high_alchemy": "241", "archery_ticket_price": "0", "id": "12465" @@ -112067,9 +112155,11 @@ "requirements": "{23,86}", "ge_buy_limit": "5000", "grand_exchange_price": "67", + "examine": "A scroll for a rune minotaur familiar.", "durability": null, "name": "Rune bull rush scroll", "low_alchemy": "17", + "tradeable": "true", "high_alchemy": "26", "archery_ticket_price": "0", "id": "12466" @@ -112078,9 +112168,11 @@ "requirements": "{23,64}", "ge_buy_limit": "5000", "grand_exchange_price": "171", + "examine": "A scroll for a stranger plant familiar.", "durability": null, "name": "Poisonous blast scroll", "low_alchemy": "144", + "tradeable": "true", "high_alchemy": "217", "archery_ticket_price": "0", "id": "12467" @@ -112089,9 +112181,11 @@ "requirements": "{23,61}", "ge_buy_limit": "5000", "grand_exchange_price": "170", + "examine": "A scroll for a smoke devil familiar.", "durability": null, "name": "Dust cloud scroll", "low_alchemy": "157", + "tradeable": "true", "high_alchemy": "236", "archery_ticket_price": "0", "id": "12468" @@ -112534,12 +112628,14 @@ "id": "12532" }, { - "requirements": "{16,23}", + "requirements": "{23,16}", "ge_buy_limit": "5000", "grand_exchange_price": "7", + "examine": "A scroll for a granite crab familiar.", "durability": null, "name": "Stony shell scroll", "low_alchemy": "23", + "tradeable": "true", "high_alchemy": "35", "archery_ticket_price": "0", "id": "12533" @@ -115386,9 +115482,11 @@ "requirements": "{23,79}", "ge_buy_limit": "5000", "grand_exchange_price": "380", + "examine": "A scroll for an elemental titan familiar.", "durability": null, "name": "Titan's con. scroll", "low_alchemy": "214", + "tradeable": "true", "high_alchemy": "322", "archery_ticket_price": "0", "id": "12824" @@ -115397,9 +115495,11 @@ "requirements": "{23,99}", "ge_buy_limit": "5000", "grand_exchange_price": "646", + "examine": "A scroll for a steel titan familiar.", "durability": null, "name": "Steel of legends scroll", "low_alchemy": "194", + "tradeable": "true", "high_alchemy": "292", "archery_ticket_price": "0", "id": "12825" @@ -115408,9 +115508,11 @@ "requirements": "{23,73}", "ge_buy_limit": "5000", "grand_exchange_price": "271", + "examine": "A scroll for an obsidian golem familiar.", "durability": null, "name": "Volcanic str. scroll", "low_alchemy": "211", + "tradeable": "true", "high_alchemy": "317", "archery_ticket_price": "0", "id": "12826" @@ -115419,9 +115521,11 @@ "requirements": "{23,93}", "ge_buy_limit": "5000", "grand_exchange_price": "310", + "examine": "A scroll for an abyssal titan familiar.", "durability": null, "name": "Essence shipment scroll", "low_alchemy": "129", + "tradeable": "true", "high_alchemy": "194", "archery_ticket_price": "0", "id": "12827" @@ -115430,9 +115534,11 @@ "requirements": "{23,95}", "ge_buy_limit": "5000", "grand_exchange_price": "389", + "examine": "A scroll for an iron titan familiar.", "durability": null, "name": "Iron within scroll", "low_alchemy": "214", + "tradeable": "true", "high_alchemy": "322", "archery_ticket_price": "0", "id": "12828" @@ -115441,9 +115547,11 @@ "requirements": "{23,46}", "ge_buy_limit": "5000", "grand_exchange_price": "146", + "examine": "A scroll for a pyrelord familiar.", "durability": null, "name": "Immense heat scroll", "low_alchemy": "127", + "tradeable": "true", "high_alchemy": "191", "archery_ticket_price": "0", "id": "12829" @@ -115452,9 +115560,11 @@ "requirements": "{23,70}", "ge_buy_limit": "5000", "grand_exchange_price": "149", + "examine": "A scroll for a ravenous locust familiar.", "durability": null, "name": "Famine scroll", "low_alchemy": "95", + "tradeable": "true", "high_alchemy": "143", "archery_ticket_price": "0", "id": "12830" @@ -115463,9 +115573,11 @@ "requirements": "{23,77}", "ge_buy_limit": "5000", "grand_exchange_price": "245", + "examine": "A scroll for a talon beast familiar.", "durability": null, "name": "Deadly claw scroll", "low_alchemy": "190", + "tradeable": "true", "high_alchemy": "286", "archery_ticket_price": "0", "id": "12831" @@ -115474,9 +115586,11 @@ "requirements": "{23,85}", "ge_buy_limit": "5000", "grand_exchange_price": "192", + "examine": "A scroll for a swamp titan familiar.", "durability": null, "name": "Swamp plague scroll", "low_alchemy": "166", + "tradeable": "true", "high_alchemy": "250", "archery_ticket_price": "0", "id": "12832" @@ -115485,8 +115599,10 @@ "requirements": "{23,89}", "ge_buy_limit": "5000", "grand_exchange_price": "294", + "examine": "A scroll for a geyser titan familiar.", "durability": null, "name": "Boil scroll", + "tradeable": "true", "archery_ticket_price": "0", "id": "12833" }, @@ -115494,9 +115610,11 @@ "requirements": "{23,29}", "ge_buy_limit": "5000", "grand_exchange_price": "103", + "examine": "A scroll for a giant chinchompa familiar.", "durability": null, "name": "Explode scroll", "low_alchemy": "238", + "tradeable": "true", "high_alchemy": "358", "archery_ticket_price": "0", "id": "12834" @@ -115505,9 +115623,11 @@ "requirements": "{23,57}", "ge_buy_limit": "5000", "grand_exchange_price": "250", + "examine": "A scroll for a spirit graahk familiar.", "durability": null, "name": "Goad scroll", "low_alchemy": "170", + "tradeable": "true", "high_alchemy": "256", "archery_ticket_price": "0", "id": "12835" @@ -115516,9 +115636,11 @@ "requirements": "{23,57}", "ge_buy_limit": "5000", "grand_exchange_price": "1428", + "examine": "A scroll for a spirit kyatt familiar.", "durability": null, "name": "Ambush scroll", "low_alchemy": "169", + "tradeable": "true", "high_alchemy": "254", "archery_ticket_price": "0", "id": "12836" @@ -115527,31 +115649,37 @@ "requirements": "{23,83}", "ge_buy_limit": "5000", "grand_exchange_price": "300", + "examine": "A scroll for a lava titan familiar.", "durability": null, "name": "Ebon thunder scroll", "low_alchemy": "211", + "tradeable": "true", "high_alchemy": "317", "archery_ticket_price": "0", "id": "12837" }, { - "requirements": "{17,23}", + "requirements": "{23,17}", "ge_buy_limit": "5000", "grand_exchange_price": "1", + "examine": "A scroll for a spirit mosquito familiar.", "durability": null, "name": "Pester scroll", "low_alchemy": "17", + "tradeable": "true", "high_alchemy": "26", "archery_ticket_price": "0", "id": "12838" }, { - "requirements": "{22,23}", + "requirements": "{23,22}", "ge_buy_limit": "5000", "grand_exchange_price": "78", + "examine": "A scroll for a spirit Tz-Kih familiar.", "durability": null, "name": "Fireball assault scroll", "low_alchemy": "80", + "tradeable": "true", "high_alchemy": "121", "archery_ticket_price": "0", "id": "12839" @@ -115560,9 +115688,11 @@ "requirements": "{23,57}", "ge_buy_limit": "5000", "grand_exchange_price": "196", + "examine": "A scroll for a spirit larupia familiar.", "durability": null, "name": "Rending scroll", "low_alchemy": "171", + "tradeable": "true", "high_alchemy": "257", "archery_ticket_price": "0", "id": "12840" @@ -115571,9 +115701,11 @@ "requirements": "{23,76}", "ge_buy_limit": "5000", "grand_exchange_price": "173", + "examine": "A scroll for a forge regent familiar.", "durability": null, "name": "Inferno scroll", "low_alchemy": "157", + "tradeable": "true", "high_alchemy": "236", "archery_ticket_price": "0", "id": "12841" @@ -138810,9 +138942,12 @@ "id": "14621" }, { + "requirements": "{23,72}", "shop_price": "498", + "examine": "A scroll for a phoenix familiar.", "durability": null, "name": "Rise from the ashes scroll", + "tradeable": "true", "archery_ticket_price": "0", "attack_speed": "4", "id": "14622", From 83369150fb1aa9fd31c7840fdeebe6864dc447b0 Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 19:42:27 -0500 Subject: [PATCH 02/44] Rename .java to .kt --- .../skill/slayer/{Equipment.java => SlayerEquipmentFlags.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Server/src/main/java/core/game/node/entity/skill/slayer/{Equipment.java => SlayerEquipmentFlags.kt} (100%) diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/Equipment.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt similarity index 100% rename from Server/src/main/java/core/game/node/entity/skill/slayer/Equipment.java rename to Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt From cc46d43db1d5d61523fccabb12229d4cb2f0ae34 Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 19:42:29 -0500 Subject: [PATCH 03/44] Slayer skillcape perk --- .../skill/slayer/AberrantSpectreNPC.java | 4 +- .../node/entity/skill/slayer/BansheeNPC.java | 2 +- .../entity/skill/slayer/CaveHorrorNPC.java | 2 +- .../entity/skill/slayer/DustDevilNPC.java | 4 +- .../node/entity/skill/slayer/GargoyleNPC.java | 3 +- .../skill/slayer/MirrorShieldHandler.java | 2 +- .../skill/slayer/SlayerEquipmentFlags.kt | 178 +++++++---------- .../entity/skill/slayer/SlayerManager.java | 7 + .../game/node/entity/skill/slayer/Tasks.java | 187 +++++++++--------- .../slayer/dungeon/LumbridgeDungeon.java | 4 +- .../skill/slayer/dungeon/SmokeDungeon.java | 4 +- .../content/global/action/EquipHandler.kt | 9 + .../item/withitem/TOTTHelmOnCape.kt | 42 ++++ .../combat/handlers/MeleeSwingHandler.kt | 23 ++- .../combat/handlers/RangeSwingHandler.kt | 3 + .../player/info/login/PlayerSaveParser.kt | 1 + .../entity/player/info/login/PlayerSaver.kt | 1 + .../skill/skillcapeperks/SkillcapePerks.kt | 10 +- 18 files changed, 268 insertions(+), 218 deletions(-) create mode 100644 Server/src/main/kotlin/rs09/game/interaction/item/withitem/TOTTHelmOnCape.kt diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/AberrantSpectreNPC.java b/Server/src/main/java/core/game/node/entity/skill/slayer/AberrantSpectreNPC.java index 7f4b25562..1e61efe34 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/AberrantSpectreNPC.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/AberrantSpectreNPC.java @@ -30,7 +30,7 @@ public final class AberrantSpectreNPC extends AbstractNPC { public void impact(final Entity entity, final Entity victim, BattleState state) { if (victim instanceof Player) { Player player = (Player) victim; - if (!Equipment.NOSE_PEG.hasEquipment(player)) { + if (!SlayerEquipmentFlags.hasNosePeg(player)) { for (int skill : SKILLS) { int drain = (int) (player.getSkills().getStaticLevel(skill) * 0.5); player.getSkills().updateLevel(skill, -drain, 0); @@ -62,7 +62,7 @@ public final class AberrantSpectreNPC extends AbstractNPC { super.checkImpact(state); if (state.getAttacker() instanceof Player) { final Player player = (Player) state.getAttacker(); - if (!Equipment.NOSE_PEG.hasEquipment(player)) { + if (!SlayerEquipmentFlags.hasNosePeg(player)) { state.neutralizeHits(); } } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/BansheeNPC.java b/Server/src/main/java/core/game/node/entity/skill/slayer/BansheeNPC.java index e561f79b4..b5ab44ff0 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/BansheeNPC.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/BansheeNPC.java @@ -105,7 +105,7 @@ public final class BansheeNPC extends AbstractNPC { * @return {@code True} if they have it. */ public static boolean hasEarMuffs(Player player) { - return Equipment.EARMUFFS.hasEquipment(player); + return SlayerEquipmentFlags.hasEarmuffs(player); } @Override diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/CaveHorrorNPC.java b/Server/src/main/java/core/game/node/entity/skill/slayer/CaveHorrorNPC.java index b8846b460..30cc07f39 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/CaveHorrorNPC.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/CaveHorrorNPC.java @@ -74,7 +74,7 @@ public final class CaveHorrorNPC extends AbstractNPC { * @return {@code true} if it is equipped. */ public static boolean hasWitchwood(Player player) { - return player.getEquipment().containsItem(Equipment.WITCHWOOD_ICON.getItem()); + return SlayerEquipmentFlags.hasWitchwoodIcon(player); } @Override diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/DustDevilNPC.java b/Server/src/main/java/core/game/node/entity/skill/slayer/DustDevilNPC.java index f604131ef..663c7a3ff 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/DustDevilNPC.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/DustDevilNPC.java @@ -32,7 +32,7 @@ public final class DustDevilNPC extends AbstractNPC { public void impact(Entity entity, Entity victim, BattleState state) { if (victim instanceof Player) { final Player player = (Player) victim; - if (!Equipment.FACEMASK.hasEquipment(player)) { + if (!SlayerEquipmentFlags.hasFaceMask(player)) { for (int i : SKILLS) { player.getSkills().updateLevel(i, -player.getSkills().getStaticLevel(i), 0); } @@ -76,7 +76,7 @@ public final class DustDevilNPC extends AbstractNPC { super.checkImpact(state); if (state.getAttacker() instanceof Player) { Player player = (Player) state.getAttacker(); - if (!Equipment.FACEMASK.hasEquipment(player)) { + if (!SlayerEquipmentFlags.hasFaceMask(player)) { state.neutralizeHits(); } } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/GargoyleNPC.java b/Server/src/main/java/core/game/node/entity/skill/slayer/GargoyleNPC.java index 06a1711ad..48ccca94a 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/GargoyleNPC.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/GargoyleNPC.java @@ -10,6 +10,7 @@ import core.game.node.entity.player.Player; import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; +import org.rs09.consts.Items; import rs09.plugin.PluginManager; /** @@ -88,7 +89,7 @@ public final class GargoyleNPC extends AbstractNPC { * Constructs a new {@code RockHammerHandler} {@code Object}. */ public RockHammerHandler() { - super(Equipment.ROCK_HAMMER.getItem().getId()); + super(Items.ROCK_HAMMER_4162); } @Override diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/MirrorShieldHandler.java b/Server/src/main/java/core/game/node/entity/skill/slayer/MirrorShieldHandler.java index 717917bf0..db7552b92 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/MirrorShieldHandler.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/MirrorShieldHandler.java @@ -60,7 +60,7 @@ public final class MirrorShieldHandler extends MeleeSwingHandler { * @return {@code True} if so. */ private static boolean hasShield(final Player player) { - return Equipment.MIRROR_SHIELD.hasEquipment(player); + return SlayerEquipmentFlags.hasMirrorShield(player); } } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt index e4fcbcff7..322d82e57 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt @@ -1,117 +1,87 @@ -package core.game.node.entity.skill.slayer; +package core.game.node.entity.skill.slayer -import core.game.node.entity.skill.Skills; -import core.game.node.entity.player.Player; -import core.game.node.item.Item; +import api.ContentAPI +import api.EquipmentSlot +import core.game.node.entity.player.Player +import org.rs09.consts.Items +import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks /** * Represents a slayer equipment. - * @author Vexia + * @author Ceikry */ -public enum Equipment { - ENCHANTED_GEM(new Item(4155, 1)), - MIRROR_SHIELD(new Item(4156, 1)) { - @Override - public boolean hasRequirement(final Player player) { - return player.getSkills().getStaticLevel(Skills.DEFENCE) >= 20; - } - }, - LEAF_BLADED_SPEAR(new Item(4158, 1)), - BROAD_ARROWS(new Item(4150, 1)), - BAG_OF_SALT(new Item(4161, 1)), - ROCK_HAMMER(new Item(4162, 1)), - FACEMASK(new Item(4164, 1), true), - EARMUFFS(new Item(4166, 1), true) { - @Override - public boolean hasRequirement(final Player player) { - return player.getSkills().getStaticLevel(Skills.DEFENCE) >= 15; - } - }, - NOSE_PEG(new Item(4168, 1), true), - SLAYERS_STAFF(new Item(4170, 1)), - SPINY_HELMET(new Item(4551, 1), true), - FISHING_EXPLOSIVE(new Item(6660, 1)), - ICE_COOLER(new Item(6696, 1)), - SLAYER_GLOVES(new Item(6708, 1)), - UNLIT_BUG_LANTERN(new Item(7051, 1)), - INSULATED_BOOTS(new Item(7159, 1)), - FUNGICIDE_SPRAY_10(new Item(7421, 1)), - FUNGICIDE(new Item(7432, 1)), - LUMBER_PATCH(new Item(8932, 1)), - SLAYER_BELL(new Item(10952, 1)), - WITCHWOOD_ICON(new Item(8923, 1)), - LIT_BUG_LANTERN(new Item(7053, 1)), +object SlayerEquipmentFlags { - //null equipment for when none is needed - NONE(new Item(0)); + val blackMasks = (Items.BLACK_MASK_10_8901..Items.BLACK_MASK_8921).map { it }.toIntArray() + val slayerItems = intArrayOf(Items.NOSE_PEG_4168, Items.EARMUFFS_4166, Items.FACE_MASK_4164, *blackMasks, Items.SPINY_HELMET_4551, Items.SLAYER_CAPET_9787, Items.SLAYER_CAPE_9786, Items.SLAYER_HELMET_13263, Items.WITCHWOOD_ICON_8923, Items.MIRROR_SHIELD_4156) - /** - * The slayer helmet item. - */ - private static final Item SLAYER_HELM = new Item(13263); + @JvmStatic + fun updateFlags(player: Player){ + var flags = 0 + if(SkillcapePerks.isActive(SkillcapePerks.TRICKS_OF_THE_TRADE,player) && ContentAPI.getAttribute(player, "cape_perks:tott:helmet-stored", false)) flags = 0x2F + else if(hasItem(player, Items.SLAYER_HELMET_13263)) flags = 0x1F + else if(hasItem(player, Items.NOSE_PEG_4168)) flags = 1 + else if(hasItem(player, Items.EARMUFFS_4166)) flags = flags or (1 shl 1) + else if(hasItem(player, Items.FACE_MASK_4164)) flags = flags or (1 shl 2) + else if((ContentAPI.getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) in blackMasks) flags = flags or (1 shl 3) + else if(hasItem(player, Items.SPINY_HELMET_4551)) flags = flags or (1 shl 4) - /** - * Represents the item. - */ - private final Item item; - - /** - * IF the slayer helm has this equipment. - */ - private final boolean slayerHelm; + if((ContentAPI.getItemFromEquipment(player, EquipmentSlot.AMULET)?.id ?: 0) == Items.WITCHWOOD_ICON_8923) flags = flags or (1 shl 7) + if((ContentAPI.getItemFromEquipment(player, EquipmentSlot.SHIELD)?.id ?: 0) == Items.MIRROR_SHIELD_4156) flags = flags or (1 shl 8) + player.slayer.equipmentFlags = flags + } - /** - * Constructs a new {@Code Equipment} {@Code Object} - * @param item The item. - * @param slayerHelm If slayer helm incorporated. - */ - Equipment(Item item, boolean slayerHelm) { - this.item = item; - this.slayerHelm = slayerHelm; - } - - /** - * Constructs a new {@Code Equipment} {@Code Object} - * @param item The item. - */ - Equipment(Item item) { - this(item, false); - } + @JvmStatic + fun hasNosePeg(player: Player): Boolean{ + return player.slayer.equipmentFlags and 1 == 1 + } - /** - * Checks if the player has the requirement for the item. - * @param player the player. - * @return {@code True} if so. - */ - public boolean hasRequirement(final Player player) { - return item.getDefinition().hasRequirement(player, false, false); - } + @JvmStatic + fun hasEarmuffs(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 1) and 1 == 1 + } - /** - * Checks if the player has the equipment equipped. - * @param player the player. - * @return {@code True} if so. - */ - public boolean hasEquipment(final Player player) { - if (slayerHelm && player.getEquipment().containsItem(SLAYER_HELM)) { - return true; - } - return player.getEquipment().containsItem(item); - } + @JvmStatic + fun hasFaceMask(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 2) and 1 == 1 + } - /** - * Gets the item. - * @return The item. - */ - public Item getItem() { - return item; - } + @JvmStatic + fun hasBlackMask(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 3) and 1 == 1 + } - /** - * Gets the slayerHelm. - * @return the slayerHelm. - */ - public boolean isSlayerHelm() { - return slayerHelm; - } -} + @JvmStatic + fun hasSpinyHelmet(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 4) and 1 == 1 + } + + @JvmStatic + fun hasWitchwoodIcon(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 7) and 1 == 1 + } + + @JvmStatic + fun hasMirrorShield(player: Player): Boolean { + return (player.slayer.equipmentFlags shr 8) and 1 == 1 + } + + @JvmStatic + fun getDamAccBonus(player: Player): Double { + val isCape = player.slayer.equipmentFlags == 0x2F + val hasMask = hasBlackMask(player) + + return if(isCape) 1.075 + else if(hasMask) 1.15 + else 1.0 + } + + private fun hasItem(player: Player, id: Int): Boolean{ + return (ContentAPI.getItemFromEquipment(player, EquipmentSlot.HAT)?.id ?: 0) == id + } + + fun isSlayerEq(item: Int): Boolean{ + return item in slayerItems + } + +} \ No newline at end of file diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java index 9fb1b24d0..bb9f0ad47 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java @@ -65,6 +65,11 @@ public final class SlayerManager { */ private final List removed = new ArrayList<>(4); + /** + * The equipment flags for the given player + */ + public int equipmentFlags = 0; + /** * Constructs a new {@Code SlayerManager} {@Code Object} * @param player The player. @@ -102,6 +107,8 @@ public final class SlayerManager { } taskTotal = Integer.parseInt( slayerData.get("totalTasks").toString()); canEarnPoints = (boolean) slayerData.get("canEarnPoints"); + if(slayerData.containsKey("equipmentFlags")) + equipmentFlags = Integer.parseInt(slayerData.get("equipmentFlags").toString()); } /** diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/Tasks.java b/Server/src/main/java/core/game/node/entity/skill/slayer/Tasks.java index ff99c093a..37c3416cc 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/Tasks.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/Tasks.java @@ -11,96 +11,96 @@ import java.util.HashMap; * @author ceik */ public enum Tasks { - ABERRANT_SPECTRES(65, new int[] { 1604, 1605, 1606, 1607 }, new String[] { "Aberrant spectres have an extremely potent stench that drains", "stats and life points. A nose peg, protects against the stench." }, 60, true, Equipment.NOSE_PEG), - 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, Equipment.NONE), - ANKOU(40, new int[] { 4381, 4382, 4383 }, new String[] { "Neither skeleton nor ghost, but a combination of both." }, 1, true, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.EARMUFFS), - BASILISKS(40, new int[] { 1616, 1617, 4228 }, new String[] { "A mirror shield is much neccesary when hunting these", "mad creatures." }, 40, false, Equipment.NONE), - 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, Equipment.NONE), - BEARS(13, new int[] { 106, 105, 1195, 3645, 3664, 1326, 1327 }, new String[] { "A large animal with a crunching punch." }, 1, false, Equipment.NONE), - 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, }, new String[] { "irds aren't the most intelligent of creatures, but watch out for their", "sharp, stabbing beaks." }, 1, false, Equipment.NONE), - BLACK_DEMONS(80, new int[] { 84, 677, 4702, 4703, 4704, 4705 }, new String[] { "Black Demons are magic creatures that are weak to magic attacks.", "They're the strongest demon and very dangerous." }, 1, false, Equipment.NONE), - BLACK_DRAGONS(80, new int[] {54, 4673, 4674, 4675, 4676, 3376, 50 }, new String[] { "Black dragons are the strongest dragons", "watch out for their firey breath" }, 1, false, 40 | 80 << 16, Equipment.NONE), - 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, Equipment.NONE), - 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 firey breath." }, 1, false, Equipment.NONE), - BRINE_RATS(45, new int[] { 3707 }, new String[] { "Small little creatures they are, yet so very", "powerfull." }, 47, false, Equipment.NONE), - 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 firey breath." }, 1, false, 30 | 60 << 16, Equipment.NONE), - 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, Equipment.NONE), - CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "It regenerates life points quickly and seems to be a good", "herblore monster." }, 7, false, Equipment.NONE), - CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "The poisonous parts of them are presumably removed." }, 10, false, Equipment.NONE), - CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "prefered to wear a witchwood icon." }, 58, false, Equipment.NONE), - CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "These are lesser versions of jellies, watch out they can poison you." }, 17, false, Equipment.NONE), - COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "A Mirror shield is necessary when fighting these monsters." }, 25, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles can be found near water and marshes in and near the Kharidian Desert." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - DARK_BEASTS(90, new int[] { 2783 }, new String[] { "A dark beast can attack using magic or melee." }, 90, false, Equipment.NONE), - 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, Equipment.NONE), - DOG(15, new int[] { 98, 99, 3582, 6374, 1994, 1593, 1594, 3582, 6374 }, new String[] { "Dogs are much like Wolves, they are pack creatures which will hunt in groups." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "An Earth warrior is a monster made of earth which fights using melee." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.ROCK_HAMMER), - 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, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks can be tough monsters to fight. Be prepared." }, 1, false, Equipment.NONE), - GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6208, 6206, 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, Equipment.NONE), - GREEN_DRAGON(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362 }, new String[] { "Green dragons are very powerfull, they have fierce", "fiery breath." }, 1, false, Equipment.NONE), - HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are insectoid Slayer monsters." }, 33, false, Equipment.NONE), - HELLHOUNDS(75, new int[] { 49, 3586, 6210, }, new String[] { "Hellhounds are mid to high level demons." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - ICE_WARRIOR(45, new int[] { 125, 145, 3073 }, new String[] { "Ice warriors, are cold magestic creatures." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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 firey breath." }, 1, false, 40 | 59 << 16, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161 }, new String[] { "Kalaphite are large insects which live in great hives under the desert sands." }, 1, false, Equipment.NONE), - KURASKS(65, new int[] { 1608, 1609, 4229 }, new String[] { "A kurask is a very quick creature." }, 70, false, Equipment.NONE), - LESSER_DEMONS(60, new int[] { 6203, 82, 3064, 4694, 4695, 6208, 6204, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to magical attacks." }, 1, false, Equipment.NONE), - MITHRIL_DRAGON(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 firey breath." }, 1, false, 5 | 9 << 16, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "They are known to carry large sticks." }, 1, false, Equipment.NONE), - NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small winged beings which", "help them fight their victems." }, 80, false, Equipment.NONE), - OGRES(40, new int[] { 114, 115, 374, 3587, 6267 }, new String[] { "Ogres are brutal creatures, favouring large blunt maces and clubs", "they often attack without warning." }, 1, false, Equipment.NONE), - OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "A creature filled with everlasting power." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "A rock slug can leave behind a trail of his presence.." }, 20, false, Equipment.NONE), - SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "A scorpion makes a piercing sound, watch out for it's", " long sharp tail." }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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 }, new String[] { "Skeletons are undead monsters found in various locations." }, 1, true, Equipment.NONE), - 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, Equipment.NONE), - SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "They are dangerous, they hit with mage." }, 83, false, Equipment.NONE), - SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "They are dangerous, they hit with range." }, 63, false, Equipment.NONE), - SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "They are dangerous, they hit with melee." }, 68, false, Equipment.NONE), - 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 firey breath." }, 1, false, 10 | 20 << 16, Equipment.NONE), - TROLLS(60, new int[] { 72, 3584, 1098, 1096, 1097, 1095, 1101, 1105, 1102, 1103, 1104, 1130, 1131, 1132, 1133, 1134, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1138, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 3840, 3841, 3842, 3843, 3845, 1933, 1934, }, new String[] { "Trolls have a crushing attack, it's bets to wear a high crushing defence." }, 1, false, Equipment.NONE), - TUROTHS(60, new int[] { 1626, 1627, 1628, 1629, 1630 }, new String[] { "Turoths are Slayer monsters that require a Slayer level of 55 to kill" }, 55, false, Equipment.NONE), - 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, Equipment.NONE), - VAMPIRES(35, new int[] { 1023, 1220, 1223, 1225, 6214 }, new String[] { "Vampies arr equiped with large fangs", "they can do serious damage." }, 1, false, Equipment.NONE), - WATERFIENDS(75, new int[] { 5361 }, new String[] { "A waterfiend takes no damage from fire!" }, 1, false, Equipment.NONE), - 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, Equipment.NONE), - 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, Equipment.NONE), - ZOMBIES(10, new int[] { 73, 74, 75, 76, 2058, 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, }, new String[] { "Zombies are creatures with no brain, they do hit farley", "high though." }, 1, true, Equipment.NONE), - JAD(90, new int[] { }, new String[] { "TzTok-Jad is the king of the Fight Caves." }, 1, false, 1 | 1 << 16, Equipment.NONE), - CHAOS_ELEMENTAL(90, new int[] { 3200 }, new String[] { "The Chaos Elemental is located in the deep Wilderness." }, 1, false, 5 | 25 << 16, Equipment.NONE), - GIANT_MOLE(75, new int[] { 3340 }, new String[] { "Fighting the Giant Mole will require a light source." }, 1, false, 5 | 25 << 16, Equipment.NONE), - KING_BLACK_DRAGON(75, new int[] { 50 }, new String[] { "The King Black Dragon is located in the deep wilderness." }, 1, false, 5 | 25 << 16, Equipment.NONE), - COMMANDER_ZILYANA(90, new int[] { 6247 }, new String[] { "Commander Zilyana is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16, Equipment.NONE), - GENERAL_GRARDOOR(90, new int[] { 6260 }, new String[] { "General Grardoor is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16, Equipment.NONE), - KRIL_TSUTSAROTH(90, new int[] { 6203 }, new String[] { "Kril Tsutsaroth is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16, Equipment.NONE), - KREE_ARRA(90, new int[] { 6222 }, new String[] { "Kree'arra is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16, Equipment.NONE), - SKELETAL_WYVERN(70, new int[] { 3068, 3069, 3070, 3071 }, new String[] { "A skeletal wyvern requires an elemental, mirror", "or dragonfire shield." }, 72, false, 24 | 39 << 16, Equipment.NONE); + ABERRANT_SPECTRES(65, new int[] { 1604, 1605, 1606, 1607 }, new String[] { "Aberrant spectres have an extremely potent stench that drains", "stats and life points. A nose peg, protects against the stench." }, 60, true), + 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), + ANKOU(40, new int[] { 4381, 4382, 4383 }, new String[] { "Neither skeleton nor ghost, but a combination of both." }, 1, true), + 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), + 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), + BASILISKS(40, new int[] { 1616, 1617, 4228 }, new String[] { "A mirror shield is much neccesary when hunting these", "mad creatures." }, 40, 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), + BEARS(13, new int[] { 106, 105, 1195, 3645, 3664, 1326, 1327 }, new String[] { "A large animal with a crunching punch." }, 1, 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, }, new String[] { "irds aren't the most intelligent of creatures, but watch out for their", "sharp, stabbing beaks." }, 1, false), + BLACK_DEMONS(80, new int[] { 84, 677, 4702, 4703, 4704, 4705 }, new String[] { "Black Demons are magic creatures that are weak to magic attacks.", "They're the strongest demon and very dangerous." }, 1, 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 firey breath" }, 1, false, 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), + 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 firey breath." }, 1, false), + BRINE_RATS(45, new int[] { 3707 }, new String[] { "Small little creatures they are, yet so very", "powerfull." }, 47, 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 firey breath." }, 1, false, 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), + CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "It regenerates life points quickly and seems to be a good", "herblore monster." }, 7, false), + CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "The poisonous parts of them are presumably removed." }, 10, false), + CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "prefered to wear a witchwood icon." }, 58, false), + CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "These are lesser versions of jellies, watch out they can poison you." }, 17, false), + COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "A Mirror shield is necessary when fighting these monsters." }, 25, 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), + 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), + CROCODILES(50, new int[] { 1993, 6779 }, new String[] { "Crocodiles can be found near water and marshes in and near the Kharidian Desert." }, 1, 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), + 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), + DARK_BEASTS(90, new int[] { 2783 }, new String[] { "A dark beast can attack using magic or melee." }, 90, 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), + DOG(15, new int[] { 98, 99, 3582, 6374, 1994, 1593, 1594, 3582, 6374 }, new String[] { "Dogs are much like Wolves, they are pack creatures which will hunt in groups." }, 1, 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), + 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), + EARTH_WARRIORS(35, new int[] { 124 }, new String[] { "An Earth warrior is a monster made of earth which fights using melee." }, 1, 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), + 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), + 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), + 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), + 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), + 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), + GORAKS(70, new int[] { 4418, 6218 }, new String[] { "Goraks can be tough monsters to fight. Be prepared." }, 1, false), + GREATER_DEMONS(75, new int[] { 83, 4698, 4699, 4700, 4701, 6208, 6206, 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), + GREEN_DRAGON(52, new int[] { 941, 4677, 4678, 4679, 4680, 5362 }, new String[] { "Green dragons are very powerfull, they have fierce", "fiery breath." }, 1, false), + HARPIE_BUG_SWARMS(45, new int[] { 3153 }, new String[] { "Harpie Bug Swarms are insectoid Slayer monsters." }, 33, false), + HELLHOUNDS(75, new int[] { 49, 3586, 6210, }, new String[] { "Hellhounds are mid to high level demons." }, 1, 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), + 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), + 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), + 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), + ICE_WARRIOR(45, new int[] { 125, 145, 3073 }, new String[] { "Ice warriors, are cold magestic creatures." }, 1, 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), + 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 firey breath." }, 1, false, 40 | 59 << 16), + 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), + 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), + KALPHITES(15, new int[] { 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161 }, new String[] { "Kalaphite are large insects which live in great hives under the desert sands." }, 1, false), + KURASKS(65, new int[] { 1608, 1609, 4229 }, new String[] { "A kurask is a very quick creature." }, 70, false), + LESSER_DEMONS(60, new int[] { 6203, 82, 3064, 4694, 4695, 6208, 6204, 6206, 3064, 4696, 4697, 6101 }, new String[] { "Lesser Demons are magic creatures so they are weak to magical attacks." }, 1, false), + MITHRIL_DRAGON(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 firey breath." }, 1, false, 5 | 9 << 16), + 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), + 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), + MOSS_GIANTS(40, new int[] { 112, 1587, 1588, 1681, 4534, 4688, 4706 }, new String[] { "They are known to carry large sticks." }, 1, false), + NECHRYAELS(85, new int[] { 1613 }, new String[] { "Nechryael are demons of decay which summon small winged beings which", "help them fight their victems." }, 80, false), + OGRES(40, new int[] { 114, 115, 374, 3587, 6267 }, new String[] { "Ogres are brutal creatures, favouring large blunt maces and clubs", "they often attack without warning." }, 1, false), + OTHERWORDLY_BEING(40, new int[] { 126 }, new String[] { "A creature filled with everlasting power." }, 1, 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), + 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), + ROCK_SLUGS(20, new int[] { 1631, 1632 }, new String[] { "A rock slug can leave behind a trail of his presence.." }, 20, false), + SCORPIONS(7, new int[] { 107, 1477, 4402, 4403, 144 }, new String[] { "A scorpion makes a piercing sound, watch out for it's", " long sharp tail." }, 1, 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), + 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 }, new String[] { "Skeletons are undead monsters found in various locations." }, 1, true), + 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), + SPIRTUAL_MAGES(60, new int[] { 6221, 6231, 6257, 6278 }, new String[] { "They are dangerous, they hit with mage." }, 83, false), + SPIRTUAL_RANGERS(60, new int[] { 6220, 6230, 6256, 6276 }, new String[] { "They are dangerous, they hit with range." }, 63, false), + SPIRTUAL_WARRIORS(60, new int[] { 6219, 6229, 6255, 6277, }, new String[] { "They are dangerous, they hit with melee." }, 68, 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 firey breath." }, 1, false, 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, }, new String[] { "Trolls have a crushing attack, it's bets to wear a high crushing defence." }, 1, false), + TUROTHS(60, new int[] { 1626, 1627, 1628, 1629, 1630 }, new String[] { "Turoths are Slayer monsters that require a Slayer level of 55 to kill" }, 55, false), + 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), + VAMPIRES(35, new int[] { 1023, 1220, 1223, 1225, 6214 }, new String[] { "Vampies arr equiped with large fangs", "they can do serious damage." }, 1, false), + WATERFIENDS(75, new int[] { 5361 }, new String[] { "A waterfiend takes no damage from fire!" }, 1, 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), + 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), + ZOMBIES(10, new int[] { 73, 74, 75, 76, 2058, 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, }, new String[] { "Zombies are creatures with no brain, they do hit farley", "high though." }, 1, true), + JAD(90, new int[] { }, new String[] { "TzTok-Jad is the king of the Fight Caves." }, 1, false, 1 | 1 << 16), + CHAOS_ELEMENTAL(90, new int[] { 3200 }, new String[] { "The Chaos Elemental is located in the deep Wilderness." }, 1, false, 5 | 25 << 16), + GIANT_MOLE(75, new int[] { 3340 }, new String[] { "Fighting the Giant Mole will require a light source." }, 1, 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, 5 | 25 << 16), + COMMANDER_ZILYANA(90, new int[] { 6247 }, new String[] { "Commander Zilyana is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16), + GENERAL_GRARDOOR(90, new int[] { 6260 }, new String[] { "General Grardoor is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16), + KRIL_TSUTSAROTH(90, new int[] { 6203 }, new String[] { "Kril Tsutsaroth is one of the four Godwars bosses." }, 1, false, 5 | 25 << 16), + KREE_ARRA(90, new int[] { 6222 }, new String[] { "Kree'arra is one of the four Godwars bosses." }, 1, 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, 24 | 39 << 16); static final HashMap taskMap = new HashMap<>(); static{ @@ -110,23 +110,20 @@ public enum Tasks { public String[] info; public int[] ids; public boolean undead; - public Equipment recEquip; public int amtHash; - Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, Equipment recEquip){ + Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead){ this.levelReq = levelReq; this.ids = ids; this.info = info; this.undead = undead; - this.recEquip = recEquip; this.combatCheck = combatCheck; } - Tasks(int combatCheck,int[] ids, String[] info, int levelReq, boolean undead, int amtHash, Equipment recEquip){ + Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, int amtHash){ this.levelReq = levelReq; this.ids = ids; this.info = info; this.undead = undead; - this.recEquip = recEquip; this.amtHash = amtHash; this.combatCheck = combatCheck; } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/LumbridgeDungeon.java b/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/LumbridgeDungeon.java index fdc2b21d3..cfca0ec06 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/LumbridgeDungeon.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/LumbridgeDungeon.java @@ -1,7 +1,7 @@ package core.game.node.entity.skill.slayer.dungeon; import core.cache.def.impl.NPCDefinition; -import core.game.node.entity.skill.slayer.Equipment; +import core.game.node.entity.skill.slayer.SlayerEquipmentFlags; import core.game.interaction.Option; import core.game.node.Node; import core.game.node.entity.Entity; @@ -75,7 +75,7 @@ public final class LumbridgeDungeon extends MapZone implements Plugin { * @return {@code True} if so. */ private boolean hasHelmet(final Player player) { - return Equipment.SPINY_HELMET.hasEquipment(player); + return SlayerEquipmentFlags.hasSpinyHelmet(player); } @Override diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/SmokeDungeon.java b/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/SmokeDungeon.java index 2d57086c0..875a6cded 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/SmokeDungeon.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/dungeon/SmokeDungeon.java @@ -2,7 +2,7 @@ package core.game.node.entity.skill.slayer.dungeon; import core.cache.def.impl.SceneryDefinition; import core.game.component.Component; -import core.game.node.entity.skill.slayer.Equipment; +import core.game.node.entity.skill.slayer.SlayerEquipmentFlags; import core.game.interaction.OptionHandler; import core.game.node.Node; import core.game.node.entity.Entity; @@ -164,7 +164,7 @@ public final class SmokeDungeon extends MapZone implements Plugin { * @return {@code True} if so. */ private static boolean isProtected(Player player) { - return Equipment.FACEMASK.hasEquipment(player); + return SlayerEquipmentFlags.hasFaceMask(player); } @Override diff --git a/Server/src/main/kotlin/rs09/game/content/global/action/EquipHandler.kt b/Server/src/main/kotlin/rs09/game/content/global/action/EquipHandler.kt index 99d125d8a..e252b41cb 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/action/EquipHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/action/EquipHandler.kt @@ -6,6 +6,7 @@ import core.game.node.entity.combat.equipment.WeaponInterface import core.game.node.entity.player.Player import core.game.node.entity.player.link.audio.Audio import core.game.node.entity.player.link.diary.DiaryType +import core.game.node.entity.skill.slayer.SlayerEquipmentFlags import core.game.system.task.Pulse import core.game.world.map.zone.ZoneBorders import core.plugin.Plugin @@ -78,6 +79,10 @@ class EquipHandler : InteractionListener() { wif.selectAutoSpell(-1, true) wif.openAutocastSelect() } + + if(SlayerEquipmentFlags.isSlayerEq(item.id)){ + SlayerEquipmentFlags.updateFlags(player) + } } } @@ -121,6 +126,10 @@ class EquipHandler : InteractionListener() { player.dialogueInterpreter.close() player.inventory.add(item) } + + if(SlayerEquipmentFlags.isSlayerEq(item.id)){ + SlayerEquipmentFlags.updateFlags(player) + } } } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/withitem/TOTTHelmOnCape.kt b/Server/src/main/kotlin/rs09/game/interaction/item/withitem/TOTTHelmOnCape.kt new file mode 100644 index 000000000..1eff3699f --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/withitem/TOTTHelmOnCape.kt @@ -0,0 +1,42 @@ +package rs09.game.interaction.item.withitem + +import api.Container +import api.ContentAPI +import api.DialUtils +import org.rs09.consts.Items +import rs09.game.content.dialogue.DialogueFile +import rs09.game.interaction.InteractionListener +import rs09.tools.END_DIALOGUE + +class TOTTHelmOnCape : InteractionListener() { + override fun defineListeners() { + onUseWith(ITEM, Items.SLAYER_HELMET_13263, Items.SLAYER_CAPE_9786, Items.SLAYER_CAPET_9787){ player, used, with -> + val alreadyHasHelm = ContentAPI.getAttribute(player, "cape_perks:tott:helmet-stored", false) + + if(alreadyHasHelm){ + ContentAPI.sendDialogue(player, "You've already stored the components of a helmet in this cape.") + } else { + ContentAPI.openDialogue(player, object : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + when(stage){ + 0 -> dialogue("This will destroy your helmet permanently.").also { stage++ } + 1 -> interpreter!!.sendOptions("Continue?", "Yes", "No").also { stage++ } + 2 -> when(buttonID){ + 1 -> { + if(ContentAPI.removeItem(player, Items.SLAYER_HELMET_13263, Container.INVENTORY)) { + dialogue(*DialUtils.splitLines("You disassemble the helmet and place the components into their respective pockets on your cape.")) + ContentAPI.setAttribute(player, "/save:cape_perks:tott:helmet-stored", true) + stage = END_DIALOGUE + } + } + 2 -> end() + } + } + } + }) + } + + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt index ace2c1905..4aad2bb0a 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt @@ -15,10 +15,13 @@ import core.game.node.entity.combat.equipment.WeaponInterface 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.entity.skill.slayer.SlayerEquipmentFlags import core.game.node.entity.state.EntityState import core.game.world.map.path.Pathfinder import core.tools.RandomFunction import rs09.game.node.entity.combat.CombatSwingHandler +import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks +import kotlin.math.ceil import kotlin.math.floor /** @@ -152,13 +155,13 @@ open class MeleeSwingHandler val amuletName = (if(entity is Player) ContentAPI.getItemFromEquipment(entity, EquipmentSlot.AMULET)?.name ?: "null" else "null").toLowerCase() val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none" - if (entity is Player //Slayer helm/ black mask - && (helmetName.contains("black mask") || helmetName.contains("slayer helm")) - && entity.slayer.task?.ids?.contains((entity.properties.combatPulse.getVictim()?.id ?: 0)) == true - ) { - effectiveAttackLevel *= 1.2 + if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.PRECISION_STRIKES, entity)){ //Attack skillcape perk + effectiveAttackLevel += 6 } + if(entity is Player) + effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape + else if (entity is Player //Salve amulet && (amuletName.contains("salve")) && checkUndead(victimName) @@ -171,7 +174,7 @@ open class MeleeSwingHandler override fun calculateHit(entity: Entity?, victim: Entity?, modifier: Double): Int { val level = entity!!.skills.getLevel(Skills.STRENGTH) - val bonus = entity.properties.bonuses[11] + var bonus = entity.properties.bonuses[11] var prayer = 1.0 if (entity is Player) { prayer += entity.prayer.getSkillBonus(Skills.STRENGTH) @@ -182,7 +185,15 @@ open class MeleeSwingHandler } else if (entity.properties.attackStyle.style == WeaponInterface.STYLE_CONTROLLED) { cumulativeStr += 1.0 } + + //Strength skillcape perk + if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.FINE_ATTUNEMENT, entity) && ContentAPI.getItemFromEquipment(entity, EquipmentSlot.WEAPON)?.definition?.getRequirement(Skills.STRENGTH) != 0) + bonus = ceil(bonus * 1.20).toInt() + cumulativeStr *= getSetMultiplier(entity, Skills.STRENGTH) + + if(entity is Player) 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)).toInt() diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/RangeSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/RangeSwingHandler.kt index 4654597d9..7072bbec3 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/RangeSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/RangeSwingHandler.kt @@ -26,6 +26,7 @@ import core.game.world.map.RegionManager import core.game.world.update.flag.context.Graphics import core.tools.RandomFunction import rs09.game.node.entity.combat.CombatSwingHandler +import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks import rs09.game.system.SystemLogger import rs09.game.world.GameWorld import java.util.* @@ -247,6 +248,8 @@ open class RangeSwingHandler if(entity.properties.attackStyle.style == WeaponInterface.STYLE_RANGE_ACCURATE) effectiveRangedLevel += 3 effectiveRangedLevel += 8 if(entity is Player && entity.isWearingVoid(false)) effectiveRangedLevel *= 1.1 + if(entity is Player && SkillcapePerks.isActive(SkillcapePerks.ACCURATE_MARKSMAN,entity)) effectiveRangedLevel *= 1.1 + effectiveRangedLevel = floor(effectiveRangedLevel) effectiveRangedLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt index 8c4a1d4ed..98e3ecbfa 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -8,6 +8,7 @@ import core.game.node.entity.player.link.SpellBookManager import core.game.node.entity.player.link.emote.Emotes import core.game.node.entity.player.link.grave.GraveType import core.game.node.entity.player.link.music.MusicEntry +import core.game.node.entity.skill.slayer.SlayerEquipmentFlags import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.json.simple.JSONArray diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt index 92dc0c733..dddeacd2e 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt @@ -723,6 +723,7 @@ class PlayerSaver (val player: Player){ } slayer.put("totalTasks",slayerManager.totalTasks.toString()) slayer.put("canEarnPoints",slayerManager.isCanEarnPoints) + slayer.put("equipmentFlags",slayerManager.equipmentFlags) root.put("slayer",slayer) } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/skillcapeperks/SkillcapePerks.kt index 12c75b817..79802c385 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/skillcapeperks/SkillcapePerks.kt @@ -63,6 +63,14 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? player.dialogueInterpreter.sendDialogue("Your cape is still on cooldown.","Ready in " + java.util.concurrent.TimeUnit.MILLISECONDS.toMinutes(time - System.currentTimeMillis()) + " minutes.") } }), + TRICKS_OF_THE_TRADE("cape_perks:tott",{player -> + val hasHelmetBonus = api.ContentAPI.getAttribute(player, "cape_perks:tott:helmet-stored", false) + if(hasHelmetBonus){ + api.ContentAPI.sendDialogue(player, "Your cape's pockets are lined with all the utilities you need for slayer.") + } else { + api.ContentAPI.sendDialogue(player, "Your cape is lined with empty pockets shaped like various utilities needed for slayer.") + } + }), NONE("cape_perks:none") ; @@ -87,7 +95,7 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? Skillcape.THIEVING -> NONE Skillcape.CRAFTING -> NONE Skillcape.FLETCHING -> NONE - Skillcape.SLAYER -> NONE + Skillcape.SLAYER -> TRICKS_OF_THE_TRADE Skillcape.CONSTRUCTION -> NONE Skillcape.MINING -> PRECISION_MINER Skillcape.SMITHING -> BAREFISTED_SMITHING From eb84efda79abfb4951672de3f3e2bebb4b4f7714 Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 20:04:28 -0500 Subject: [PATCH 04/44] Quick preemptive bugfix --- .../game/node/entity/skill/slayer/SlayerEquipmentFlags.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt index 322d82e57..23e7e40d7 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt @@ -18,7 +18,7 @@ object SlayerEquipmentFlags { @JvmStatic fun updateFlags(player: Player){ var flags = 0 - if(SkillcapePerks.isActive(SkillcapePerks.TRICKS_OF_THE_TRADE,player) && ContentAPI.getAttribute(player, "cape_perks:tott:helmet-stored", false)) flags = 0x2F + if(SkillcapePerks.isActive(SkillcapePerks.TRICKS_OF_THE_TRADE,player) && ContentAPI.getAttribute(player, "cape_perks:tott:helmet-stored", false)) flags = 0x3F else if(hasItem(player, Items.SLAYER_HELMET_13263)) flags = 0x1F else if(hasItem(player, Items.NOSE_PEG_4168)) flags = 1 else if(hasItem(player, Items.EARMUFFS_4166)) flags = flags or (1 shl 1) @@ -68,7 +68,7 @@ object SlayerEquipmentFlags { @JvmStatic fun getDamAccBonus(player: Player): Double { - val isCape = player.slayer.equipmentFlags == 0x2F + val isCape = player.slayer.equipmentFlags == 0x3F val hasMask = hasBlackMask(player) return if(isCape) 1.075 From 428502dde55a8367860fb52e06904ef5c35994ff Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 20:32:08 -0500 Subject: [PATCH 05/44] Quick preemptive bugfix --- .../game/node/entity/combat/handlers/MeleeSwingHandler.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt index 4aad2bb0a..86e048129 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt @@ -151,7 +151,6 @@ open class MeleeSwingHandler effectiveAttackLevel = floor(effectiveAttackLevel) effectiveAttackLevel *= (entity.properties.bonuses[entity.properties.attackStyle.bonusType] + 64) - val helmetName = (if(entity is Player) ContentAPI.getItemFromEquipment(entity, EquipmentSlot.HAT)?.name ?: "null" else "null").toLowerCase() val amuletName = (if(entity is Player) ContentAPI.getItemFromEquipment(entity, EquipmentSlot.AMULET)?.name ?: "null" else "null").toLowerCase() val victimName = entity.properties.combatPulse.getVictim()?.name ?: "none" @@ -159,7 +158,7 @@ open class MeleeSwingHandler effectiveAttackLevel += 6 } - if(entity is Player) + if(entity is Player && (entity.properties.combatPulse.getVictim()?.id ?: 0) in entity.slayer.task.ids) effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape else if (entity is Player //Salve amulet @@ -192,7 +191,8 @@ open class MeleeSwingHandler cumulativeStr *= getSetMultiplier(entity, Skills.STRENGTH) - if(entity is Player) cumulativeStr *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer helm/black mask/skillcape + if(entity is Player && (entity.properties.combatPulse.getVictim()?.id ?: 0) in entity.slayer.task.ids) + 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*/ From 386b65799a156a122f90fddb08c6e77a8f7dcae9 Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 20:35:29 -0500 Subject: [PATCH 06/44] Quick preemptive bugfix --- .../game/node/entity/combat/handlers/MeleeSwingHandler.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt index 86e048129..3b8346b79 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/handlers/MeleeSwingHandler.kt @@ -158,7 +158,7 @@ open class MeleeSwingHandler effectiveAttackLevel += 6 } - if(entity is Player && (entity.properties.combatPulse.getVictim()?.id ?: 0) in entity.slayer.task.ids) + if(entity is Player && entity.slayer.task?.ids?.contains((entity.properties.combatPulse?.getVictim()?.id ?: 0)) == true) effectiveAttackLevel *= SlayerEquipmentFlags.getDamAccBonus(entity) //Slayer Helm/ Black Mask/ Slayer cape else if (entity is Player //Salve amulet @@ -191,7 +191,7 @@ open class MeleeSwingHandler cumulativeStr *= getSetMultiplier(entity, Skills.STRENGTH) - if(entity is Player && (entity.properties.combatPulse.getVictim()?.id ?: 0) in entity.slayer.task.ids) + if(entity is Player && entity.slayer.task?.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 From 4a6502b4ea6b490f0e4ab5da2064f76f56451bab Mon Sep 17 00:00:00 2001 From: ceikry Date: Sat, 31 Jul 2021 22:26:39 -0500 Subject: [PATCH 07/44] Limited daily rerolls to 10. --- .../skill/slayer/SlayerMasterDialogue.java | 56 +++++++++++++++++-- Server/src/main/kotlin/rs09/ServerStore.kt | 2 + 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerMasterDialogue.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerMasterDialogue.java index 164e902ee..ecb1aed5f 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerMasterDialogue.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerMasterDialogue.java @@ -1,5 +1,7 @@ package core.game.node.entity.skill.slayer; +import org.json.simple.JSONObject; +import rs09.ServerStore; import rs09.game.world.GameWorld; import core.game.content.dialogue.DialoguePlugin; import core.game.content.dialogue.FacialExpression; @@ -13,6 +15,8 @@ import core.game.node.entity.player.link.quest.Quest; import core.game.node.item.Item; import core.plugin.Initializable; +import static rs09.tools.DialogueConstKt.END_DIALOGUE; + /** * Represents the dialogue plugin used for a slayer master. * @@ -68,6 +72,8 @@ public final class SlayerMasterDialogue extends DialoguePlugin { private final int level = 2; + private int rerolls = 0; + /** * Constructs a new {@code SlayerMasterDialogue} {@code Object}. */ @@ -117,6 +123,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin { @Override public boolean handle(int interfaceId, int buttonId) { + rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase()); if (isDiary) { switch (stage) { case 999: @@ -495,8 +502,8 @@ public final class SlayerMasterDialogue extends DialoguePlugin { break; } if (Master.hasSameTask(master, player)) { - interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. Come back when you've", "finished your task."); - stage = 999; + interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. But let me check something..."); + stage = 847; } else { player.getSlayer().setTaskCount(0); player.getSlayer().generate(master); @@ -514,9 +521,9 @@ public final class SlayerMasterDialogue extends DialoguePlugin { } else { options("Got any tips for me?", "Okay, great!"); } - stage = 854; + stage++; break; - case 854: + case 845: switch (buttonId) { case 1: interpreter.sendDialogues(master.getNpc(), getExpression(master), player.getSlayer().getTask().getTip()); @@ -528,8 +535,45 @@ public final class SlayerMasterDialogue extends DialoguePlugin { break; case 3: player("I'd like to re-roll this task."); + if(rerolls == 10){ + stage++; + } else { + player.getSlayer().clear(); + getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1); + stage = 701; + } + } + break; + case 846: + npcl(FacialExpression.NEUTRAL, "Actually, you're out of free rerolls. You can buy a reroll from my reward store, though."); + stage = END_DIALOGUE; + break; + case 847: + if(rerolls < 10){ + npcl(FacialExpression.NEUTRAL, "You do have " + (10 - rerolls) + " rerolls left today, would you like to use one?"); + stage++; + } + else { + npcl(FacialExpression.NEUTRAL, "And it also seems you're out of rerolls for today. That's unfortunate."); + stage = END_DIALOGUE; + } + break; + case 848: + options("Yes, please.", "No, thanks."); + stage++; + break; + case 849: + switch(buttonId){ + case 1: + playerl(FacialExpression.FRIENDLY, "Yes, please."); player.getSlayer().clear(); + getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1); stage = 701; + break; + case 2: + playerl(FacialExpression.NEUTRAL, "No, thanks."); + stage = END_DIALOGUE; + break; } break; case 860: @@ -667,4 +711,8 @@ public final class SlayerMasterDialogue extends DialoguePlugin { return new int[]{70, 1598, 1596, 1597, 1599, 8275, 8273, 8274, 8649}; } + private JSONObject getStoreFile() { + return ServerStore.getArchive("daily-slayer-rerolls"); + } + } diff --git a/Server/src/main/kotlin/rs09/ServerStore.kt b/Server/src/main/kotlin/rs09/ServerStore.kt index 195a03c98..aa42288f1 100644 --- a/Server/src/main/kotlin/rs09/ServerStore.kt +++ b/Server/src/main/kotlin/rs09/ServerStore.kt @@ -63,6 +63,7 @@ object ServerStore { } } + @JvmStatic fun getArchive(name: String): JSONObject { if(fileMap[name] == null){ fileMap[name] = JSONObject() @@ -87,6 +88,7 @@ object ServerStore { } } + @JvmStatic fun JSONObject.getInt(key: String): Int { return when(val value = this[key]){ is Long -> value.toInt() From 20e430475740241f3868e183bab69dfb0be6a0ec Mon Sep 17 00:00:00 2001 From: ceikry Date: Sun, 1 Aug 2021 17:08:28 -0500 Subject: [PATCH 08/44] can no longer wear (g) or (t) rune platebodies without having done dragon slayer --- .../content/quest/free/dragonslayer/DragonSlayerPlugin.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java b/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java index 0d1a639d2..3e04833cb 100644 --- a/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java +++ b/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java @@ -105,6 +105,8 @@ public final class DragonSlayerPlugin extends OptionHandler { ItemDefinition.forId(2653).getHandlers().put("option:wear", this); ItemDefinition.forId(2669).getHandlers().put("option:wear", this); ItemDefinition.forId(2661).getHandlers().put("option:wear", this); + ItemDefinition.forId(2615).getHandlers().put("option:wear", this); + ItemDefinition.forId(2623).getHandlers().put("option:wear", this); // guild SceneryDefinition.forId(24357).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(10558).getHandlers().put("option:open", this); @@ -143,6 +145,8 @@ public final class DragonSlayerPlugin extends OptionHandler { case 2653: case 2661: case 2669: + case 2615: + case 2623: if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 100) { player.getPacketDispatch().sendMessage("You need to complete the Dragon Slayer Quest in order to wear this."); return true; From 1ac9dd360a95ad56240982c14b17282344633a92 Mon Sep 17 00:00:00 2001 From: ceikry Date: Sun, 1 Aug 2021 17:24:03 -0500 Subject: [PATCH 09/44] Can no longer wear standard, (g), (t), or god rune platebodies or dragonhide bodies without having done dragon slayer --- .../free/dragonslayer/DragonSlayerPlugin.java | 21 ---------- .../free/dragonslayer/DSEquipListeners.kt | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt diff --git a/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java b/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java index 3e04833cb..cc8d30721 100644 --- a/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java +++ b/Server/src/main/java/core/game/content/quest/free/dragonslayer/DragonSlayerPlugin.java @@ -99,14 +99,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); - // reward items - ItemDefinition.forId(1127).getHandlers().put("option:wear", this); - ItemDefinition.forId(1135).getHandlers().put("option:wear", this); - ItemDefinition.forId(2653).getHandlers().put("option:wear", this); - ItemDefinition.forId(2669).getHandlers().put("option:wear", this); - ItemDefinition.forId(2661).getHandlers().put("option:wear", this); - ItemDefinition.forId(2615).getHandlers().put("option:wear", this); - ItemDefinition.forId(2623).getHandlers().put("option:wear", this); // guild SceneryDefinition.forId(24357).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(10558).getHandlers().put("option:open", this); @@ -140,19 +132,6 @@ public final class DragonSlayerPlugin extends OptionHandler { ClimbActionHandler.climbLadder(player, (Scenery) node, "climb-up"); } break; - case 1127: - case 1135: - case 2653: - case 2661: - case 2669: - case 2615: - case 2623: - if (player.getQuestRepository().getQuest("Dragon Slayer").getStage(player) != 100) { - player.getPacketDispatch().sendMessage("You need to complete the Dragon Slayer Quest in order to wear this."); - return true; - } - InteractionListeners.run(node.getId(),0,"equip",player,node); - 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/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt b/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt new file mode 100644 index 000000000..8c86f5482 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt @@ -0,0 +1,41 @@ +package rs09.game.content.quest.free.dragonslayer + +import api.ContentAPI +import org.rs09.consts.Items +import rs09.game.interaction.InteractionListener + +class DSEquipListeners : InteractionListener() { + + private val restrictedItems = intArrayOf( + Items.RUNE_PLATEBODY_1127, + Items.RUNE_PLATEBODY_G_10798, + Items.RUNE_PLATEBODY_G_2615, + Items.RUNE_PLATEBODY_G_13800, + Items.RUNE_PLATEBODY_T_10800, + Items.RUNE_PLATEBODY_T_13805, + Items.RUNE_PLATEBODY_T_2623, + Items.ZAMORAK_PLATEBODY_2653, + Items.SARADOMIN_PLATEBODY_2661, + Items.GUTHIX_PLATEBODY_2669, + Items.GREEN_DHIDE_BODY_1135, + Items.BLUE_DHIDE_BODY_2499, + Items.RED_DHIDE_BODY_2501, + Items.BLACK_DHIDE_BODY_2503, + Items.DHIDE_BODYG_7370, + Items.DHIDE_BODY_G_7374, + Items.DHIDE_BODY_T_7372, + Items.DHIDE_BODY_T_7376 + ) + + override fun defineListeners() { + for(id in restrictedItems){ + onEquip(id){ player, _ -> + if(!player.questRepository.isComplete("Dragon Slayer")){ + ContentAPI.sendMessage(player, "You must have completed Dragon Slayer to equip this.") + return@onEquip false + } + return@onEquip true + } + } + } +} \ No newline at end of file From 174e6221de7e12764bfc81f6ba40d6b567a78b22 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Mon, 2 Aug 2021 04:00:28 +0000 Subject: [PATCH 10/44] Slayer improvements --- .../interaction/inter/JewelleryInterface.java | 2 +- .../fletching/items/arrow/ArrowHeadPulse.java | 2 +- .../fletching/items/bolts/BoltPulse.java | 2 +- .../skill/slayer/EnchantedGemDialogue.java | 3 +- .../skill/slayer/SlayerEquipmentFlags.kt | 18 +- .../entity/skill/slayer/SlayerManager.java | 206 ++++++++---------- .../skill/slayer/SlayerRewardPlugin.java | 30 ++- .../entity/player/info/login/PlayerSaver.kt | 20 +- .../node/entity/skill/slayer/SlayerFlags.kt | 152 +++++++++++++ 9 files changed, 277 insertions(+), 158 deletions(-) create mode 100644 Server/src/main/kotlin/rs09/game/node/entity/skill/slayer/SlayerFlags.kt diff --git a/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java b/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java index 15daafba9..251da81c8 100644 --- a/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java +++ b/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java @@ -186,7 +186,7 @@ public final class JewelleryInterface extends ComponentPlugin { }); return true; } - if(!player.getSlayer().getLearned()[1] && data.equals(JewelleryItem.SLAYER_RING)){ + if(!player.getSlayer().flags.isRingUnlocked()){ player.sendMessages("You don't know how to make this. Talk to any Slayer master in order to learn the", "ability that creates Slayer rings."); return true; } diff --git a/Server/src/main/java/core/game/node/entity/skill/fletching/items/arrow/ArrowHeadPulse.java b/Server/src/main/java/core/game/node/entity/skill/fletching/items/arrow/ArrowHeadPulse.java index 17bfe101e..2d3dd0870 100644 --- a/Server/src/main/java/core/game/node/entity/skill/fletching/items/arrow/ArrowHeadPulse.java +++ b/Server/src/main/java/core/game/node/entity/skill/fletching/items/arrow/ArrowHeadPulse.java @@ -43,7 +43,7 @@ public class ArrowHeadPulse extends SkillPulse { @Override public boolean checkRequirements() { if (arrow.unfinished == 4160) { - if (!player.getSlayer().getLearned()[0]) { + if (!player.getSlayer().flags.isBroadsUnlocked()) { player.getDialogueInterpreter().sendDialogue("You need to unlock the ability to create broad arrows."); return false; } diff --git a/Server/src/main/java/core/game/node/entity/skill/fletching/items/bolts/BoltPulse.java b/Server/src/main/java/core/game/node/entity/skill/fletching/items/bolts/BoltPulse.java index f8581b08c..f8ec05101 100644 --- a/Server/src/main/java/core/game/node/entity/skill/fletching/items/bolts/BoltPulse.java +++ b/Server/src/main/java/core/game/node/entity/skill/fletching/items/bolts/BoltPulse.java @@ -60,7 +60,7 @@ public final class BoltPulse extends SkillPulse { @Override public boolean checkRequirements() { if (bolt.getUnfinished().getId() == 13279) { - if (!player.getSlayer().getLearned()[0]) { + if (!player.getSlayer().flags.isBroadsUnlocked()) { player.getDialogueInterpreter().sendDialogue("You need to unlock the ability to create broad bolts."); return false; } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/EnchantedGemDialogue.java b/Server/src/main/java/core/game/node/entity/skill/slayer/EnchantedGemDialogue.java index 583a59ab8..f56ed151b 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/EnchantedGemDialogue.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/EnchantedGemDialogue.java @@ -93,8 +93,7 @@ public final class EnchantedGemDialogue extends DialoguePlugin { break; } interpreter.sendDialogues(player.getSlayer().getMaster().getNpc(), FacialExpression.HALF_GUILTY, "You're currently assigned to kill " + (player.getSlayer().getTask() == Tasks.JAD ? " TzTok-Jad!" : NPCDefinition.forId((player.getSlayer().getTask().getNpcs()[0])).getName().toLowerCase() + "'s;"), "only " + player.getSlayer().getAmount() + " more to go."); - player.varpManager.get(2502).setVarbit(1,player.getSlayer().getTask().ordinal()); - player.varpManager.get(2502).setVarbit(8,player.getSlayer().getAmount()).send(player); + player.varpManager.get(2502).setVarbit(0,player.getSlayer().flags.getTaskFlags() >> 4).send(player); stage = 11; break; case 11: diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt index 23e7e40d7..d925e3d1f 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerEquipmentFlags.kt @@ -28,47 +28,47 @@ object SlayerEquipmentFlags { if((ContentAPI.getItemFromEquipment(player, EquipmentSlot.AMULET)?.id ?: 0) == Items.WITCHWOOD_ICON_8923) flags = flags or (1 shl 7) if((ContentAPI.getItemFromEquipment(player, EquipmentSlot.SHIELD)?.id ?: 0) == Items.MIRROR_SHIELD_4156) flags = flags or (1 shl 8) - player.slayer.equipmentFlags = flags + player.slayer.flags.equipmentFlags = flags } @JvmStatic fun hasNosePeg(player: Player): Boolean{ - return player.slayer.equipmentFlags and 1 == 1 + return player.slayer.flags.equipmentFlags and 1 == 1 } @JvmStatic fun hasEarmuffs(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 1) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 1) and 1 == 1 } @JvmStatic fun hasFaceMask(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 2) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 2) and 1 == 1 } @JvmStatic fun hasBlackMask(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 3) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 3) and 1 == 1 } @JvmStatic fun hasSpinyHelmet(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 4) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 4) and 1 == 1 } @JvmStatic fun hasWitchwoodIcon(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 7) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 7) and 1 == 1 } @JvmStatic fun hasMirrorShield(player: Player): Boolean { - return (player.slayer.equipmentFlags shr 8) and 1 == 1 + return (player.slayer.flags.equipmentFlags shr 8) and 1 == 1 } @JvmStatic fun getDamAccBonus(player: Player): Double { - val isCape = player.slayer.equipmentFlags == 0x3F + val isCape = player.slayer.flags.equipmentFlags == 0x3F val hasMask = hasBlackMask(player) return if(isCape) 1.075 diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java index bb9f0ad47..669da7a1c 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java @@ -8,6 +8,7 @@ import core.game.node.entity.skill.Skills; import core.tools.RandomFunction; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import rs09.game.node.entity.skill.slayer.SlayerFlags; import java.util.ArrayList; import java.util.Collections; @@ -26,49 +27,9 @@ public final class SlayerManager { private final Player player; /** - * The current slayer master used. + * The player's slayer flags */ - private Master master; - - /** - * The current task. - */ - private Tasks task; - - /** - * The amount of the hunted killed. - */ - private int amount; - - /** - * The slayer points. - */ - private int slayerPoints; - - /** - * The task streak. - */ - private int taskCount; - - /** - * Total tasks completed - */ - private int taskTotal; - - /** - * The learned rewards. - */ - private final boolean[] learned = new boolean[3]; - - /** - * The removed tasks. - */ - private final List removed = new ArrayList<>(4); - - /** - * The equipment flags for the given player - */ - public int equipmentFlags = 0; + public final SlayerFlags flags; /** * Constructs a new {@Code SlayerManager} {@Code Object} @@ -76,39 +37,66 @@ public final class SlayerManager { */ public SlayerManager(Player player) { this.player = player; + this.flags = new SlayerFlags(player); } - /** - * If the player can earn points (taskTotal > 4) - */ - private boolean canEarnPoints = false; - public void parse(JSONObject slayerData){ Object m = slayerData.get("master"); - if(m != null) - this.master = Master.forId(Integer.parseInt(m.toString())); + if(m != null) { + flags.setMaster(Master.forId(Integer.parseInt(m.toString()))); + } Object t = slayerData.get("taskId"); if(t != null) - task = Tasks.values()[Integer.parseInt(t.toString())]; + flags.setTask(Tasks.values()[Integer.parseInt(t.toString())]); Object a = slayerData.get("taskAmount"); if(a != null) - amount = Integer.parseInt(a.toString()); - slayerPoints = Integer.parseInt( slayerData.get("points").toString()); - taskCount = Integer.parseInt( slayerData.get("taskStreak").toString()); - JSONArray learnedArray = (JSONArray) slayerData.get("learned_rewards"); - for(int i = 0; i < learnedArray.size(); i++){ - learned[i] = (boolean) learnedArray.get(i); - } + flags.setTaskAmount(Integer.parseInt(a.toString())); + Object points = slayerData.get("points"); + if(points != null){ + flags.setPoints(Integer.parseInt(points.toString())); + } + Object taskStreak = slayerData.get("taskStreak"); + if(taskStreak != null){ + flags.setTaskStreak(Integer.parseInt(taskStreak.toString())); + } + Object la = slayerData.get("learned_rewards"); + if(la != null) { + JSONArray learnedArray = (JSONArray) slayerData.get("learned_rewards"); + for (int i = 0; i < learnedArray.size(); i++) { + boolean unlocked = (boolean) learnedArray.get(i); + switch(i){ + case 0: + if(unlocked) flags.unlockBroads(); + break; + case 1: + if(unlocked) flags.unlockRing(); + break; + case 2: + if(unlocked) flags.unlockHelm(); + break; + default: + break; + } + } + } JSONArray removedTasks = (JSONArray) slayerData.get("removedTasks"); if(removedTasks != null){ for(int i = 0; i < removedTasks.size(); i++){ - removed.add(Tasks.values()[Integer.parseInt(removedTasks.get(i).toString())]); + flags.getRemoved().add(Tasks.values()[Integer.parseInt(removedTasks.get(i).toString())]); } } - taskTotal = Integer.parseInt( slayerData.get("totalTasks").toString()); - canEarnPoints = (boolean) slayerData.get("canEarnPoints"); + Object completedTasks = slayerData.get("totalTasks").toString(); + if(completedTasks != null) flags.setCompletedTasks(Integer.parseInt(completedTasks.toString())); + if(flags.getCompletedTasks() >= 4) flags.flagCanEarnPoints(); + + //New system parsing if(slayerData.containsKey("equipmentFlags")) - equipmentFlags = Integer.parseInt(slayerData.get("equipmentFlags").toString()); + flags.setEquipmentFlags(Integer.parseInt(slayerData.get("equipmentFlags").toString())); + if(slayerData.containsKey("taskFlags")) + flags.setTaskFlags(Integer.parseInt(slayerData.get("taskFlags").toString())); + if(slayerData.containsKey("rewardFlags")) + flags.setRewardFlags(Integer.parseInt(slayerData.get("rewardFlags").toString())); + } /** @@ -121,25 +109,25 @@ public final class SlayerManager { decrementAmount(1); if (!hasTask()) { clear(); - taskCount++; - taskTotal++; - if ((taskCount > 4 || canEarnPoints ) && master != Master.TURAEL && slayerPoints < 64000) { - int points = master.getTaskPoints()[0]; - if (taskCount % 10 == 0) { - points = master.getTaskPoints()[1]; - } else if (taskCount % 50 == 0) { - points = master.getTaskPoints()[2]; + flags.setTaskStreak(flags.getTaskStreak() + 1); + flags.setCompletedTasks(flags.getCompletedTasks() + 1); + if ((flags.getCompletedTasks() > 4 || flags.canEarnPoints() ) && flags.getMaster() != Master.TURAEL && flags.getPoints() < 64000) { + int points = flags.getMaster().getTaskPoints()[0]; + if (flags.getTaskStreak() % 10 == 0) { + points = flags.getMaster().getTaskPoints()[1]; + } else if (flags.getTaskStreak() % 50 == 0) { + points = flags.getMaster().getTaskPoints()[2]; } - slayerPoints += points; - if (slayerPoints > 64000) { - slayerPoints = 64000; + flags.incrementPoints(points); + if (flags.getPoints() > 64000) { + flags.setPoints(64000); } - player.sendMessages("You've completed " + taskCount + " tasks in a row and received " + points + " points, with a total of " + player.getSlayer().getSlayerPoints(),"You have completed " + taskTotal + " tasks in total. Return to a Slayer master."); - } else if(taskCount == 4){ + player.sendMessages("You've completed " + flags.getTaskStreak() + " tasks in a row and received " + points + " points, with a total of " + flags.getPoints(),"You have completed " + flags.getCompletedTasks() + " tasks in total. Return to a Slayer master."); + } else if(flags.getCompletedTasks() == 4){ player.sendMessage("You've completed your task; you will start gaining points on your next task!"); - canEarnPoints = true; + flags.flagCanEarnPoints(); } else { - player.sendMessages("You've completed your task; Complete " + (4 - taskCount) + " more task(s) to start gaining points.", "Return to a Slayer master."); + player.sendMessages("You've completed your task; Complete " + (4 - flags.getCompletedTasks()) + " more task(s) to start gaining points.", "Return to a Slayer master."); } } else { //player.sendMessage("You're assigned to kill " + NPCDefinition.forId((player.getSlayer().getTask().getNpcs()[0])).getName().toLowerCase() + "s; Only " + getAmount() + " more to go."); @@ -160,8 +148,7 @@ public final class SlayerManager { } else if (master == Master.VANNAKA) { player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 1, 14); } - getPlayer().varpManager.get(2502).setVarbit(1,task.ordinal()); - getPlayer().varpManager.get(2502).setVarbit(8,getAmount()).send(player); + getPlayer().varpManager.get(2502).setVarbit(0, flags.getTaskFlags() >> 4).send(player); } /** @@ -185,14 +172,13 @@ public final class SlayerManager { } public boolean canBeAssigned(Tasks task){ - return player.getSkills().getLevel(Skills.SLAYER) >= task.levelReq && !removed.contains(task); + return player.getSkills().getLevel(Skills.SLAYER) >= task.levelReq && !flags.getRemoved().contains(task); } /** * Clears the task. */ public void clear() { - setTask(null); setAmount(0); } @@ -210,14 +196,12 @@ public final class SlayerManager { * @return the name. */ public String getTaskName() { - if (task == null) { - return "null"; - } + Tasks task = flags.getTask(); if (task.getNpcs() == null) { return "no npcs report me"; } if (task.getNpcs().length < 1) { - return "npc length to small report me"; + return "npc length too small report me"; } return NPCDefinition.forId(task.getNpcs()[0]).getName().toLowerCase(); } @@ -227,15 +211,15 @@ public final class SlayerManager { * @return The task. */ public Tasks getTask() { - return task; + return flags.getTask(); } /** * Sets the task. * @param task The task to set. */ - public void setTask(Tasks task) { - this.task = task; + public void setTask(Tasks task){ + flags.setTask(task); } /** @@ -251,7 +235,7 @@ public final class SlayerManager { * @return The master. */ public Master getMaster() { - return master; + return flags.getMaster(); } /** @@ -259,7 +243,7 @@ public final class SlayerManager { * @param master The master to set. */ public void setMaster(Master master) { - this.master = master; + flags.setMaster(master); } /** @@ -267,13 +251,7 @@ public final class SlayerManager { * @return {@code True} if so. */ public boolean hasTask() { - if (task == null) { - return false; - } - if (getAmount() == 0) { - return false; - } - return true; + return getAmount() != 0; } /** @@ -281,7 +259,7 @@ public final class SlayerManager { * @return True if so. */ public boolean isCompleted() { - return amount <= 0; + return flags.getTaskAmount() <= 0; } /** @@ -289,7 +267,7 @@ public final class SlayerManager { * @return The amount. */ public int getAmount() { - return amount; + return flags.getTaskAmount(); } /** @@ -297,7 +275,7 @@ public final class SlayerManager { * @param amount The amount to set. */ public void setAmount(int amount) { - this.amount = amount; + flags.setTaskAmount(amount); } /** @@ -305,10 +283,8 @@ public final class SlayerManager { * @param amount the amount. */ public void decrementAmount(int amount) { - this.amount -= amount; - if(player.varpManager.get(2502).getVarbit(1) == null) player.varpManager.get(2502).setVarbit(1,task.ordinal()); - player.varpManager.get(2502).setVarbit(8,getAmount()); - player.varpManager.get(2502).send(player); + flags.decrementTaskAmount(amount); + player.varpManager.get(2502).setVarbit(0, flags.getTaskFlags() >> 4).send(player); } /** @@ -316,7 +292,7 @@ public final class SlayerManager { * @return {@code True} if so. */ public boolean hasStarted() { - return master != null; + return flags.getCompletedTasks() > 0 || flags.getTaskAmount() > 0; } /** @@ -324,7 +300,7 @@ public final class SlayerManager { * @return the slayerPoints. */ public int getSlayerPoints() { - return slayerPoints; + return flags.getPoints(); } /** @@ -332,7 +308,7 @@ public final class SlayerManager { * @param slayerPoints the slayerPoints to set */ public void setSlayerPoints(int slayerPoints) { - this.slayerPoints = slayerPoints; + flags.setPoints(slayerPoints); } /** @@ -340,7 +316,7 @@ public final class SlayerManager { * @return the taskCount. */ public int getTaskCount() { - return taskCount; + return flags.getTaskStreak(); } /** @@ -348,15 +324,7 @@ public final class SlayerManager { * @param taskCount the taskCount to set */ public void setTaskCount(int taskCount) { - this.taskCount = taskCount; - } - - /** - * Gets the learned. - * @return the learned. - */ - public boolean[] getLearned() { - return learned; + flags.setTaskStreak(taskCount); } /** @@ -364,13 +332,13 @@ public final class SlayerManager { * @return the removed. */ public List getRemoved() { - return removed; + return flags.getRemoved(); } - public int getTotalTasks() {return taskTotal;} + public int getTotalTasks() {return flags.getCompletedTasks();} public boolean isCanEarnPoints(){ - return canEarnPoints; + return flags.canEarnPoints(); } } diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerRewardPlugin.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerRewardPlugin.java index 6f5488e4a..480ba0f22 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerRewardPlugin.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerRewardPlugin.java @@ -132,34 +132,34 @@ public class SlayerRewardPlugin extends ComponentPlugin { break; case 22://Broad arrows case 29: - if (player.getSlayer().getLearned()[0]) { + if (player.getSlayer().flags.isBroadsUnlocked()) { player.sendMessage("You don't need to learn this ability again."); break; } if (purchase(player, 300)) { - player.getSlayer().getLearned()[0] = true; + player.getSlayer().flags.unlockBroads(); updateInterface(player, component); } break; case 23://Slayer ring case 30: - if (player.getSlayer().getLearned()[1]) { + if (player.getSlayer().flags.isRingUnlocked()) { player.sendMessage("You don't need to learn this ability again."); break; } if (purchase(player, 300)) { - player.getSlayer().getLearned()[1] = true; + player.getSlayer().flags.unlockRing(); updateInterface(player, component); } break; case 24://Slayer helm case 31: - if (player.getSlayer().getLearned()[2]) { + if (player.getSlayer().flags.isHelmUnlocked()) { player.sendMessage("You don't need to learn this ability again."); break; } if (purchase(player, 400)) { - player.getSlayer().getLearned()[2] = true; + player.getSlayer().flags.unlockHelm(); updateInterface(player, component); } break; @@ -268,8 +268,20 @@ public class SlayerRewardPlugin extends ComponentPlugin { player.getPacketDispatch().sendString(space + player.getSlayer().getSlayerPoints(), open.getId(), 19); break; case 163://learn - for (int i = 0; i < player.getSlayer().getLearned().length; i++) { - player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !player.getSlayer().getLearned()[i]); + for (int i = 0; i < 3; i++) { + switch(i){ + case 0: + player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !player.getSlayer().flags.isBroadsUnlocked()); + break; + case 1: + player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !player.getSlayer().flags.isRingUnlocked()); + break; + case 2: + player.getPacketDispatch().sendInterfaceConfig(open.getId(), 25 + i, !player.getSlayer().flags.isHelmUnlocked()); + break; + default: + break; + } } player.getPacketDispatch().sendString(space + player.getSlayer().getSlayerPoints(), open.getId(), 18); break; @@ -370,7 +382,7 @@ public class SlayerRewardPlugin extends ComponentPlugin { player.sendMessage("You need a Crafting level of at least 55 in order to do this."); return true; } - if (!player.getSlayer().getLearned()[2]) { + if (!player.getSlayer().flags.isHelmUnlocked()) { player.sendMessage("You need to unlock the ability to do that first."); return true; } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt index dddeacd2e..2c8d65e41 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt @@ -700,20 +700,6 @@ class PlayerSaver (val player: Player){ fun saveSlayer(root: JSONObject){ val slayer = JSONObject() val slayerManager = player.slayer - if(slayerManager.hasStarted()){ - slayer.put("master",slayerManager.master.npc.toString()) - } - if(slayerManager.hasTask()){ - slayer.put("taskId",slayerManager.task.ordinal.toString()) - slayer.put("taskAmount",slayerManager.amount.toString()) - } - slayer.put("points",slayerManager.slayerPoints.toString()) - slayer.put("taskStreak",slayerManager.taskCount.toString()) - val learnedRewards = JSONArray() - slayerManager.learned.map { - learnedRewards.add(it) - } - slayer.put("learned_rewards",learnedRewards) if(slayerManager.removed.isNotEmpty()) { val removedTasks = JSONArray() slayerManager.removed.map { @@ -721,9 +707,11 @@ class PlayerSaver (val player: Player){ } slayer.put("removedTasks",removedTasks) } + slayer.put("taskStreak",slayerManager.taskCount.toString()) slayer.put("totalTasks",slayerManager.totalTasks.toString()) - slayer.put("canEarnPoints",slayerManager.isCanEarnPoints) - slayer.put("equipmentFlags",slayerManager.equipmentFlags) + slayer.put("equipmentFlags",slayerManager.flags.equipmentFlags) + slayer.put("taskFlags", slayerManager.flags.taskFlags) + slayer.put("rewardFlags", slayerManager.flags.rewardFlags) root.put("slayer",slayer) } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/slayer/SlayerFlags.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/slayer/SlayerFlags.kt new file mode 100644 index 000000000..5619c87c7 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/slayer/SlayerFlags.kt @@ -0,0 +1,152 @@ +package rs09.game.node.entity.skill.slayer + +import core.game.node.entity.player.Player +import core.game.node.entity.skill.slayer.Master +import core.game.node.entity.skill.slayer.Tasks + +/** + * Bitflag-based system for storing slayer-related data for a player and various helper functions. + * @author Ceikry + */ +class SlayerFlags(val player: Player) { + var taskFlags = 0 + var rewardFlags = 0 + var equipmentFlags = 0 + var completedTasks = 0 + var taskStreak = 0 + + /** + * The removed tasks. + */ + val removed: List = ArrayList(4) + + /** + * Get/set master flags + */ + fun getMaster(): Master { + val ordinal = taskFlags and 0xF + return Master.values()[ordinal] + } + + fun setMaster(master: Master){ + taskFlags = (taskFlags - (taskFlags and 0xF)) or master.ordinal + } + + /** + *============================================== + */ + + + /** + * Get/set task flags + */ + fun getTask(): Tasks { + val ordinal = (taskFlags shr 4) and 0x7F + return Tasks.values()[ordinal] + } + + fun setTask(tasks: Tasks){ + taskFlags = (taskFlags - (getTask().ordinal shl 4)) or (tasks.ordinal shl 4) + } + + /** + *============================================== + */ + + /** + * Get/set/decrement task amount flag + */ + fun getTaskAmount(): Int { + return (taskFlags shr 11) and 0xFF + } + + fun setTaskAmount(amount: Int) { + taskFlags = (taskFlags - (getTaskAmount() shl 11)) or (amount shl 11) + } + + fun decrementTaskAmount(amount: Int){ + setTaskAmount(getTaskAmount() - amount) + } + /** + *============================================== + */ + + /** + * Get/Set canEarnPoints flag + */ + fun canEarnPoints(): Boolean { + return (taskFlags shr 16) and 1 == 1 + } + + fun flagCanEarnPoints() { + taskFlags = taskFlags or (1 shl 16) + } + /** + *============================================== + */ + + /** + * Get/set reward unlock flags + */ + fun isBroadsUnlocked(): Boolean{ + return rewardFlags and 1 == 1 + } + + fun unlockBroads() { + rewardFlags = rewardFlags or 1 + } + + fun isRingUnlocked(): Boolean { + return (rewardFlags shr 1) and 1 == 1 + } + + fun unlockRing() { + rewardFlags = rewardFlags or (1 shl 1) + } + + fun isHelmUnlocked(): Boolean { + return (rewardFlags shr 2) and 1 ==1 + } + + fun unlockHelm() { + rewardFlags = rewardFlags or (1 shl 2) + } + + /** + *============================================== + */ + + /** + * Get/set/increment points flag + */ + fun setPoints(amount: Int) { + rewardFlags = (rewardFlags - (getPoints() shl 15)) or (amount shl 15) + } + + fun getPoints(): Int { + return (rewardFlags shr 15) and 0xFFFF + } + + fun incrementPoints(amount: Int){ + setPoints(getPoints() + amount) + } + /** + *============================================== + */ + + /** + * Reset task and task amount to 0 + */ + fun clearTask() { + setTask(Tasks.values()[0]) + setTaskAmount(0) + } + + /** + * Checks if we have a task + */ + fun hasTask(): Boolean{ + return getTaskAmount() != 0 + } + +} \ No newline at end of file From 425e1a954ca32d8c575ec4e79d0e981c414b34dd Mon Sep 17 00:00:00 2001 From: ceikry Date: Sun, 1 Aug 2021 23:39:20 -0500 Subject: [PATCH 11/44] Force rune shop to buy chaos runes at 13ea and death runes at 27ea until formula is corrected --- Server/data/configs/item_configs.json | 2 ++ Server/src/main/java/core/game/content/global/shop/Shop.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 2fc325c31..b8cd15e3d 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -5625,6 +5625,7 @@ "examine": "Used for medium missile spells.", "grand_exchange_price": "320", "durability": null, + "tokkul_price": "270", "name": "Death rune", "tradeable": "true", "low_alchemy": "41", @@ -5651,6 +5652,7 @@ "examine": "Used for small missile spells.", "grand_exchange_price": "140", "durability": null, + "tokkul_price": "135", "name": "Chaos rune", "tradeable": "true", "low_alchemy": "18", diff --git a/Server/src/main/java/core/game/content/global/shop/Shop.java b/Server/src/main/java/core/game/content/global/shop/Shop.java index 080cfca8a..5b44cfc1c 100644 --- a/Server/src/main/java/core/game/content/global/shop/Shop.java +++ b/Server/src/main/java/core/game/content/global/shop/Shop.java @@ -639,7 +639,10 @@ public class Shop { } double mod = (maxMod + minMod) / 2; SystemLogger.logInfo("" + item.getDefinition().getAlchemyValue(highAlch) + " " + mod + " " + item.getAmount()); - int value = (int) (item.getDefinition().getAlchemyValue(highAlch) * mod * item.getAmount()); + int baseValue = item.getDefinition().getAlchemyValue(highAlch); + int value = (int) (baseValue * mod * item.getAmount()); + if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.CHAOS_RUNE_562) value = 13; + if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.DEATH_RUNE_560) value = 27; if(item.getId() == 12183){ value = 25 * item.getAmount(); } From 0feadf985bf322c7f36c3f0e668fdc794bd06100 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 07:44:29 -0500 Subject: [PATCH 12/44] Fixed a warrior's guild dupe --- Server/data/configs/item_configs.json | 2 +- .../wguild/catapult/CatapultRoom.java | 2 +- .../activity/wguild/WGuildListeners.kt | 42 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 Server/src/main/kotlin/rs09/game/content/activity/wguild/WGuildListeners.kt diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index b8cd15e3d..62d72fee2 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -80754,7 +80754,7 @@ "name": "Defensive shield", "weight": "3.6", "archery_ticket_price": "0", - "two_handed": "true", + "two_handed": "false", "id": "8856", "bonuses": "0,0,0,-6,-2,8,9,7,0,8,0,0,0,0,0", "equipment_slot": "5" diff --git a/Server/src/main/java/core/game/content/activity/wguild/catapult/CatapultRoom.java b/Server/src/main/java/core/game/content/activity/wguild/catapult/CatapultRoom.java index f2633d42b..47b4ae155 100644 --- a/Server/src/main/java/core/game/content/activity/wguild/catapult/CatapultRoom.java +++ b/Server/src/main/java/core/game/content/activity/wguild/catapult/CatapultRoom.java @@ -44,7 +44,7 @@ public final class CatapultRoom extends MapZone implements Plugin { /** * The target location. */ - private static final Location TARGET = Location.create(2842, 3545, 1); + public static final Location TARGET = Location.create(2842, 3545, 1); /** * The shield item id. diff --git a/Server/src/main/kotlin/rs09/game/content/activity/wguild/WGuildListeners.kt b/Server/src/main/kotlin/rs09/game/content/activity/wguild/WGuildListeners.kt new file mode 100644 index 000000000..fafd7ce09 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/activity/wguild/WGuildListeners.kt @@ -0,0 +1,42 @@ +package rs09.game.content.activity.wguild + +import core.game.component.Component +import core.game.container.impl.EquipmentContainer +import core.game.content.activity.wguild.catapult.CatapultRoom +import core.game.node.item.Item +import org.rs09.consts.Items +import rs09.game.interaction.InteractionListener + +class WGuildListeners : InteractionListener() { + override fun defineListeners() { + onEquip(Items.DEFENSIVE_SHIELD_8856){player, node -> + if (node is Item) { + if (player.location != CatapultRoom.TARGET) { + player.packetDispatch.sendMessage("You may not equip this shield outside the target area in the Warrior's Guild.") + return@onEquip false + } + if (player.equipment[EquipmentContainer.SLOT_WEAPON] != null) { + player.dialogueInterpreter.sendDialogue( + "You will need to make sure your sword hand is free to equip this", + "shield." + ) + return@onEquip false + } + + player.interfaceManager.hideTabs(2, 3, 5, 6, 7, 11, 12) + player.interfaceManager.openTab(4, Component(411)) + player.interfaceManager.setViewedTab(4) + player.interfaceManager.open(Component(410)) + return@onEquip true + } + + return@onEquip false + } + + onUnequip(Items.DEFENSIVE_SHIELD_8856){player, _ -> + player.interfaceManager.restoreTabs() + player.interfaceManager.openTab(4, Component(387)) + return@onUnequip true + } + } +} \ No newline at end of file From 644600070f979e42a5e63db417748c1796cd64d1 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 12:17:46 -0500 Subject: [PATCH 13/44] Add Tiadeche spawn --- Server/data/configs/npc_spawns.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 8d84a19ea..7b6c7a393 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -10734,5 +10734,9 @@ { "npc_id": "312", "loc_data": "{2421,3789,0,1,0}" + }, + { + "npc_id": "1164", + "loc_data": "{2780,3058,0,1,0}" } ] \ No newline at end of file From 2c993c5b97cac89a61ed2c2a4505edb4b7ee3c88 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 13:02:59 -0500 Subject: [PATCH 14/44] Fixed Turoth stats --- Server/data/configs/npc_configs.json | 493 ++------------------------- 1 file changed, 26 insertions(+), 467 deletions(-) diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json index 6a356ecf9..d12a0160a 100644 --- a/Server/data/configs/npc_configs.json +++ b/Server/data/configs/npc_configs.json @@ -2372,7 +2372,7 @@ "slayer_task": "29", "melee_animation": "99", "range_animation": "0", - "attack_speed": "6", + "attack_speed": "6", "defence_animation": "0", "weakness": "6", "slayer_exp": "16", @@ -16595,35 +16595,19 @@ "examine": "It's one leg short!", "melee_animation": "9471", "range_animation": "9471", - "attack_speed": "5", + "attack_speed": "4", + "magic_level": "1", "defence_animation": "9473", "magic_animation": "9471", "death_animation": "9472", "name": "Turoth", - "defence_level": "30", + "defence_level": "88", "safespot": null, "lifepoints": "27", - "strength_level": "1", - "id": "1622", - "range_level": "1", - "attack_level": "30" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", + "strength_level": "88", "id": "1623", "range_level": "1", - "attack_level": "30" + "attack_level": "58" }, { "examine": "The vacuumed face of evil.", @@ -16667,96 +16651,58 @@ "examine": "It's one leg short!", "melee_animation": "9471", "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", + "attack_speed": "4", + "magic_level": "1", "defence_animation": "9473", "magic_animation": "9471", "death_animation": "9472", "name": "Turoth", - "defence_level": "75", + "defence_level": "86", "safespot": null, "lifepoints": "79", - "strength_level": "85", + "strength_level": "86", "id": "1626", "clue_level": "2", - "range_level": "75", - "attack_level": "80" + "range_level": "1", + "attack_level": "56" }, { "examine": "It's one leg short!", "melee_animation": "9471", "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", + "attack_speed": "4", + "magic_level": "1", "defence_animation": "9473", "magic_animation": "9471", "death_animation": "9472", "name": "Turoth", - "defence_level": "75", + "defence_level": "84", "safespot": null, - "lifepoints": "79", - "strength_level": "85", + "lifepoints": "77", + "strength_level": "84", "id": "1627", "clue_level": "2", - "range_level": "75", - "attack_level": "80" + "range_level": "1", + "attack_level": "54" }, { "examine": "It's one leg short!", "melee_animation": "9471", "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", + "attack_speed": "4", + "magic_level": "1", "defence_animation": "9473", "magic_animation": "9471", "death_animation": "9472", "name": "Turoth", - "defence_level": "75", + "defence_level": "83", "safespot": null, - "lifepoints": "79", - "strength_level": "85", + "lifepoints": "76", + "strength_level": "83", "id": "1628", "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1629", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1630", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" + "range_level": "1", + "attack_level": "53" }, { "examine": "A rocky slug.", @@ -90884,40 +90830,6 @@ "range_level": "1", "attack_level": "32" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1622", - "range_level": "1", - "attack_level": "30" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1623", - "range_level": "1", - "attack_level": "30" - }, { "examine": "The vacuumed face of evil.", "slayer_task": "28", @@ -90956,101 +90868,6 @@ "range_level": "61", "attack_level": "105" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1626", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1627", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1628", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1629", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1630", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, { "examine": "A rocky slug.", "slayer_task": "69", @@ -165433,40 +165250,6 @@ "range_level": "1", "attack_level": "32" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1622", - "range_level": "1", - "attack_level": "30" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1623", - "range_level": "1", - "attack_level": "30" - }, { "examine": "The vacuumed face of evil.", "slayer_task": "28", @@ -165505,101 +165288,6 @@ "range_level": "61", "attack_level": "105" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1626", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1627", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1628", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1629", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1630", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, { "examine": "A rocky slug.", "slayer_task": "69", @@ -239726,40 +239414,6 @@ "range_level": "1", "attack_level": "32" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1622", - "range_level": "1", - "attack_level": "30" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "30", - "safespot": null, - "lifepoints": "27", - "strength_level": "1", - "id": "1623", - "range_level": "1", - "attack_level": "30" - }, { "examine": "The vacuumed face of evil.", "slayer_task": "28", @@ -239798,101 +239452,6 @@ "range_level": "61", "attack_level": "105" }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1626", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1627", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1628", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1629", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, - { - "examine": "It's one leg short!", - "melee_animation": "9471", - "range_animation": "9471", - "attack_speed": "5", - "magic_level": "75", - "defence_animation": "9473", - "magic_animation": "9471", - "death_animation": "9472", - "name": "Turoth", - "defence_level": "75", - "safespot": null, - "lifepoints": "79", - "strength_level": "85", - "id": "1630", - "clue_level": "2", - "range_level": "75", - "attack_level": "80" - }, { "examine": "A rocky slug.", "slayer_task": "69", From 295faf96ed787bdf67002128b74ef59f25c7a6f8 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 17:05:15 -0500 Subject: [PATCH 15/44] Revert odd changes to cache From 273d9b1f733030aef29ff9c815c43f329884645c Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 18:54:14 -0500 Subject: [PATCH 16/44] Working on it From 2c6992acd23131a3f83c3100fb33401b6db49ef7 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 19:03:48 -0500 Subject: [PATCH 17/44] Add libraries From db490a31963b0b3fb54720647dcb523d4135820e Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 19:08:16 -0500 Subject: [PATCH 18/44] Fixed all bugs From 6b12e8fab01b1a02d756cad49c56adf50b567c31 Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 19:15:08 -0500 Subject: [PATCH 19/44] Fixed windows and mac From 2bf74f4b60b98b858e616b472e1acde11935c20c Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 19:30:02 -0500 Subject: [PATCH 20/44] Tired of Windows. From 4e4f9d7b617bd927a88dc7a08c5cdd98ad3abb6f Mon Sep 17 00:00:00 2001 From: ceikry Date: Mon, 2 Aug 2021 21:06:48 -0500 Subject: [PATCH 21/44] Tired of Windows. From 35b57399ecc218af4e56db92a7810a4d8c882b83 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Tue, 3 Aug 2021 03:19:59 -0500 Subject: [PATCH 22/44] Fixed windows support From 341a5979ce67101df3e0db47f903dad6b7d895d8 Mon Sep 17 00:00:00 2001 From: ceikry Date: Tue, 3 Aug 2021 07:54:09 -0500 Subject: [PATCH 23/44] Did some more refactoring/renaming in SignLink From 4d17a14c6f11c2cd7962ef9ede1afb635880a0ee Mon Sep 17 00:00:00 2001 From: ceikry Date: Tue, 3 Aug 2021 08:17:51 -0500 Subject: [PATCH 24/44] A little more refactoring From de2efbff19ec3e1e2df4d92787211fe39e1c34ec Mon Sep 17 00:00:00 2001 From: ceikry Date: Tue, 3 Aug 2021 09:30:40 -0500 Subject: [PATCH 25/44] Pushed probably-more-correct mac libs From e17c15001303eb143f1be238fb5390cd3b1dd64b Mon Sep 17 00:00:00 2001 From: ceikry Date: Tue, 3 Aug 2021 11:03:52 -0500 Subject: [PATCH 26/44] Fixed jewellery-related bug --- .../java/core/game/interaction/inter/JewelleryInterface.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java b/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java index 251da81c8..781e54e9c 100644 --- a/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java +++ b/Server/src/main/java/core/game/interaction/inter/JewelleryInterface.java @@ -186,7 +186,7 @@ public final class JewelleryInterface extends ComponentPlugin { }); return true; } - if(!player.getSlayer().flags.isRingUnlocked()){ + if(!player.getSlayer().flags.isRingUnlocked() && data.equals(JewelleryItem.SLAYER_RING)){ player.sendMessages("You don't know how to make this. Talk to any Slayer master in order to learn the", "ability that creates Slayer rings."); return true; } From 396dd56dbe5cdb8d2b3f94a16e889244c7f89fb8 Mon Sep 17 00:00:00 2001 From: ceikry Date: Tue, 3 Aug 2021 11:50:55 -0500 Subject: [PATCH 27/44] Undo mac-related changes From 41596156a6372e60d11c8838a3ebd2885366634c Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 17:20:17 -0500 Subject: [PATCH 28/44] Try to reinforce non-nullability in xp interface callback --- .../global/worldevents/penguinhns/LarryHandler.kt | 10 +++++----- .../rs09/game/interaction/inter/ExperienceInterface.kt | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt index 8a5c30ec1..f337ab176 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt @@ -68,19 +68,19 @@ class LarryHandler(player: Player? = null) : DialoguePlugin(player){ return true } - override fun handleSelectionCallback(skill: Int, player: Player?) { - val points = player?.getAttribute("phns:points",0) + override fun handleSelectionCallback(skill: Int, player: Player) { + val points = player.getAttribute("phns:points",0) if(points == 0){ player.sendMessage("Sorry, but you have no points to redeem.") return } - val level = player?.skills?.getLevel(skill) ?: 0 + val level = player.skills.getLevel(skill) ?: 0 System.out.println("Level: $level") val expGained = points?.toDouble()?.times((level * 25)) System.out.print("exp: $expGained") - player?.skills?.addExperience(skill,expGained!!) - player?.setAttribute("/save:phns:points",0) + player.skills.addExperience(skill,expGained!!) + player.setAttribute("/save:phns:points",0) } override fun getIds(): IntArray { diff --git a/Server/src/main/kotlin/rs09/game/interaction/inter/ExperienceInterface.kt b/Server/src/main/kotlin/rs09/game/interaction/inter/ExperienceInterface.kt index ce9dd3038..666b376f1 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/inter/ExperienceInterface.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/inter/ExperienceInterface.kt @@ -70,7 +70,6 @@ class ExperienceInterface() : ComponentPlugin() { 46 -> Skills.WOODCUTTING 40 -> Skills.FLETCHING 51 -> Skills.CONSTRUCTION - 52 -> Skills.SUMMONING else -> Skills.SLAYER.also { SystemLogger.logWarn("EXP_INTERFACE: Invalid SKILL CHOICE BUTTON: $button") } } player.setAttribute("exp_interface:skill",skill) From f48e853b150b30ccadab1cb692ec89c9c7cd9b3e Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 17:29:13 -0500 Subject: [PATCH 29/44] fix potential bug with boostable stats --- .../game/content/global/worldevents/penguinhns/LarryHandler.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt index f337ab176..38382f1c6 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/LarryHandler.kt @@ -1,5 +1,6 @@ package rs09.game.content.global.worldevents.penguinhns +import api.ContentAPI import core.game.component.Component import core.game.content.dialogue.DialoguePlugin import core.game.content.dialogue.FacialExpression @@ -75,7 +76,7 @@ class LarryHandler(player: Player? = null) : DialoguePlugin(player){ return } - val level = player.skills.getLevel(skill) ?: 0 + val level = ContentAPI.getStatLevel(player, skill) System.out.println("Level: $level") val expGained = points?.toDouble()?.times((level * 25)) System.out.print("exp: $expGained") From 1347c70a711b901a97c4add48553d52806cf9ee3 Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 17:40:58 -0500 Subject: [PATCH 30/44] Fixed an exploit related to farming --- .../game/node/entity/skill/farming/CropHarvester.kt | 13 +++++++++++-- .../rs09/game/node/entity/skill/farming/Patch.kt | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt index 892394d6b..15f7331e3 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt @@ -16,6 +16,8 @@ import org.rs09.consts.Items @Initializable class CropHarvester : OptionHandler() { + val nonLives = arrayOf(PatchType.HERB, PatchType.CACTUS, PatchType.BELLADONNA, PatchType.HOPS, PatchType.ALLOTMENT,PatchType.EVIL_TURNIP) + val spadeAnim = Animation(830) override fun newInstance(arg: Any?): Plugin { @@ -67,8 +69,15 @@ class CropHarvester : OptionHandler() { delay = 2 player.inventory.add(Item(plantable.harvestItem,1)) player.skills.addExperience(Skills.FARMING,plantable.harvestXP) - patch.rollLivesDecrement(ContentAPI.getDynLevel(player, Skills.FARMING), requiredItem == Items.MAGIC_SECATEURS_7409) - return patch.cropLives <= 0 + if(patch.patch.type in nonLives){ + patch.harvestAmt-- + } else { + patch.rollLivesDecrement( + ContentAPI.getDynLevel(player, Skills.FARMING), + requiredItem == Items.MAGIC_SECATEURS_7409 + ) + } + return patch.cropLives <= 0 || patch.harvestAmt <= 0 } }) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt index e178d8ae8..070e38617 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt @@ -16,6 +16,10 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl var cropLives = 3 fun setNewHarvestAmount() { + harvestAmt = when (plantable) { + Plantable.LIMPWURT_SEED, Plantable.WOAD_SEED -> 3 + else -> 1 + } cropLives = 3 } From 15ee9b01cc561afd650fb0396f7144e05552f20b Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 22:17:40 -0500 Subject: [PATCH 31/44] Make penguin spying infallible --- .../penguinhns/PenguinSpyingHandler.kt | 51 +++++++------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinSpyingHandler.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinSpyingHandler.kt index cf90e6852..6d96d95ce 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinSpyingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinSpyingHandler.kt @@ -11,13 +11,27 @@ import core.game.world.update.flag.context.Animation import core.plugin.Plugin import core.game.content.quest.PluginInteraction import core.game.content.quest.PluginInteractionManager +import rs09.game.interaction.InteractionListener -class PenguinSpyingHandler : PluginInteraction(8107,8108,8104,8105,8109,8110){ +class PenguinSpyingHandler : InteractionListener(){ - class SpyPulse(val player: Player) : Pulse() { + override fun defineListeners() { + on(PENGUINS, NPC, "spy-on"){player, node -> + val npc = node.asNpc() + if(PenguinManager.hasTagged(player, npc.location)){ + player.sendMessage("You've already tagged this penguin.") + } else { + GameWorld.submit(SpyPulse(player, npc)) + } + return@on true + } + } + + val PENGUINS = intArrayOf(8104,8105,8107,8108,8109,8110) + + class SpyPulse(val player: Player, val npc: NPC) : Pulse() { var stage = 0 val curPoints = player.getAttribute("phns:points",0) - val weeklyPoints = player.getAttribute("phns:weekly",0) val ANIMATION = Animation(10355) @@ -26,6 +40,7 @@ class PenguinSpyingHandler : PluginInteraction(8107,8108,8104,8105,8109,8110){ 0 -> player.lock().also { player.animator.animate(ANIMATION) } 1 -> player.sendMessage("You manage to spy on the penguin.").also { player.setAttribute("/save:phns:points",curPoints + 1) + PenguinManager.registerTag(player, npc.location) player.unlock() } 2 -> return true @@ -33,34 +48,4 @@ class PenguinSpyingHandler : PluginInteraction(8107,8108,8104,8105,8109,8110){ return false } } - - override fun handle(player: Player?, npc: NPC?, option: Option?): Boolean { - class movePulse : MovementPulse(player,DestinationFlag.ENTITY.getDestination(player,npc)){ - override fun pulse(): Boolean { - player.let { player?.face(npc);GameWorld.submit(SpyPulse(player!!)) } - return true - } - } - if(option?.name?.toLowerCase()?.equals("spy-on")!!){ - player ?: return false - if(PenguinManager.hasTagged(player, npc!!.location)){ - player.sendMessage("You've already tagged this penguin.") - } else { - GameWorld.submit(movePulse()) - PenguinManager.registerTag(player, npc!!.location) - } - return true - } - return false - } - - override fun fireEvent(identifier: String?, vararg args: Any?): Any { - return Unit - } - - override fun newInstance(arg: Any?): Plugin { - PluginInteractionManager.register(this,PluginInteractionManager.InteractionType.NPC) - return this - } - } \ No newline at end of file From c12cbc0f91829efc9b1b7710c9c2eaadf59b8b32 Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 22:55:57 -0500 Subject: [PATCH 32/44] Make penguin spying infallible --- .../rs09/game/node/entity/skill/farming/CropHarvester.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt index 15f7331e3..0589276c5 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt @@ -16,7 +16,7 @@ import org.rs09.consts.Items @Initializable class CropHarvester : OptionHandler() { - val nonLives = arrayOf(PatchType.HERB, PatchType.CACTUS, PatchType.BELLADONNA, PatchType.HOPS, PatchType.ALLOTMENT,PatchType.EVIL_TURNIP) + val livesBased = arrayOf(PatchType.HERB, PatchType.CACTUS, PatchType.BELLADONNA, PatchType.HOPS, PatchType.ALLOTMENT,PatchType.EVIL_TURNIP) val spadeAnim = Animation(830) @@ -69,13 +69,13 @@ class CropHarvester : OptionHandler() { delay = 2 player.inventory.add(Item(plantable.harvestItem,1)) player.skills.addExperience(Skills.FARMING,plantable.harvestXP) - if(patch.patch.type in nonLives){ - patch.harvestAmt-- - } else { + if(patch.patch.type in livesBased){ patch.rollLivesDecrement( ContentAPI.getDynLevel(player, Skills.FARMING), requiredItem == Items.MAGIC_SECATEURS_7409 ) + } else { + patch.harvestAmt-- } return patch.cropLives <= 0 || patch.harvestAmt <= 0 } From 21c5f77a49cfb86939d3104d64920eea992c3d40 Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 22:57:14 -0500 Subject: [PATCH 33/44] Slight farming bugfix --- .../rs09/game/node/entity/skill/farming/CropHarvester.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt index 0589276c5..c887ed0f6 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/CropHarvester.kt @@ -76,6 +76,9 @@ class CropHarvester : OptionHandler() { ) } else { patch.harvestAmt-- + if(patch.harvestAmt <= 0){ + patch.clear() + } } return patch.cropLives <= 0 || patch.harvestAmt <= 0 } From 75c0a842259c96d7a399723e2e7ec52f29a2ccf3 Mon Sep 17 00:00:00 2001 From: ceikry Date: Wed, 4 Aug 2021 22:59:34 -0500 Subject: [PATCH 34/44] E --- .../content/global/worldevents/penguinhns/PenguinHNSEvent.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinHNSEvent.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinHNSEvent.kt index e28aa1c3d..38f68a8da 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinHNSEvent.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/penguinhns/PenguinHNSEvent.kt @@ -25,7 +25,6 @@ class PenguinHNSEvent : WorldEvent("penguin-hns"){ plugins = PluginSet( LarryHandler(), NotebookHandler(), - PenguinSpyingHandler() ) super.initialize() fireEvent() From 31f0e469db70f731b8d6642601786a541192e869 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 07:31:07 -0500 Subject: [PATCH 35/44] Fixed bug with osman's dialogue --- .../interaction/object/sorceress/GardenObjectsPlugin.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Server/src/main/java/core/game/interaction/object/sorceress/GardenObjectsPlugin.kt b/Server/src/main/java/core/game/interaction/object/sorceress/GardenObjectsPlugin.kt index fbd14fac5..b76395aed 100644 --- a/Server/src/main/java/core/game/interaction/object/sorceress/GardenObjectsPlugin.kt +++ b/Server/src/main/java/core/game/interaction/object/sorceress/GardenObjectsPlugin.kt @@ -478,6 +478,7 @@ class GardenObjectsPlugin : InteractionListener() { * @author SonicForce41 * @date 31/12/2013 */ + @Initializable class OsmanDialogue : DialoguePlugin { /** * Represents the quest instance. @@ -538,10 +539,7 @@ class GardenObjectsPlugin : InteractionListener() { 20 -> { if (!player.getInventory().containsItem(KEY_PRINT)) { interpreter.sendDialogues(player, null, "Can you tell me what I need to get?") - } else if (!player.getInventory().containsItem(BRONZE_BAR) && player.getInventory().containsItem( - KEY_PRINT - ) - ) { + } else if (!player.getInventory().containsItem(BRONZE_BAR) && player.getInventory().containsItem(KEY_PRINT)) { interpreter.sendDialogues( npc, null, From 25e9d4998c7ba2c631f0d4a3d166763b8a0d78d5 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 09:20:37 -0500 Subject: [PATCH 36/44] Update README --- README.md | 70 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 3fc1787f2..b9e2403b2 100644 --- a/README.md +++ b/README.md @@ -7,26 +7,24 @@

An open source MMORPG emulation server

-

Play the live server »

+

Play the live server »



- Community Hosted Server + Community Hosted Server · Discord Invite - · Report Bug - · - Bug Board + · Report Bug

-

NOTE: Do not report issues if you are running your own server. Chances are, the fault lies in your misconfiguration of the server or the issue has already long been fixed on live. Essentially: Your server. Your issues. We have enough to worry about with our own server.

-

ATTENTION: Starting October 5th, 2020 the development team will no longer be providing support for setting up your own server. Do not ping or private message Developers asking how to build the project. This in-depth guide will be continually updated if the building process changes. We are focusing all of our efforts on the development of features and bugfixes for the live server.

+

NOTE: Bug reports and support are only accepted by/offered to players of our live hosted server. We will not provide support to those running their own copies.

## Table of Contents * [Live Server Information](#live-server-information) -* [About the Project](#about-the-project) +* [History of this Codebase](#history-of-this-codebase) +* [Our Core Values](#our-core-values) * [Contributing](#contributing) * [Contributing without Building](#contributing-without-building) * [Video Setup Tutorial](#video-setup-tutorial) @@ -42,49 +40,57 @@ ## Live Server Information -Did you know that the 2009Scape Development Team hosts the main branch of this repo that you can connect to and play? Come join a growing community of people that love to grind out skills, quest, and hangout together. A download link for the launcher can be found here. Connecting to the live server is also one of the easiest ways to identify bugs/typos/missing features. Identifying these issues help developers, whether already on the project, or are even brand new to the project, fix bugs and issues in an expedited rate. +Did you know that the 2009Scape Development Team hosts the main branch of this repo that you can connect to and play? Come join a growing community of people that love to grind out skills, quest, and hangout together. A download link for the launcher can be found here. Connecting to the live server is also one of the easiest ways to identify bugs/typos/missing features. Identifying these issues help developers, whether already on the project, or are even brand new to the project, fix bugs and issues in an expedited rate. -## About The Project +## History of this Codebase The 2009Scape you see today has gone through a magnitude of changes. Originally starting its life as Arios498, this server saw a lot of people playing it daily, unfortunately, it was for profit and closed source. It was later upgraded to Arios530, targeting the build 530 of runescape with content in and around January 1st, 2009. Development came to a halt when a developer of the closed source project released the source code. The original developers of this server went on to create Kratos 530 back in 2015. -This project was started out of love for the 530 revision. A small group of developers spent hundreds of hours improving on the existing source that was left to the curb. Over the past year, this project has seen many developers coming and going, fixing bugs that they find either through their own server, or bugs that they find in the live game that is currently hosted. We do not accept donations of any kind. The smiles and wonderful compliments are more than enough to keep us going! Content and bugfixes are always number one on our list, and we try our best to answer any questions that you may have, provided you have read through this readme and frequently asked questions on the discord. +This project was started out of love for the 530 revision. A small group of developers spent thousands of hours improving on the existing source that was left to the curb. Over the past year, this project has seen many developers coming and going, fixing bugs that they find either through their own server, or bugs that they find in the live game that is currently hosted. We do not accept donations of any kind. The smiles and wonderful compliments are more than enough to keep us going! Content and bugfixes are always number one on our list, and we try our best to answer any questions that you may have, provided you have read through this readme and frequently asked questions on the discord. + +## Our Core Values + +In the current climate of RSPS in general, we believe it's important to wear our core values on our sleeves and defend them with everything we have! Below are what we hold as our core, most important values: + +* **We do NOT believe in profiting off RSPS.** To many of us here at the 2009scape team, what we care about most is preserving the wonderful work of the Gower brothers in the most true-to-spirit manner possible. We do NOT do this to make a profit, and in fact **we outright refuse donations.** This is a labor of love and passion for everyone involved, a love for real RS2! This is perhaps the single most central value we have. If you want to "donate" to us, do so with your time and your dedication. That is what we desire most. + + +* **Authenticity is central to the work**. As a remake, one of the most important things to us is being true to the Gower spirit. What the Gowers brought to us in our childhood is what we are driven to preserve for the remainder of the world. + + +* **Open Source Is Crucial**. We believe open source remakes to be crucial to preserving what we loved in our childhood, and we believe for-profit and/or closed-source servers are destined to flounder out and fail. + + +* **Be Welcoming**. One of our most important goals is to provide a community of friendly and caring people that get along and love to enjoy the game with eachother. For this reason, we do tend to be very strict when it comes to toxicity. We care about quality a whole lot more than quantity! ## Contributing -

Note: A live server that the 2009Scape development team runs is the best way to find and report bugs! Any changes made should be pushed to the Development Branch, Any changes that are pushed to the main branch will be denied, and you will have to submit another PR request. We are currently in the process of rewriting the codebase in Kotlin. Any new commits should be written in Kotlin Only.

+

Note: A live server that the 2009Scape development team runs is the best way to find and report bugs! We are currently in the process of rewriting the codebase in Kotlin. Any new commits should be written in Kotlin Only.

More information on Kotlin can be found here.

-We are always looking for fellow helpers and developers to help preserve history and contribute towards making the most complete emulation server! The beautiful part is you don't even have to download and build the project in order to contribute! Want to make simple edits to NPCs, Items, Music, Shops, Typos? Follow the [Contributing-without-Building](#contributing-without-building) guide below! +There are many ways everyone can contribute! From the most seasoned programmers to those who do not have the most remote clue how code works! Below are some things that can always use some love from the community. -## Contributing without Building - -First create a Github account if you do not have one already. Editing the repository directly is one of the easiest ways to contribute to the project. You will start off in the master/main branch. Switch to the **"Development Branch"** by clicking on the drop down menu which is on the left hand side where it says "Branches" and "Tags". Then navigate to the file you wish to change, for example, All definitions are located in **"Server/data/configs/"**. If you were to edit NPCSpawns.json, you would select NPCSpawns.json, and on the right hand side of the window there will be a screen icon, pencil icon, and trashcan icon. Click on the pencil icon to make changes. When you are finished with your changes, ensure you are in **development** by looking at the branch in the top left. Scroll down until you see "propose changes", and fill out the two info bars at the bottom to describe what you changed/fixed. -
-**More information on repository file editing can be found here.** -
-
-**Editing files that are too large for Github in-browser editing** -
-First follow the [Github-Setup](#github-setup). After you have forked over your copy of the repo, swap over to the **Development branch**, and then download the file that you wish to edit. JSON format can be edited in any notepad program, however it is recommended to use either Atom or Notepad++. After you are finished editing your file, navigate back to the file you wish to replace on your **Development Branch**. Select it and delete it off your branch. Then go back and on the right hand side click on "Add files" and then "Upload new files". Upload the file you are done editing and then submit a Pull request (PR). To submit a PR navigate to "Pull requests" and then click on "New pull request". On the top of the page you should see "Comparing changes". The left set of options is what you will be pushing to and the right side is where you are pushing from. On the right side, put your repo and compare to **Development**, On the left hand side put the repo as 2009scape/2009scape base: **Development**. If at anytime it tries to pull/push into its own repository, click "Compare across forks" and you should be able to select where you want to push to and from. -
-**More information about submitting PR's can be found here.** +* Wiki Editors: Did you know we have a wiki? Well it's always in need of people to fill it out and stay on top of it. Editing the wiki is one of the easiest ways you can contribute to 2009scape! If you're an active player and have the will, there's so much you could be helping out with over at the wiki. Click here to go to the wiki. +* JSON editors: Did you know that the vast majority of our drop tables, stats, examines, item info, npc info, etc is all stored in a very easy-to-modify format called JSON? This is something almost anyone can help with, especially with the tool made by Ceikry to make it simple and streamlined. If you want to know what can be done to help here, get in touch in the development channel in the discord! **JSON editors are always in need and always appreciated!!**. -## Getting Started +* Auditors: As a remake, authenticity is central to our core values! We could always use someone to go through the game and create large lists of simple tasks that can be done to bring us closer to the authentic 2009 game! The preferred way to do this is one-area-at-a-time. If you want to see an example of some audits we've done in the past, take a look here. + + +* Content Developers: As a remake, we have massive amounts of content that need to be implemented or corrected. If you know how to program or are willing to learn, this is where you could be extremely helpful! We need everything from quests to dialogue to minigames to skills that still need to be corrected or implemented, and this is perhaps one of the most valuable ways someone could help out the project! If you are interested in developing content, reach out in the development channel of the Discord. + +## Content Developers: Setting Up the Project. ### Github Setup

Note: This allows you to commit changes to the main repo (with approval)! Also, always stay up to date with the most recent updates by pulling into your copy when 2009Scape updates!

-1. Create a github account if you haven't done so already +1. Create a gitlab account if you haven't done so already -2. Go to the 2009Scape Github Page +3. Click "Fork" in the top right hand side of our gitlab page. -3. Click "Fork" in the top right hand side of Github - -**If at anytime you have an issue with Github please refer to the** Github help center. +**If at anytime you have an issue with gitlab please refer to the** Gitlab help center. ### Prerequisites @@ -92,7 +98,7 @@ First follow the [Github-Setup](#github-setup). After you have forked over your

Note: It is required for a developer submitting a PR to use Intellij IDEA as your integrated development environment.

* Intellij IDEA -* Java SE Development Kit Version 1.8 +* Java SE Development Kit Version 1.8/OpenJDK 1.8 (preferred) * Gradle (optional - Installs with Intellij on project build) * Xampp From fbf797bac9d640056e0e86f6b38c2280adcff515 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 09:21:25 -0500 Subject: [PATCH 37/44] Update README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index b9e2403b2..d6eb014c4 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,7 @@ * [Live Server Information](#live-server-information) * [History of this Codebase](#history-of-this-codebase) * [Our Core Values](#our-core-values) -* [Contributing](#contributing) -* [Contributing without Building](#contributing-without-building) +* [Setup for Content Developers](#content-developers-setting-up-the-project) * [Video Setup Tutorial](#video-setup-tutorial) * [Getting Started](#getting-started) * [Github Setup](#github-setup) From c9160ccf0328fe6fa1d64d87c7347518a88a1e1d Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 09:22:07 -0500 Subject: [PATCH 38/44] Update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6eb014c4..c5c7dbe48 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ * [Live Server Information](#live-server-information) * [History of this Codebase](#history-of-this-codebase) * [Our Core Values](#our-core-values) -* [Setup for Content Developers](#content-developers-setting-up-the-project) +* [Contributing](#contributing) * [Video Setup Tutorial](#video-setup-tutorial) -* [Getting Started](#getting-started) +* [Setup for Content Developers](#content-developers-setting-up-the-project) * [Github Setup](#github-setup) * [Prerequisites](#prerequisites) * [Prereq Installation](#prereq-installation) From 88cfbc8f32e88a8a854c0d6dd253867bae2eb94a Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 09:26:26 -0500 Subject: [PATCH 39/44] Update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c5c7dbe48..d34988b75 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ * [Github Setup](#github-setup) * [Prerequisites](#prerequisites) * [Prereq Installation](#prereq-installation) -* [Project Setup](#project-setup) -* [Running the project](#running-the-project) + * [Project Setup](#project-setup) + * [Running the project](#running-the-project) * [License](#license) * [Contact](#contact) From c2f3aba3ef5fc4b58da8d3370e99db92640ea064 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 09:35:28 -0500 Subject: [PATCH 40/44] Update README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d34988b75..94ef0654c 100644 --- a/README.md +++ b/README.md @@ -69,16 +69,16 @@ In the current climate of RSPS in general, we believe it's important to wear our There are many ways everyone can contribute! From the most seasoned programmers to those who do not have the most remote clue how code works! Below are some things that can always use some love from the community. -* Wiki Editors: Did you know we have a wiki? Well it's always in need of people to fill it out and stay on top of it. Editing the wiki is one of the easiest ways you can contribute to 2009scape! If you're an active player and have the will, there's so much you could be helping out with over at the wiki. Click here to go to the wiki. +* **Wiki Editors**: Did you know we have a wiki? Well it's always in need of people to fill it out and stay on top of it. Editing the wiki is one of the easiest ways you can contribute to 2009scape! If you're an active player and have the will, there's so much you could be helping out with over at the wiki. Click here to go to the wiki. -* JSON editors: Did you know that the vast majority of our drop tables, stats, examines, item info, npc info, etc is all stored in a very easy-to-modify format called JSON? This is something almost anyone can help with, especially with the tool made by Ceikry to make it simple and streamlined. If you want to know what can be done to help here, get in touch in the development channel in the discord! **JSON editors are always in need and always appreciated!!**. +* **JSON editors**: Did you know that the vast majority of our drop tables, stats, examines, item info, npc info, etc is all stored in a very easy-to-modify format called JSON? This is something almost anyone can help with, especially with the tool made by Ceikry to make it simple and streamlined. If you want to know what can be done to help here, get in touch in the development channel in the discord! **JSON editors are always in need and always appreciated!!**. -* Auditors: As a remake, authenticity is central to our core values! We could always use someone to go through the game and create large lists of simple tasks that can be done to bring us closer to the authentic 2009 game! The preferred way to do this is one-area-at-a-time. If you want to see an example of some audits we've done in the past, take a look here. +* **Auditors**: As a remake, authenticity is central to our core values! We could always use someone to go through the game and create large lists of simple tasks that can be done to bring us closer to the authentic 2009 game! The preferred way to do this is one-area-at-a-time. If you want to see an example of some audits we've done in the past, take a look here. -* Content Developers: As a remake, we have massive amounts of content that need to be implemented or corrected. If you know how to program or are willing to learn, this is where you could be extremely helpful! We need everything from quests to dialogue to minigames to skills that still need to be corrected or implemented, and this is perhaps one of the most valuable ways someone could help out the project! If you are interested in developing content, reach out in the development channel of the Discord. +* **Content Developers**: As a remake, we have massive amounts of content that need to be implemented or corrected. If you know how to program or are willing to learn, this is where you could be extremely helpful! We need everything from quests to dialogue to minigames to skills that still need to be corrected or implemented, and this is perhaps one of the most valuable ways someone could help out the project! If you are interested in developing content, reach out in the development channel of the Discord. ## Content Developers: Setting Up the Project. ### Github Setup From 1f8260a1fe32f4a21fed99beb4ee7f4f69de1456 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 15:09:36 -0500 Subject: [PATCH 41/44] Updated client with new config settings From c5e2e0bcc67eccb4a71e8ceb8fa0ffdea57d60f0 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 15:27:03 -0500 Subject: [PATCH 42/44] woops teehee From d71fd8062fb1457e4b963dabe18823c4a465ee80 Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 16:10:44 -0500 Subject: [PATCH 43/44] woops teehee From d6714d7087e800bd9624f52af4e0f2a7870af0ef Mon Sep 17 00:00:00 2001 From: ceikry Date: Thu, 5 Aug 2021 16:36:32 -0500 Subject: [PATCH 44/44] Redundant safety checks