Merged updates from 2009scape

This commit is contained in:
randy 2025-02-20 19:43:05 -07:00
commit 680a08ea98
874 changed files with 38212 additions and 9941 deletions

View file

@ -149,4 +149,4 @@ These credits can be spent in the 2009Scape Reward Shop. It's important to be cl
Testers are not the only people who can gain credits - other ways of earning credits can be found on [the 2009Scape website](https://2009scape.org/site/game_guide/credits.html).
Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded.
Please be patient! The Credit system is not fully complete yet, so it will take a long time for credits to be awarded.

1
Server/.gitignore vendored
View file

@ -2,6 +2,7 @@ bin/**
out/**
data/logs/**
data/profile/**
data/playerstats/**
.idea/**
/bin
.DS_Store**

BIN
Server/data/cache/main_file_cache.dat2 (Stored with Git LFS) vendored

Binary file not shown.

BIN
Server/data/cache/main_file_cache.idx255 (Stored with Git LFS) vendored

Binary file not shown.

BIN
Server/data/cache/main_file_cache.idx5 (Stored with Git LFS) vendored

Binary file not shown.

View file

@ -301,7 +301,7 @@
},
{
"id": "2025",
"replaceId": "1534",
"replaceId": "2026",
"fence": "false",
"metal": "false"
},
@ -925,7 +925,7 @@
},
{
"id": "3747",
"replaceId": "1534",
"replaceId": "3748",
"fence": "false",
"metal": "false"
},
@ -943,7 +943,7 @@
},
{
"id": "4148",
"replaceId": "4248",
"replaceId": "4246",
"fence": "false",
"metal": "false"
},
@ -1759,7 +1759,7 @@
},
{
"id": "14245",
"replaceId": "14248",
"replaceId": "14246",
"fence": "true",
"metal": "false"
},
@ -1984,16 +1984,14 @@
"replaceId": "28518",
"fence": "false",
"metal": "true",
"autowalk": "true",
"questRequirement": "Icthlarin's Little Helper"
"autowalk": "true"
},
{
"id": "28514",
"replaceId": "28518",
"fence": "false",
"metal": "true",
"autowalk": "true",
"questRequirement": "Icthlarin's Little Helper"
"autowalk": "true"
},
{
"id": "21065",

View file

@ -3262,7 +3262,7 @@
}
],
"charm": [],
"ids": "73,74,75,419,420,421,422,423,424,1826,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
"ids": "73,74,75,419,420,421,422,423,424,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
"description": "",
"main": [
{
@ -5858,205 +5858,165 @@
"charm": [
{
"minAmount": "1",
"weight": "100.0",
"id": "12158",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12159",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12160",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12163",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5600.0",
"weight": "1000.0",
"id": "0",
"maxAmount": "1"
}
],
"tertiary": [
{
"minAmount": "1",
"weight": "4986.5",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "12.5",
"id": "10976",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.0",
"id": "10977",
"maxAmount": "1"
}
],
"ids": "114",
"description": "",
"main": [
{
"minAmount": "1",
"weight": "50.0",
"id": "7844",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "10977",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "10976",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5323",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5298",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5281",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5301",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5280",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5294",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5297",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5104",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5100",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5106",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "12176",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5293",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5296",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5311",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5105",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5292",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5295",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5303",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5302",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5321",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5299",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "31",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "3.0",
"weight": "39.0625",
"id": "6666",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "3.0",
"weight": "78.125",
"id": "6665",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "13.0",
"id": "14422",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "13.0",
"id": "14430",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "345",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "327",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "371",
"maxAmount": "1"
},
{
"minAmount": "2",
"weight": "156.25",
"id": "372",
"maxAmount": "5"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "359",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "360",
"maxAmount": "3"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "383",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "349",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "331",
"maxAmount": "1"
},
{
"minAmount": "5",
"weight": "156.25",
"id": "313",
"maxAmount": "15"
},
{
"minAmount": "1",
"weight": "156.25",
"id": "1511",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "1383",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "78.125",
"id": "407",
"maxAmount": "1"
},
{
"minAmount": "4",
"weight": "78.125",
"id": "402",
"maxAmount": "8"
},
{
"minAmount": "5",
"weight": "4.0",
"id": "555",
"maxAmount": "18"
},
{
"minAmount": "3",
"weight": "78.125",
"id": "6664",
"maxAmount": "6"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "401",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "39.0625",
"id": "6667",
"maxAmount": "1"
}
]
},
@ -11426,47 +11386,11 @@
"weight": "100.0",
"id": "526",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "1506",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "6065",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "6067",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "6069",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "6068",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "6070",
"maxAmount": "1"
}
],
"charm": [],
"ids": "347,348,357,369,370,371,372,717,718,719,2349,2350,2351,2373,2374,2784,3216",
"description": "",
"ids": "370,357,348,369,347,371",
"description": "all combat mourners",
"main": []
},
{
@ -18161,7 +18085,7 @@
"maxAmount": "1"
}
],
"ids": "1183,1184,1201,2359,2360,2361,2362,7438,7439,7440,7441",
"ids": "1183,1184,1201,2359,2360,2361,2362,2373,7438,7439,7440,7441",
"description": "",
"main": [
{
@ -28545,60 +28469,10 @@
"maxAmount": "1"
}
],
"charm": [
{
"minAmount": "1",
"weight": "85.8093",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "10.9113",
"id": "12158",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.6775",
"id": "12159",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.6019",
"id": "12160",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "0.0",
"id": "12163",
"maxAmount": "1"
}
],
"ids": "2044,2045,2046,2047,2048,2049,2051,2052,2053,2054,2055",
"charm": [],
"ids": "2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057",
"description": "",
"main": [
{
"minAmount": "1",
"weight": "1.0",
"id": "1",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "124.0",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "3.0",
"id": "7848",
"maxAmount": "1"
}
]
"main": []
},
{
"default": [
@ -39929,7 +39803,20 @@
]
},
{
"default": [],
"default": [
{
"minAmount": "1",
"weight": "1.0",
"id": "532",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.0",
"id": "9080",
"maxAmount": "1"
}
],
"charm": [
{
"minAmount": "1",
@ -58901,6 +58788,26 @@
"description": "Ram",
"main": []
},
{
"default": [
{
"minAmount": "1",
"weight": "1.0",
"id": "526",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.0",
"id": "1583",
"maxAmount": "1"
}
],
"charm": [],
"ids": "6108",
"description": "",
"main": []
},
{
"default": [],
"charm": [],

View file

@ -233,7 +233,7 @@
},
{
"item_id": "946",
"loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-"
"loc_data": "{1,2903,3148,0,80}-{1,3205,3212,0,80}-{1,3224,3202,0,80}-{1,3218,3416,1,90}-{1,2820,3450,0,90}-{1,3106,3956,0,60}-{1,2566,9526,0,30}-{1,3215,9625,0,80}-{1,3218,9887,0,33}-{1,2700,3407,0,100}-"
},
{
"item_id": "952",
@ -241,7 +241,7 @@
},
{
"item_id": "954",
"loc_data": "{1,2094,3152,0,150}-"
"loc_data": "{1,2094,3152,0,150}-{1,2785,3279,0,150}-{1,2786,3287,0,150}-{1,2786,3286,0,150}-"
},
{
"item_id": "960",
@ -339,6 +339,14 @@
"item_id": "1422",
"loc_data": "{1,3320,3137,0,150}-"
},
{
"item_id": "1467",
"loc_data": "{1,2784,3289,0,0}-"
},
{
"item_id": "1469",
"loc_data": "{1,2766,3277,0,100}-{1,2766,3289,0,100}-"
},
{
"item_id": "1510",
"loc_data": "{1,2576,3334,0,100}-"
@ -619,6 +627,10 @@
"item_id": "4707",
"loc_data": "{1,3571,3312,0,40}-"
},
{
"item_id": "4838",
"loc_data": "{1,2593,3103,1,40}-"
},
{
"item_id": "5008",
"loc_data": "{1,3230,9609,0,44}-"

View file

@ -95,6 +95,30 @@
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "68",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "69",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "70",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "71",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "74",
"interfaceType": "4",
@ -365,6 +389,30 @@
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "245",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "246",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "247",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "248",
"interfaceType": "4",
"walkable": "false",
"tabIndex": "-1"
},
{
"id": "256",
"interfaceType": "8",

View file

@ -5719,7 +5719,7 @@
},
{
"shop_price": "35",
"examine": "Allows you to rest in the luxurious Paramayer[sic] Inn.",
"examine": "Allows you to rest in the luxurious Paramayer Inn.",
"durability": null,
"name": "Paramaya ticket",
"archery_ticket_price": "0",
@ -5727,7 +5727,7 @@
},
{
"shop_price": "35",
"examine": "Allows you to rest in the luxurious Paramayer[sic] Inn.",
"examine": "Allows you to rest in the luxurious Paramayer Inn.",
"durability": null,
"name": "Paramaya ticket",
"archery_ticket_price": "0",
@ -16309,6 +16309,7 @@
"examine": "Maybe I should read this...",
"durability": null,
"name": "A magic scroll",
"tradeable": "false",
"archery_ticket_price": "0",
"id": "1505"
},
@ -16324,7 +16325,7 @@
"equipment_slot": "0"
},
{
"examine": "Quite a small key (Plague City).",
"examine": "Quite a small key.",
"durability": null,
"name": "A small key",
"archery_ticket_price": "0",
@ -16869,7 +16870,7 @@
"id": "1583"
},
{
"examine": "Apparently my name is Hartigan",
"examine": "Apparently my name is Hartigen.",
"durability": null,
"name": "Id papers",
"tradeable": "false",
@ -20559,7 +20560,7 @@
},
{
"ge_buy_limit": "1000",
"examine": "On ground: Cabbage... yuck!In inventory: Yuck, I don't like cabbage.",
"examine": "Yuck, I don't like cabbage.",
"grand_exchange_price": "41",
"durability": null,
"name": "Cabbage",
@ -20578,7 +20579,7 @@
"id": "1966"
},
{
"examine": "On ground: Cabbage... yuck!In inventory: Yuck, I don't like cabbage.",
"examine": "Yuck, a cabbage from Draynor Manor. I don't like cabbage.",
"grand_exchange_price": "55",
"durability": null,
"name": "Cabbage",
@ -33982,7 +33983,7 @@
{
"requirements": "{1,40}",
"ge_buy_limit": "2",
"examine": "Rune platebody with complete gold trim & plating.",
"examine": "Rune platebody with complete gold trim & plating.",
"durability": null,
"weight": "10",
"absorb": "3,0,6",
@ -42660,7 +42661,7 @@
"id": "4619"
},
{
"examine": "It looks horrible.On ground: Not good for eating.",
"examine": "It looks horrible.",
"durability": null,
"name": "Black mushroom",
"weight": "1",
@ -42749,7 +42750,7 @@
"equipment_slot": "12"
},
{
"examine": "Frank's shiny silver coated pot.",
"examine": "A silver pot made by Ruantun.",
"durability": null,
"name": "Silver pot",
"tradeable": "false",
@ -42766,7 +42767,7 @@
"id": "4659"
},
{
"examine": "Frank's shiny silver coated pot.",
"examine": "A silver pot made by Ruantun filled with your blood.",
"durability": null,
"name": "Silver pot",
"tradeable": "false",
@ -42775,7 +42776,7 @@
"id": "4660"
},
{
"examine": "A silver pot made by Ruantun and blessed on Entrana.",
"examine": "A blessed silver pot made by Ruantun filled with your blood.",
"durability": null,
"name": "Blessed pot",
"weight": "2",
@ -42783,7 +42784,7 @@
"id": "4661"
},
{
"examine": "Frank's shiny silver coated pot.",
"examine": "A silver pot made by Ruantun filled with blood and garlic.",
"durability": null,
"name": "Silver pot",
"tradeable": "false",
@ -42792,7 +42793,7 @@
"id": "4662"
},
{
"examine": "A silver pot made by Ruantun and blessed on Entrana.",
"examine": "A blessed silver pot filled with blood and garlic.",
"durability": null,
"name": "Blessed pot",
"weight": "2",
@ -42800,7 +42801,7 @@
"id": "4663"
},
{
"examine": "Frank's shiny silver coated pot.",
"examine": "A silver pot made by Ruantun filled with blood and spices.",
"durability": null,
"name": "Silver pot",
"tradeable": "false",
@ -42809,7 +42810,7 @@
"id": "4664"
},
{
"examine": "A silver pot made by Ruantun and blessed on Entrana.",
"examine": "A blessed silver pot filled with blood and spices.",
"durability": null,
"name": "Blessed pot",
"weight": "2",
@ -42817,7 +42818,7 @@
"id": "4665"
},
{
"examine": "Frank's shiny silver coated pot.",
"examine": "A silver pot made by Ruantun filled with blood, garlic and spices.",
"durability": null,
"name": "Silver pot",
"tradeable": "false",
@ -42826,7 +42827,7 @@
"id": "4666"
},
{
"examine": "A silver pot made by Ruantun and blessed on Entrana.",
"examine": "A blessed silver pot filled with blood, garlic and spices.",
"durability": null,
"name": "Blessed pot",
"weight": "2",
@ -43126,13 +43127,13 @@
"id": "4702"
},
{
"shop_price": "975000",
"examine": "A magic stone to make high-level furniture.",
"grand_exchange_price": "977755",
"shop_price": "1",
"examine": "Doesn't look very special.",
"grand_exchange_price": "0",
"durability": null,
"name": "Magic stone",
"tradeable": "true",
"weight": "1",
"tradeable": "false",
"weight": "2.267",
"archery_ticket_price": "0",
"id": "4703"
},
@ -48987,7 +48988,7 @@
"id": "5419"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There is one potato in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(1)",
@ -49004,7 +49005,7 @@
"id": "5421"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are two potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(2)",
@ -49021,7 +49022,7 @@
"id": "5423"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are three potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(3)",
@ -49038,7 +49039,7 @@
"id": "5425"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are four potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(4)",
@ -49055,7 +49056,7 @@
"id": "5427"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are five potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(5)",
@ -49072,7 +49073,7 @@
"id": "5429"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are six potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(6)",
@ -49089,7 +49090,7 @@
"id": "5431"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are seven potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(7)",
@ -49106,7 +49107,7 @@
"id": "5433"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are eight potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(8)",
@ -49123,7 +49124,7 @@
"id": "5435"
},
{
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are nine potatoes in this sack.",
"grand_exchange_price": "1276",
"durability": null,
"name": "Potatoes(9)",
@ -49141,7 +49142,7 @@
},
{
"ge_buy_limit": "1000",
"examine": "There are <number of potatoes> in this sack.",
"examine": "There are ten potatoes in this sack.",
"grand_exchange_price": "1052",
"durability": null,
"name": "Potatoes(10)",
@ -49333,7 +49334,7 @@
"id": "5459"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There is one cabbage in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(1)",
@ -49349,7 +49350,7 @@
"id": "5461"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are two cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(2)",
@ -49365,7 +49366,7 @@
"id": "5463"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are three cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(3)",
@ -49381,7 +49382,7 @@
"id": "5465"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are four cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(4)",
@ -49397,7 +49398,7 @@
"id": "5467"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are five cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(5)",
@ -49413,7 +49414,7 @@
"id": "5469"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are six cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(6)",
@ -49429,7 +49430,7 @@
"id": "5471"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are seven cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(7)",
@ -49445,7 +49446,7 @@
"id": "5473"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are eight cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(8)",
@ -49461,7 +49462,7 @@
"id": "5475"
},
{
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are nine cabbages in this sack.",
"grand_exchange_price": "1304",
"durability": null,
"name": "Cabbages(9)",
@ -49478,7 +49479,7 @@
},
{
"ge_buy_limit": "1000",
"examine": "There are <number of cabbages> in this sack.",
"examine": "There are ten cabbages in this sack.",
"grand_exchange_price": "917",
"durability": null,
"name": "Cabbages(10)",
@ -55738,7 +55739,7 @@
"equipment_slot": "4"
},
{
"examine": "Damaged: These are in need of a good tailor.Repaired: A pair of mourner trousers.",
"examine": "These are in need of a good tailor.",
"durability": null,
"name": "Mourner trousers",
"weight": "2.25",
@ -55746,7 +55747,7 @@
"id": "6066"
},
{
"examine": "Damaged: These are in need of a good tailor.Repaired: A pair of mourner trousers.",
"examine": "A pair of mourner trousers.",
"durability": null,
"name": "Mourner trousers",
"weight": "2.25",
@ -58309,7 +58310,7 @@
{
"shop_price": "150",
"ge_buy_limit": "100",
"examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.",
"examine": "A brown armband, as worn by the Tai Bwo Wannai locals.",
"grand_exchange_price": "734",
"durability": null,
"name": "Villager armband",
@ -58442,7 +58443,7 @@
{
"shop_price": "150",
"ge_buy_limit": "100",
"examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.",
"examine": "A blue armband, as worn by the Tai Bwo Wannai locals.",
"grand_exchange_price": "672",
"durability": null,
"name": "Villager armband",
@ -58553,7 +58554,7 @@
{
"shop_price": "150",
"ge_buy_limit": "100",
"examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.",
"examine": "A yellow armband, as worn by the Tai Bwo Wannai locals.",
"grand_exchange_price": "823",
"durability": null,
"name": "Villager armband",
@ -58664,7 +58665,7 @@
{
"shop_price": "150",
"ge_buy_limit": "100",
"examine": "A <colour> armband, as worn by the Tai Bwo Wannai locals.",
"examine": "A pink armband, as worn by the Tai Bwo Wannai locals.",
"grand_exchange_price": "1697",
"durability": null,
"name": "Villager armband",
@ -59764,7 +59765,7 @@
},
{
"destroy_message": "You will not get a replacement for the present. Open it for your reward.",
"examine": "Thanks for all your help! Love, Bob & Neite.",
"examine": "Thanks for all your help! Love, Bob & Neite.",
"durability": null,
"name": "Present",
"tradeable": "false",
@ -70692,7 +70693,7 @@
},
{
"ge_buy_limit": "100",
"examine": "In inventory: Nice bit of crafting! When released: Nice bit of crafting that...",
"examine": "Nice bit of crafting!",
"grand_exchange_price": "3236",
"durability": null,
"name": "Toy doll",
@ -70710,7 +70711,7 @@
"id": "7764"
},
{
"examine": "In inventory: Nice bit of crafting! When released: Nice bit of crafting that...",
"examine": "Nice bit of crafting!",
"grand_exchange_price": "3289",
"durability": null,
"name": "Toy doll (wound)",
@ -93158,7 +93159,7 @@
},
{
"requirements": "{1,40}",
"examine": "Rune platebody with complete gold trim & plating.",
"examine": "Rune platebody with complete gold trim & plating.",
"durability": null,
"weight": "10",
"absorb": "3,0,6",
@ -105245,28 +105246,28 @@
"id": "12196"
},
{
"examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.",
"examine": "A hatchling green dragon.",
"durability": null,
"name": "Dragon hatchling",
"archery_ticket_price": "0",
"id": "12197"
},
{
"examine": "Baby: Little NipperAdult: Bigger Nipper.",
"examine": "Little Nipper.",
"durability": null,
"name": "Baby giant crab",
"archery_ticket_price": "0",
"id": "12198"
},
{
"examine": "(Baby) A stripy little baby raccoon.(Adult) He can run with us.",
"examine": "A stripy little baby raccoon.",
"durability": null,
"name": "Baby raccoon",
"archery_ticket_price": "0",
"id": "12199"
},
{
"examine": "Adult: An experienced nut-thief.Baby: A tiny nut-thief.",
"examine": "An experienced nut-thief.",
"durability": null,
"name": "Squirrel",
"archery_ticket_price": "0",
@ -106499,28 +106500,28 @@
"id": "12468"
},
{
"examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.",
"examine": "A hatchling red dragon.",
"durability": null,
"name": "Hatchling dragon",
"name": "Dragon hatchling",
"archery_ticket_price": "0",
"id": "12469"
},
{
"examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.",
"examine": "A hatchling blue dragon.",
"durability": null,
"name": "Hatchling dragon",
"archery_ticket_price": "0",
"id": "12471"
},
{
"examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.",
"examine": "A hatchling green dragon.",
"durability": null,
"name": "Hatchling dragon",
"archery_ticket_price": "0",
"id": "12473"
},
{
"examine": "(hatchling) A hatchling <dragon colour> dragon.(baby) A bigger baby <colour> dragon.",
"examine": "A hatchling black dragon.",
"durability": null,
"name": "Hatchling dragon",
"archery_ticket_price": "0",
@ -106567,16 +106568,17 @@
"id": "12480"
},
{
"examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.",
"examine": "Can't fly and can barely walk, but adorable nonetheless.",
"durability": null,
"name": "Baby penguin",
"archery_ticket_price": "0",
"id": "12481"
},
{
"examine": "I can hatch this in an Incubator.",
"examine": "I can hatch this in an incubator.",
"durability": null,
"name": "Penguin egg",
"tradeable": "false",
"archery_ticket_price": "0",
"id": "12483"
},
@ -108972,14 +108974,14 @@
"id": "12761"
},
{
"examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.",
"examine": "Can't fly and can barely walk, but adorable nonetheless.",
"durability": null,
"name": "Baby penguin",
"archery_ticket_price": "0",
"id": "12763"
},
{
"examine": "(Baby) Can't fly and can barely walk, but adorable nonetheless. (adult) Emperor of all he surveys.",
"examine": "Can't fly and can barely walk, but adorable nonetheless.",
"durability": null,
"name": "Baby penguin",
"archery_ticket_price": "0",
@ -122124,7 +122126,7 @@
{
"lendable": "true",
"destroy_message": "Drop",
"examine": "Rune platebody with complete gold trim & plating.",
"examine": "Rune platebody with complete gold trim & plating.",
"grand_exchange_price": "2034838",
"durability": null,
"name": "Gilded platebody",
@ -132095,5 +132097,20 @@
"archery_ticket_price": "0",
"id": "14658",
"equipment_slot": "0"
},
{
"examine": "Emperor of all he surveys.",
"name": "Penguin",
"id": "12482"
},
{
"examine": "Emperor of all he surveys.",
"name": "Penguin",
"id": "12762"
},
{
"examine": "Emperor of all he surveys.",
"name": "Penguin",
"id": "12764"
}
]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -16324,7 +16324,7 @@
"ids": "11629"
},
{
"examine": "South to Falador :: West to Taverley :: East to Varrock.",
"examine": "This tells you which way is which.",
"ids": "11630,11631,11632,11633"
},
{

View file

@ -564,7 +564,7 @@
"general_store": "false",
"id": "65",
"title": "Dodgy Mikes Second-hand Clothing",
"stock": "{7114,10,100}"
"stock": "{7114,10,100}-{7122,10,100}-{7128,10,100}-{7134,10,100}-{7110,10,100}-{7126,10,100}-{7132,10,100}-{7138,10,100}-{7116,10,100}-{7124,10,100}-{7130,10,100}-{7112,10,100}-{7136,10,100}"
},
{
"npcs": "2161",
@ -2177,5 +2177,23 @@
"id": "255",
"title": "Castle Wars Ticket Exchange",
"stock": "{4068,1,100}-{4069,1,100}-{4070,1,100}-{4071,1,100}-{4072,1,100}-{4503,1,100}-{4504,1,100}-{4505,1,100}-{4506,1,100}-{4507,1,100}-{4508,1,100}-{4509,1,100}-{4510,1,100}-{4511,1,100}-{4512,1,100}-{4513,1,100}-{4514,1,100}-{4515,1,100}-{4516,1,100}"
},
{
"npcs": "5111",
"high_alch": "0",
"currency": "995",
"general_store": "false",
"id": "256",
"title": "Leon's Prototype Crossbow",
"stock": "{10156,2,100}"
},
{
"npcs": "2039",
"high_alch": "0",
"currency": "995",
"general_store": "false",
"id": "256",
"title": "Uglug's Stuffsies",
"stock": "{4844,100,10}-{10927,0,100}-{2862,100,100}-{1777,10,200}-{2876,0,500}-{2878,10,100}-{4850,0,100}-{946,5,100}-{4773,0,1000}-{4778,0,1000}-{4783,0,1000}-{4788,0,1500}-{4793,0,2000}-{4798,0,3000}-{4803,0,4000}-{4827,0,2000}"
}
]

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@ package content.data
import content.global.skill.magic.TeleportMethod
import content.global.skill.slayer.SlayerManager.Companion.getInstance
import content.global.skill.slayer.SlayerUtils
import core.ServerConstants
import core.api.*
import core.game.event.TeleportEvent
@ -304,7 +305,7 @@ enum class EnchantedJewellery(
return
}
sendNPCDialogue(player, slayerManager.master!!.npc, "You're currently " +
"assigned to kill ${getSlayerTaskName(player).lowercase(Locale.getDefault())}'s; " +
"assigned to kill ${SlayerUtils.pluralise(getSlayerTaskName(player))} " +
"only ${getSlayerTaskKillsRemaining(player)} more to go.", core.game.dialogue.FacialExpression.FRIENDLY)
// Slayer tracker UI
setVarp(player, 2502, slayerManager.flags.taskFlags shr 4)

View file

@ -100,7 +100,7 @@ public enum GodBook {
* @param page the page.
*/
public void insertPage(Player player, Item book, Item page) {
if (!hasRequirement(player, "Horror from the Deep"))
if (!hasRequirement(player, Quests.HORROR_FROM_THE_DEEP))
return;
if (hasPage(player, book, page)) {
player.sendMessage("The book already has that page.");

View file

@ -0,0 +1,158 @@
package content.data
enum class Quests(val questName: String) {
MYTHS_OF_THE_WHITE_LANDS("Myths of the White Lands"),
BLACK_KNIGHTS_FORTRESS("Black Knights' Fortress"),
COOKS_ASSISTANT("Cook's Assistant"),
DEMON_SLAYER("Demon Slayer"),
DORICS_QUEST("Doric's Quest"),
DRAGON_SLAYER("Dragon Slayer"),
ERNEST_THE_CHICKEN("Ernest the Chicken"),
GOBLIN_DIPLOMACY("Goblin Diplomacy"),
IMP_CATCHER("Imp Catcher"),
THE_KNIGHTS_SWORD("The Knight's Sword"),
PIRATES_TREASURE("Pirate's Treasure"),
PRINCE_ALI_RESCUE("Prince Ali Rescue"),
THE_RESTLESS_GHOST("The Restless Ghost"),
ROMEO_JULIET("Romeo & Juliet"),
RUNE_MYSTERIES("Rune Mysteries"),
SHEEP_SHEARER("Sheep Shearer"),
SHIELD_OF_ARRAV("Shield of Arrav"),
VAMPIRE_SLAYER("Vampire Slayer"),
WITCHS_POTION("Witch's Potion"),
ANIMAL_MAGNETISM("Animal Magnetism"),
BETWEEN_A_ROCK("Between a Rock..."),
BIG_CHOMPY_BIRD_HUNTING("Big Chompy Bird Hunting"),
BIOHAZARD("Biohazard"),
CABIN_FEVER("Cabin Fever"),
CLOCK_TOWER("Clock Tower"),
CONTACT("Contact!"),
ZOGRE_FLESH_EATERS("Zogre Flesh Eaters"),
CREATURE_OF_FENKENSTRAIN("Creature of Fenkenstrain"),
DARKNESS_OF_HALLOWVALE("Darkness of Hallowvale"),
DEATH_TO_THE_DORGESHUUN("Death to the Dorgeshuun"),
DEATH_PLATEAU("Death Plateau"),
DESERT_TREASURE("Desert Treasure"),
DEVIOUS_MINDS("Devious Minds"),
THE_DIG_SITE("The Dig Site"),
DRUIDIC_RITUAL("Druidic Ritual"),
DWARF_CANNON("Dwarf Cannon"),
EADGARS_RUSE("Eadgar's Ruse"),
EAGLES_PEAK("Eagles' Peak"),
ELEMENTAL_WORKSHOP_I("Elemental Workshop I"),
ELEMENTAL_WORKSHOP_II("Elemental Workshop II"),
ENAKHRAS_LAMENT("Enakhra's Lament"),
ENLIGHTENED_JOURNEY("Enlightened Journey"),
THE_EYES_OF_GLOUPHRIE("The Eyes of Glouphrie"),
FAIRYTALE_I_GROWING_PAINS("Fairytale I - Growing Pains"),
FAIRYTALE_II_CURE_A_QUEEN("Fairytale II - Cure a Queen"),
FAMILY_CREST("Family Crest"),
THE_FEUD("The Feud"),
FIGHT_ARENA("Fight Arena"),
FISHING_CONTEST("Fishing Contest"),
FORGETTABLE_TALE("Forgettable Tale..."),
THE_FREMENNIK_TRIALS("The Fremennik Trials"),
WATERFALL_QUEST("Waterfall Quest"),
GARDEN_OF_TRANQUILITY("Garden of Tranquility"),
GERTRUDES_CAT("Gertrude's Cat"),
GHOSTS_AHOY("Ghosts Ahoy"),
THE_GIANT_DWARF("The Giant Dwarf"),
THE_GOLEM("The Golem"),
THE_GRAND_TREE("The Grand Tree"),
THE_HAND_IN_THE_SAND("The Hand in the Sand"),
HAUNTED_MINE("Haunted Mine"),
HAZEEL_CULT("Hazeel Cult"),
HEROES_QUEST("Heroes' Quest"),
HOLY_GRAIL("Holy Grail"),
HORROR_FROM_THE_DEEP("Horror from the Deep"),
ICTHLARINS_LITTLE_HELPER("Icthlarin's Little Helper"),
IN_AID_OF_THE_MYREQUE("In Aid of the Myreque"),
IN_SEARCH_OF_THE_MYREQUE("In Search of the Myreque"),
JUNGLE_POTION("Jungle Potion"),
LEGENDS_QUEST("Legend's Quest"),
LOST_CITY("Lost City"),
THE_LOST_TRIBE("The Lost Tribe"),
LUNAR_DIPLOMACY("Lunar Diplomacy"),
MAKING_HISTORY("Making History"),
MERLINS_CRYSTAL("Merlin's Crystal"),
MONKEY_MADNESS("Monkey Madness"),
MONKS_FRIEND("Monk's Friend"),
MOUNTAIN_DAUGHTER("Mountain Daughter"),
MOURNINGS_END_PART_I("Mourning's End Part I"),
MOURNINGS_END_PART_II("Mourning's End Part II"),
MURDER_MYSTERY("Murder Mystery"),
MY_ARMS_BIG_ADVENTURE("My Arm's Big Adventure"),
NATURE_SPIRIT("Nature Spirit"),
OBSERVATORY_QUEST("Observatory Quest"),
ONE_SMALL_FAVOUR("One Small Favour"),
PLAGUE_CITY("Plague City"),
PRIEST_IN_PERIL("Priest in Peril"),
RAG_AND_BONE_MAN("Rag and Bone Man"),
RATCATCHERS("Ratcatchers"),
RECIPE_FOR_DISASTER("Recipe for Disaster"),
RECRUITMENT_DRIVE("Recruitment Drive"),
REGICIDE("Regicide"),
ROVING_ELVES("Roving Elves"),
ROYAL_TROUBLE("Royal Trouble"),
RUM_DEAL("Rum Deal"),
SCORPION_CATCHER("Scorpion Catcher"),
SEA_SLUG("Sea Slug"),
THE_SLUG_MENACE("The Slug Menace"),
SHADES_OF_MORTTON("Shades of Mort'ton"),
SHADOW_OF_THE_STORM("Shadow of the Storm"),
SHEEP_HERDER("Sheep Herder"),
SHILO_VILLAGE("Shilo Village"),
A_SOULS_BANE("A Soul's Bane"),
SPIRITS_OF_THE_ELID("Spirits of the Elid"),
SWAN_SONG("Swan Song"),
TAI_BWO_WANNAI_TRIO("Tai Bwo Wannai Trio"),
A_TAIL_OF_TWO_CATS("A Tail of Two Cats"),
TEARS_OF_GUTHIX("Tears of Guthix"),
TEMPLE_OF_IKOV("Temple of Ikov"),
THRONE_OF_MISCELLANIA("Throne of Miscellania"),
THE_TOURIST_TRAP("The Tourist Trap"),
WITCHS_HOUSE("Witch's House"),
TREE_GNOME_VILLAGE("Tree Gnome Village"),
TRIBAL_TOTEM("Tribal Totem"),
TROLL_ROMANCE("Troll Romance"),
TROLL_STRONGHOLD("Troll Stronghold"),
UNDERGROUND_PASS("Underground Pass"),
WANTED("Wanted!"),
WATCHTOWER("Watchtower"),
COLD_WAR("Cold War"),
THE_FREMENNIK_ISLES("The Fremennik Isles"),
TOWER_OF_LIFE("Tower of Life"),
THE_GREAT_BRAIN_ROBBERY("The Great Brain Robbery"),
WHAT_LIES_BELOW("What Lies Below"),
OLAFS_QUEST("Olaf's Quest"),
ANOTHER_SLICE_OF_HAM("Another Slice of H.A.M"),
DREAM_MENTOR("Dream Mentor"),
GRIM_TALES("Grim Tales"),
KINGS_RANSOM("King's Ransom"),
THE_PATH_OF_GLOUPHRIE("The Path of Glouphrie"),
BACK_TO_MY_ROOTS("Back to my Roots"),
LAND_OF_THE_GOBLINS("Land of the Goblins"),
DEALING_WITH_SCABARAS("Dealing with Scabaras"),
WOLF_WHISTLE("Wolf Whistle"),
AS_A_FIRST_RESORT("As a First Resort..."),
CATAPULT_CONSTRUCTION("Catapult Construction"),
KENNITHS_CONCERNS("Kennith's Concerns"),
LEGACY_OF_SEERGAZE("Legacy of Seergaze"),
PERILS_OF_ICE_MOUNTAIN("Perils of Ice Mountain"),
TOKTZ_KET_DILL("TokTz-Ket-Dill"),
SMOKING_KILLS("Smoking Kills"),
ROCKING_OUT("Rocking Out"),
SPIRIT_OF_SUMMER("Spirit of Summer"),
MEETING_HISTORY("Meeting History"),
ALL_FIRED_UP("All Fired Up"),
SUMMERS_END("Summer's End"),
DEFENDER_OF_VARROCK("Defender of Varrock"),
SWEPT_AWAY("Swept Away"),
WHILE_GUTHIX_SLEEPS("While Guthix Sleeps"),
IN_PYRE_NEED("In Pyre Need"),
TEST_QUEST("Test Quest");
override fun toString(): String {
return questName
}
}

View file

@ -30,36 +30,36 @@ public enum Consumables {
HERRING(new Food(new int[] {347}, new HealingEffect(5))),
MACKEREL(new Food(new int[] {355}, new HealingEffect(6))),
ROAST_BIRD_MEAT(new Food(new int[] {9980}, new HealingEffect(6))),
THIN_SNAIL(new Food(new int[] {3369}, new HealingEffect(5))),
THIN_SNAIL(new Food(new int[] {3369}, new RandomHealthEffect(5, 7))),
TROUT(new Food(new int[] {333}, new HealingEffect(7))),
SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new HealingEffect(7))),
SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new RandomHealthEffect(7, 11))),
SPIDER_ON_SHAFT(new Food(new int[] {6299}, new HealingEffect(7))),
ROAST_RABBIT(new Food(new int[] {7223}, new HealingEffect(7))),
LEAN_SNAIL(new Food(new int[] {3371}, new HealingEffect(8))),
LEAN_SNAIL(new Food(new int[] {3371}, new RandomHealthEffect(6, 8))),
COD(new Food(new int[] {339}, new HealingEffect(7))),
PIKE(new Food(new int[] {351}, new HealingEffect(8))),
ROAST_BEAST_MEAT(new Food(new int[] {9988}, new HealingEffect(8))),
COOKED_CRAB_MEAT(new Food(new int[] {7521, 7523, 7524, 7525, 7526}, new HealingEffect(2))),
FAT_SNAIL(new Food(new int[] {3373}, new HealingEffect(9))),
FAT_SNAIL(new Food(new int[] {3373}, new RandomHealthEffect(7, 9))),
SALMON(new Food(new int[] {329}, new HealingEffect(9))),
SLIMY_EEL(new Food(new int[] {3381}, new HealingEffect(6))),
SLIMY_EEL(new Food(new int[] {3381}, new RandomHealthEffect(6, 10))),
TUNA(new Food(new int[] {361}, new HealingEffect(10))),
COOKED_KARAMBWAN(new Food(new int[] {3144}, new HealingEffect(18)), true),
COOKED_CHOMPY(new Food(new int[] {2878}, new HealingEffect(10))),
RAINBOW_FISH(new Food(new int[] {10136}, new HealingEffect(11))),
CAVE_EEL(new Food(new int[] {5003}, new HealingEffect(7))),
CAVE_EEL(new Food(new int[] {5003}, new RandomHealthEffect(8, 12))),
LOBSTER(new Food(new int[] {379}, new HealingEffect(12))),
COOKED_JUBBLY(new Food(new int[] {7568}, new HealingEffect(15))),
BASS(new Food(new int[] {365}, new HealingEffect(13))),
SWORDFISH(new Food(new int[] {373}, new HealingEffect(14))),
LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(14))),
LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(11))),
MONKFISH(new Food(new int[] {7946}, new HealingEffect(16))),
SHARK(new Food(new int[] {385}, new HealingEffect(20))),
SEA_TURTLE(new Food(new int[] {397}, new HealingEffect(21))),
MANTA_RAY(new Food(new int[] {391}, new HealingEffect(22))),
KARAMBWANJI(new Food(new int[] {3151}, new HealingEffect(3))),
STUFFED_SNAKE(new Food(new int[] {7579}, new HealingEffect(20), "You eat the stuffed snake-it's quite a meal! It tastes like chicken.")),
CRAYFISH(new Food(new int[] {13433}, new HealingEffect(2))),
CRAYFISH(new Food(new int[] {13433}, new HealingEffect(1))),
GIANT_FROG_LEGS(new Food(new int [] {4517}, new HealingEffect(6))),
/** Breads */
@ -111,7 +111,7 @@ public enum Consumables {
/** Vegetables */
POTATO(new Food(new int[] {1942}, new HealingEffect(1), "You eat the potato. Yuck!")),
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(2))),
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(4))),
SPICY_SAUCE(new Food(new int[] {7072, 1923}, new HealingEffect(2))),
CHILLI_CON_CARNE(new Food(new int[] {7062, 1923}, new HealingEffect(5))),
SCRAMBLED_EGG(new Food(new int[] {7078, 1923}, new HealingEffect(5))),
@ -128,8 +128,8 @@ public enum Consumables {
MUSHROOM_POTATO(new Food(new int[] {7058}, new HealingEffect(20))),
TUNA_AND_CORN(new Food(new int[] {7068, 1923}, new HealingEffect(13))),
TUNA_POTATO(new Food(new int[] {7060}, new HealingEffect(22))),
ONION(new Food(new int[] {1957}, new HealingEffect(2), "It's always sad to see a grown man/woman cry.")),
CABBAGE(new Food(new int[] {1965}, new HealingEffect(2), "You eat the cabbage. Yuck!")),
ONION(new Food(new int[] {1957}, new HealingEffect(1), "It's always sad to see a grown man/woman cry.")),
CABBAGE(new Food(new int[] {1965}, new HealingEffect(1), "You eat the cabbage. Yuck!")),
DRAYNOR_CABBAGE(new Food(new int[] {1967}, new DraynorCabbageEffect(), "You eat the cabbage.", "It seems to taste nicer than normal.")),
EVIL_TURNIP(new Food(new int[] {12134, 12136, 12138}, new HealingEffect(6))),
SPINACH_ROLL(new Food(new int[] {1969}, new HealingEffect(2))),
@ -147,7 +147,7 @@ public enum Consumables {
ORANGE(new Food(new int[] {2108}, new HealingEffect(2))),
ORANGE_CHUNKS(new Food(new int[] {2110}, new HealingEffect(2))),
ORANGE_SLICES(new Food(new int[] {2112}, new HealingEffect(2))),
PAPAYA_FRUIT(new Food(new int[] {5972}, new HealingEffect(2))),
PAPAYA_FRUIT(new Food(new int[] {5972}, new MultiEffect(new EnergyEffect(5), new HealingEffect(8)))),
TENTI_PINEAPPLE(new FakeConsumable(1851, new String[] {"Try using a knife to slice it into pieces."})),
PINEAPPLE(new FakeConsumable(2114, new String[] {"Try using a knife to slice it into pieces."})),
PINEAPPLE_CHUNKS(new Food(new int[] {2116}, new HealingEffect(2))),
@ -169,8 +169,8 @@ public enum Consumables {
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(30)))),
/** Gnome Cooking */
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(12))),
PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(12))),
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(8))),
PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(8))),
SPICY_CRUNCHIES(new Food(new int[] {2213}, new HealingEffect(7))),
PREMADE_SY_CRUNCH(new Food(new int[] {2241}, new HealingEffect(7))),
WORM_CRUNCHIES(new Food(new int[] {2205}, new HealingEffect(8))),
@ -307,7 +307,7 @@ public enum Consumables {
OOMLIE_WRAP(new Food(new int[] {Items.COOKED_OOMLIE_WRAP_2343}, new MultiEffect(new HealingEffect(14), new AchievementEffect(DiaryType.KARAMJA, 2, 2)))),
ROE(new Food(new int[]{11324}, new HealingEffect(3))),
EQUA_LEAVES(new Food(new int[]{2128}, new HealingEffect(1))),
CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(6))),
CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(7))),
EDIBLE_SEAWEED(new Food(new int[] {403}, new HealingEffect(4))),
FROG_SPAWN(new Food(new int[] {5004}, new RandomHealthEffect(3, 7), "You eat the frogspawn. Yuck.")),
@ -328,7 +328,7 @@ public enum Consumables {
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new AddTimerEffect("poison:immunity", minutesToTicks(9)))),
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new AddTimerEffect("poison:immunity", minutesToTicks(12)))),
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new AddTimerEffect("poison:immunity", minutesToTicks(6)))),
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveTimerEffect("disease")))),
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new CureDiseaseEffect())),
AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))),
HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))),
RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))),
@ -339,8 +339,8 @@ public enum Consumables {
FISHING(new Potion(new int[] {2438, 151, 153, 155}, new SkillEffect(Skills.FISHING, 3, 0))),
PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))),
SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new RestoreEffect(8, 0.25, true))),
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))),
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.25), new SkillEffect(Skills.STRENGTH, 0, 0.15), new SkillEffect(Skills.DEFENCE, 0, -0.1)))),
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new AddTimerEffect("dragonfire:immunity", 600, true))),
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveTimerEffect("poison"), new EnergyEffect(5), new HealingEffect(5)))),
MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))),
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25, true), new AddTimerEffect("poison:immunity", secondsToTicks(90)), new RemoveTimerEffect("disease")))),
@ -349,10 +349,10 @@ public enum Consumables {
/** Barbarian Mixes */
PRAYERMIX(new BarbarianMix(new int[] {11465, 11467}, new MultiEffect(new PrayerEffect(7, 0.25), new HealingEffect(6)))),
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1)))),
ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))),
ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new AddTimerEffect("poison:immunity", secondsToTicks(90)), new HealingEffect(3)))),
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveTimerEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))),
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new CureDiseaseEffect(), new HealingEffect(3)))),
STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))),
RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))),
SUPER_RESTO_MIX(new BarbarianMix(new int [] {11493, 11495}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25), new HealingEffect(6)))),
@ -367,6 +367,7 @@ public enum Consumables {
SUPER_STR_MIX(new BarbarianMix(new int[] {11485, 11487}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 5, 0.15), new HealingEffect(6)))),
ANTIDOTE_PLUS_MIX(new BarbarianMix(new int[] {11501, 11503}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(9)), new RandomHealthEffect(3, 7)))),
ANTIP_SUPERMIX(new BarbarianMix(new int[] {11473, 11475}, new MultiEffect(new AddTimerEffect("poison:immunity", minutesToTicks(6)), new RandomHealthEffect(3, 7)))),
ANTIFIRE_MIX(new BarbarianMix(new int[] {11505, 11507}, new MultiEffect(new AddTimerEffect("dragonfire:immunity", 600, true), new RandomHealthEffect(3, 7)))),
/** Stealing creation potions */
SC_PRAYER(new Potion(new int[] {14207, 14209, 14211, 14213, 14215}, new PrayerEffect(7, 0.25))),

View file

@ -0,0 +1,21 @@
package content.data.consumables.effects
import core.api.*
import core.game.consumable.ConsumableEffect
import core.game.node.entity.player.Player
import core.game.system.timer.impl.Disease
class CureDiseaseEffect () : ConsumableEffect() {
override fun activate (p: Player) {
val existingTimer = getTimer<Disease>(p)
if (existingTimer != null) {
existingTimer.hitsLeft -= 9
if (existingTimer.hitsLeft <= 0) {
sendMessage(p, "The disease has been cured.")
removeTimer<Disease>(p)
}else{
sendMessage(p,"You feel slightly better.")
}
}
}
}

View file

@ -30,11 +30,13 @@ public class RestoreEffect extends ConsumableEffect {
int[] skills = this.all_skills ? ALL_SKILLS : SKILLS;
for(int skill : skills){
int statL = sk.getStaticLevel(skill);
int boost = (int) (base + (statL * bonus));
int curL = sk.getLevel(skill);
if(curL < statL){
int boost = (int) (base + (statL * bonus));
p.getSkills().updateLevel(skill, boost, statL);
}
if (skill == Skills.PRAYER)
p.getSkills().incrementPrayerPoints(boost);
}
}
}

View file

@ -11,12 +11,13 @@ import core.ServerStore.Companion.getString
import content.global.bots.ShootingStarBot
import core.game.world.repository.Repository
import core.tools.RandomFunction
/**
* Represents a shooting star object (Only ever initialized once) (ideally)
* @author Ceikry
*/
class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()){
class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()) {
val crash_locations = mapOf(
"East of Dark Wizards' Tower" to Location.create(2925, 3339, 0), // East of Dark Wizards' Tower
"Crafting Guild" to Location.create(2940, 3280, 0), // Crafting Guild Mine
@ -30,7 +31,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
"Relleka mining site" to Location.create(2682, 3700, 0), // Rellekka mining site
"Jatizso mine" to Location.create(2393, 3815, 0), //Jatiszo mining site (requires Fremennik Isles prereqs)
"Lunar Isle mine" to Location.create(2140, 3939, 0), // Lunar Isle mine (requires Lunar Diplomacy prereqs)
"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires Fremennik Trials)
"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires The Fremennik Trials)
//"Neitiznot runite mine" to Location.create(2376, 3835, 0), // Near the Neitiznot runite mine (requires Fremennik Isles prereqs) currently inaccessible as bridge does not work
"Ardougne mining site" to Location.create(2600, 3232, 0), // Ardougne mining site (Monastery)
"Ardougne eastern mine" to Location.create(2706, 3334, 0), // Ardougne mining site (Legends Guild)
@ -79,22 +80,15 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
* Degrades a ShootingStar (or removes the starObject and spawns a Star Sprite if it's the last star)
*/
fun degrade() {
if(level.ordinal == 0){
selfBots.filter { it.isMining() }.forEach { it.sleep() }
SceneryBuilder.remove(starObject)
isSpawned = false
starSprite.location = starObject.location
starSprite.init()
spriteSpawned = true
ShootingStarPlugin.getStoreFile().clear()
if(level.ordinal == 0) {
spawnSprite()
return
}
level = getNextType()
maxDust = level.totalStardust
dustLeft = level.totalStardust
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
val newStar = Scenery(level.objectId, starObject.location)
SceneryBuilder.replace(starObject, newStar)
@ -110,7 +104,6 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
*/
fun fire() {
SceneryBuilder.remove(starObject)
rebuildVars()
clearSprite()
SceneryBuilder.add(starObject)
if(!isSpawned) {
@ -123,37 +116,54 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
}
isSpawned = true
Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location}!")
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
ShootingStarPlugin.getStoreFile()["location"] = location
ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
}
/**
* Rebuilds some of the variables with new information.
*/
fun rebuildVars(){
if(firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()){
level = ShootingStarType.values()[ShootingStarPlugin.getStoreFile().getInt("level")]
location = ShootingStarPlugin.getStoreFile().getString("location")
isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered")
} else {
level = ShootingStarType.values().random()
location = crash_locations.entries.random().key
isDiscovered = false
// Defaults
var levelOrd = RandomFunction.random(9)
level = ShootingStarType.values()[levelOrd]
location = crash_locations.entries.random().key
isDiscovered = false
dustLeft = level.totalStardust
ticks = 0
spriteSpawned = false
if (firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()) {
// Replace default with stored values, if any
levelOrd = ShootingStarPlugin.getStoreFile().getInt("level", levelOrd)
level = ShootingStarType.values()[levelOrd]
location = ShootingStarPlugin.getStoreFile().getString("location", location)
isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered", false)
dustLeft = ShootingStarPlugin.getStoreFile().getInt("dustLeft", dustLeft)
ticks = ShootingStarPlugin.getStoreFile().getInt("ticks", ticks)
spriteSpawned = ShootingStarPlugin.getStoreFile().getBoolean("spriteSpawned", false)
}
maxDust = level.totalStardust
dustLeft = level.totalStardust
starObject = Scenery(level.objectId, crash_locations.get(location))
}
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
ShootingStarPlugin.getStoreFile()["location"] = location
ShootingStarPlugin.getStoreFile()["isDiscovered"] = false
ticks = 0
firstStar = false
fun spawnSprite() {
selfBots.filter { it.isMining() }.forEach { it.sleep() }
SceneryBuilder.remove(starObject)
isSpawned = false
starSprite.location = starObject.location
starSprite.init()
spriteSpawned = true
ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned
}
fun clearSprite() {
starSprite.clear()
spriteSpawned = false
ShootingStarPlugin.getStoreFile()["spriteSpawned"] = spriteSpawned
}
/**
@ -161,6 +171,7 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando
*/
fun decDust() {
if(--dustLeft <= 0) degrade()
ShootingStarPlugin.getStoreFile()["dustLeft"] = dustLeft
}
/**

View file

@ -51,6 +51,7 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin
player.sendMessage("You have ${player.skills.experienceMultiplier * player.getAttribute("shooting-star:bonus-xp", 0).toDouble()} bonus xp towards mining stardust.")
ShootingStarPlugin.submitScoreBoard(player)
star.isDiscovered = true
ShootingStarPlugin.getStoreFile()["isDiscovered"] = star.isDiscovered
return player.skills.getLevel(Skills.MINING) >= star.miningLevel
}

View file

@ -12,11 +12,11 @@ import core.ServerStore.Companion.getBoolean
import core.game.dialogue.DialogueFile
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import core.tools.SystemLogger
import core.game.system.command.Privilege
import core.game.world.GameWorld
import core.tools.Log
import core.tools.secondsToTicks
import content.data.Quests
class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Commands, StartupListener {
override fun login(player: Player) {
@ -27,14 +27,30 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
override fun tick() {
++star.ticks
// Check if the current star sprite should expire
val maxDelay = tickDelay + (tickDelay / 3)
if(star.ticks > maxDelay && star.spriteSpawned){
star.clearSprite()
}
if ((star.ticks >= tickDelay && !star.spriteSpawned) || (!star.isSpawned && !star.spriteSpawned)) {
if (star.firstStar && !star.isSpawned && !star.spriteSpawned) {
// Apparently, the server has only just booted
star.rebuildVars()
if (star.spriteSpawned) {
star.spawnSprite()
} else {
star.fire()
}
star.firstStar = false
}
// Check if it's time to fire a new one
if (star.ticks >= tickDelay && !star.spriteSpawned) {
star.rebuildVars()
star.fire()
}
getStoreFile()["ticks"] = star.ticks
}
override fun defineListeners() {
@ -80,17 +96,17 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
override fun handle(componentID: Int, buttonID: Int) {
fun teleportToStar(player: Player) {
val condition: (p: Player) -> Boolean = when (star.location.toLowerCase()) {
"canifis bank" -> {p -> requireQuest(p, "Priest in Peril", "to access this.") }
//"burgh de rott bank" -> {p -> hasRequirement(p, "In Aid of the Myreque") } //disabled: crash
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40) }
"lletya bank" -> {p -> hasRequirement(p, "Mourning's End Part I") }
"jatizso mine" -> {p -> hasRequirement(p, "The Fremennik Isles") }
"south crandor mining site" -> {p -> hasRequirement(p, "Dragon Slayer") }
"shilo village mining site" -> {p -> hasRequirement(p, "Shilo Village") }
"mos le'harmless bank" -> {p -> hasRequirement(p, "Cabin Fever") } //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025
"lunar isle mine" -> {p -> hasRequirement(p, "Lunar Diplomacy") }
"miscellania coal mine" -> {p -> requireQuest(p, "The Fremennik Trials", "to access this.") }
//"neitiznot runite mine" -> {p -> hasRequirement(p, "The Fremennik Isles") } //disabled: currently not reachable
"canifis bank" -> {p -> requireQuest(p, Quests.PRIEST_IN_PERIL, "to access this.")}
//"burgh de rott bank" -> {p -> hasRequirement(p, Quests.IN_AID_OF_THE_MYREQUE)} //disabled: crash
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40)}
"lletya bank" -> {p -> hasRequirement(p, Quests.MOURNINGS_END_PART_I)}
"jatizso mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)}
"south crandor mining site" -> {p -> hasRequirement(p, Quests.DRAGON_SLAYER)}
"shilo village mining site" -> {p -> hasRequirement(p, Quests.SHILO_VILLAGE)}
"mos le'harmless bank" -> {p -> hasRequirement(p, Quests.CABIN_FEVER)} //needs to be updated to check for completion when the quest releases; https://runescape.wiki/w/Mos_Le%27Harmless?oldid=913025
"lunar isle mine" -> {p -> hasRequirement(p, Quests.LUNAR_DIPLOMACY)}
"miscellania coal mine" -> {p -> requireQuest(p, Quests.THE_FREMENNIK_TRIALS, "to access this.")}
//"neitiznot runite mine" -> {p -> hasRequirement(p, Quests.THE_FREMENNIK_ISLES)} //disabled: currently not reachable
else -> {_ -> true}
}
if (!condition.invoke(player)) {
@ -122,6 +138,7 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com
}
define("submit", Privilege.ADMIN) { _, _ ->
star.rebuildVars()
star.fire()
}

View file

@ -0,0 +1,23 @@
package content.global.ame
import core.ServerConstants
import core.api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager.TeleportType
import core.game.world.map.Location
fun kidnapPlayer(player: Player, loc: Location, type: TeleportType) {
setAttribute(player, "kidnapped-by-random", true)
if (getAttribute(player, "/save:original-loc", null) == null) {
setAttribute(player, "/save:original-loc", player.location)
}
teleport(player, loc, type)
}
fun returnPlayer(player: Player) {
player.locks.unlockTeleport()
val destination = getAttribute(player, "/save:original-loc", ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
teleport(player, destination)
unlock(player)
removeAttributes(player, "/save:original-loc", "kidnapped-by-random")
}

View file

@ -3,9 +3,15 @@ package content.global.ame
import content.global.ame.events.MysteriousOldManNPC
import core.api.playGlobalAudio
import core.api.poofClear
import core.api.sendMessage
import core.api.utils.WeightBasedTable
import core.game.interaction.MovementPulse
import core.game.node.entity.Entity
import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.impl.PulseType
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.agg.AggressiveBehavior
import core.game.node.entity.npc.agg.AggressiveHandler
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.world.map.Location
@ -13,10 +19,11 @@ import core.game.world.map.RegionManager
import core.game.world.map.path.Pathfinder
import core.game.world.update.flag.context.Graphics
import core.integrations.discord.Discord
import core.api.utils.WeightBasedTable
import core.tools.secondsToTicks
import core.tools.ticksToCycles
import org.rs09.consts.Sounds
import kotlin.math.ceil
import kotlin.math.min
import kotlin.random.Random
import kotlin.reflect.full.createInstance
@ -66,7 +73,6 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
if (!player.getAttribute("random:pause", false)) {
ticksLeft--
}
if (!pulseManager.hasPulseRunning() && !finalized) {
follow()
}
@ -87,6 +93,11 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
location = spawnLocation
player.setAttribute("re-npc", this)
super.init()
super.aggressiveHandler = AggressiveHandler(this, object : AggressiveBehavior() {
override fun canSelectTarget(entity: Entity, target: Entity): Boolean {
return target == player
}
})
}
open fun onTimeUp() {
@ -118,4 +129,19 @@ abstract class RandomEventNPC(id: Int) : NPC(id) {
}
abstract fun talkTo(npc: NPC)
}
override fun isAttackable(entity: Entity, style: CombatStyle, message: Boolean): Boolean {
if (entity != player) {
if (entity is Player) {
sendMessage(entity, "It isn't interested in fighting you.") //TODO authentic message
}
return false
}
return super.isAttackable(entity, style, message)
}
fun idForCombatLevel(ids: List<Int>, player: Player): Int {
val index = min(ids.size, ceil(player.properties.currentCombatLevel / 20.0).toInt()) - 1
return ids[index]
}
}

View file

@ -3,16 +3,18 @@ package content.global.ame
import org.rs09.consts.Items
import content.global.ame.events.MysteriousOldManNPC
import content.global.ame.events.certer.CerterNPC
import content.global.ame.events.drilldemon.SeargentDamienNPC
import content.global.ame.events.drilldemon.SergeantDamienNPC
import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC
import content.global.ame.events.evilbob.EvilBobNPC
import content.global.ame.events.evilchicken.EvilChickenNPC
import content.global.ame.events.freakyforester.FreakyForesterNPC
import content.global.ame.events.maze.MazeNPC
import content.global.ame.events.genie.GenieNPC
import content.global.ame.events.pillory.PilloryNPC
import content.global.ame.events.rickturpentine.RickTurpentineNPC
import content.global.ame.events.rivertroll.RiverTrollRENPC
import content.global.ame.events.rockgolem.RockGolemRENPC
import content.global.ame.events.quizmaster.QuizMasterNPC
import content.global.ame.events.sandwichlady.SandwichLadyRENPC
import content.global.ame.events.shade.ShadeRENPC
import content.global.ame.events.strangeplant.StrangePlantNPC
@ -44,7 +46,8 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985,1,1,0.1),
WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1)
)),
DRILL_DEMON(npc = SeargentDamienNPC()),
MAZE(npc = MazeNPC()),
DRILL_DEMON(npc = SergeantDamienNPC()),
EVIL_CHICKEN(npc = EvilChickenNPC()),
STRANGE_PLANT(npc = StrangePlantNPC()),
SWARM(npc = SwarmNPC()),
@ -55,6 +58,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
FREAKY_FORESTER(npc = FreakyForesterNPC(), skillIds = intArrayOf(Skills.WOODCUTTING)),
PILLORY(npc = PilloryNPC(), skillIds = intArrayOf(Skills.THIEVING)),
TREE_SPIRIT(npc = TreeSpiritRENPC(), skillIds = intArrayOf(Skills.WOODCUTTING)),
QUIZ_MASTER(npc = QuizMasterNPC()),
RIVER_TROLL(RiverTrollRENPC(), skillIds = intArrayOf(Skills.FISHING)),
ROCK_GOLEM(RockGolemRENPC(), skillIds = intArrayOf(Skills.MINING)),
SHADE(ShadeRENPC(), skillIds = intArrayOf(Skills.PRAYER)),

View file

@ -0,0 +1,19 @@
package content.global.ame.events
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import org.rs09.consts.NPCs
class HostileRandomEventBehavior : NPCBehavior(
NPCs.EVIL_CHICKEN_2463, NPCs.EVIL_CHICKEN_2464, NPCs.EVIL_CHICKEN_2465, NPCs.EVIL_CHICKEN_2466, NPCs.EVIL_CHICKEN_2467, NPCs.EVIL_CHICKEN_2468,
NPCs.RIVER_TROLL_391, NPCs.RIVER_TROLL_392, NPCs.RIVER_TROLL_393, NPCs.RIVER_TROLL_394, NPCs.RIVER_TROLL_395, NPCs.RIVER_TROLL_396,
NPCs.ROCK_GOLEM_413, NPCs.ROCK_GOLEM_414, NPCs.ROCK_GOLEM_415, NPCs.ROCK_GOLEM_416, NPCs.ROCK_GOLEM_417, NPCs.ROCK_GOLEM_418,
NPCs.SHADE_425, NPCs.SHADE_426, NPCs.SHADE_427, NPCs.SHADE_428, NPCs.SHADE_429, NPCs.SHADE_430, NPCs.SHADE_431,
NPCs.TREE_SPIRIT_438, NPCs.TREE_SPIRIT_439, NPCs.TREE_SPIRIT_440, NPCs.TREE_SPIRIT_441, NPCs.TREE_SPIRIT_442, NPCs.TREE_SPIRIT_443,
NPCs.ZOMBIE_419, NPCs.ZOMBIE_420, NPCs.ZOMBIE_421, NPCs.ZOMBIE_422, NPCs.ZOMBIE_423, NPCs.ZOMBIE_424
) {
override fun getXpMultiplier(self: NPC, attacker: Entity): Double {
return super.getXpMultiplier(self, attacker) / 16.0
}
}

View file

@ -1,9 +1,11 @@
package content.global.ame.events.drilldemon
import core.ServerConstants
import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.*
import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.update.flag.context.Animation
@ -12,7 +14,6 @@ import org.rs09.consts.NPCs
object DrillDemonUtils {
val DD_KEY_TASK = "/save:drilldemon:task"
val DD_KEY_RETURN_LOC = "/save:original-loc"
val DD_SIGN_VARP = 531
val DD_SIGN_JOG = 0
val DD_SIGN_SITUP = 1
@ -24,10 +25,7 @@ object DrillDemonUtils {
val DD_NPC = NPCs.SERGEANT_DAMIEN_2790
fun teleport(player: Player) {
if (getAttribute(player, DD_KEY_RETURN_LOC, null) == null) {
setAttribute(player, DD_KEY_RETURN_LOC, player.location)
}
teleport(player, Location.create(3163, 4819, 0))
kidnapPlayer(player, Location.create(3163, 4819, 0), TeleportManager.TeleportType.INSTANT)
player.interfaceManager.closeDefaultTabs()
setComponentVisibility(player, 548, 69, true)
setComponentVisibility(player, 746, 12, true)
@ -66,14 +64,8 @@ object DrillDemonUtils {
}
fun cleanup(player: Player) {
player.locks.unlockTeleport()
unlock(player)
val destination = getAttribute(player, DD_KEY_RETURN_LOC, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
teleport(player, destination)
removeAttribute(player, DD_KEY_RETURN_LOC)
removeAttribute(player, DD_KEY_TASK)
removeAttribute(player, DD_CORRECT_OFFSET)
removeAttribute(player, DD_CORRECT_COUNTER)
returnPlayer(player)
removeAttributes(player, DD_KEY_TASK, DD_CORRECT_OFFSET, DD_CORRECT_COUNTER)
player.interfaceManager.openDefaultTabs()
setComponentVisibility(player, 548, 69, false)
setComponentVisibility(player, 746, 12, false)

View file

@ -10,11 +10,11 @@ import core.game.interaction.QueueStrength
import core.game.system.timer.impl.AntiMacro
import core.tools.secondsToTicks
class SeargentDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
class SergeantDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
override fun init() {
super.init()
sendChat(player.username.capitalize() + "! Drop and give me 20!")
sendChat(player.username+ "! Drop and give me 20!")
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {

View file

@ -1,5 +1,6 @@
package content.global.ame.events.evilbob
import content.global.ame.returnPlayer
import core.ServerConstants
import core.api.*
import core.game.dialogue.FacialExpression
@ -8,8 +9,6 @@ import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
import core.game.node.entity.Entity
import core.game.node.entity.player.link.emote.Emotes
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction
@ -121,8 +120,7 @@ class EvilBobListeners : InteractionListener, MapArea {
}
3 -> {
sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.")
val destination = getAttribute(player, EvilBobUtils.prevLocation, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
teleport(player, destination)
returnPlayer(player)
EvilBobUtils.reward(player)
EvilBobUtils.cleanup(player)
resetAnimator(player)

View file

@ -1,8 +1,10 @@
package content.global.ame.events.evilbob
import core.ServerConstants
import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.node.entity.skill.Skills
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
@ -14,7 +16,6 @@ import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
object EvilBobUtils {
const val prevLocation = "/save:original-loc"
const val eventComplete = "/save:evilbob:eventcomplete"
const val assignedFishingZone = "/save:evilbob:fishingzone"
const val attentive = "/save:evilbob:attentive"
@ -53,16 +54,11 @@ object EvilBobUtils {
}
fun teleport(player: Player) {
if (getAttribute(player, prevLocation, null) == null) {
setAttribute(player, prevLocation, player.location)
}
player.properties.teleportLocation = Location.create(3419, 4776, 0)
kidnapPlayer(player, Location.create(3419, 4776, 0), TeleportManager.TeleportType.INSTANT)
}
fun cleanup(player: Player) {
player.locks.unlockTeleport()
player.properties.teleportLocation = getAttribute(player, prevLocation, ServerConstants.HOME_LOCATION)
removeAttributes(player, assignedFishingZone, eventComplete, prevLocation, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
removeAttributes(player, assignedFishingZone, eventComplete, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
removeAll(player, Items.FISHLIKE_THING_6202)
removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK)
removeAll(player, Items.FISHLIKE_THING_6206)

View file

@ -9,9 +9,8 @@ import core.tools.RandomFunction
import org.rs09.consts.Items
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import java.lang.Integer.max
val ids = 2463..2468
val ids = (2463..2468).toList()
class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(2463) {
val phrases = arrayOf("Bwuk","Bwuk bwuk bwuk","Flee from me, @name!","Begone, @name!","Bwaaaauuuk bwuk bwuk","MUAHAHAHAHAAA!")
@ -19,8 +18,7 @@ class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventN
override fun init() {
super.init()
val index = max(0, (player.properties.combatLevel / 20) - 1)
val id = ids.toList()[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat(phrases.random().replace("@name",player.username.capitalize()))

View file

@ -1,17 +1,18 @@
package content.global.ame.events.freakyforester
import core.ServerConstants
import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.*
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.tools.RandomFunction
object FreakUtils{
const val freakNpc = NPCs.FREAKY_FORESTER_2458
const val freakPreviousLoc = "/save:original-loc"
const val freakTask = "/save:freakyf:task"
const val freakComplete = "/save:freakyf:complete"
const val pheasantKilled = "freakyf:killed"
@ -28,16 +29,12 @@ object FreakUtils{
}
fun teleport(player: Player) {
if (getAttribute(player, freakPreviousLoc,null) == null) {
setAttribute(player, freakPreviousLoc, player.location)
}
teleport(player, Location.create(2599, 4777 ,0))
kidnapPlayer(player, Location.create(2599, 4777 ,0), TeleportManager.TeleportType.INSTANT)
}
fun cleanup(player: Player) {
player.locks.unlockTeleport()
player.properties.teleportLocation = getAttribute(player,freakPreviousLoc, ServerConstants.HOME_LOCATION)
removeAttributes(player, freakPreviousLoc, freakTask, freakComplete, pheasantKilled)
returnPlayer(player)
removeAttributes(player, freakTask, freakComplete, pheasantKilled)
removeAll(player, Items.RAW_PHEASANT_6178)
removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK)
removeAll(player, Items.RAW_PHEASANT_6179)

View file

@ -0,0 +1,277 @@
package content.global.ame.events.maze
import content.global.ame.returnPlayer
import core.api.*
import core.api.utils.WeightBasedTable
import core.api.utils.WeightedItem
import core.game.event.EventHook
import core.game.event.TickEvent
import core.game.global.action.DoorActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.system.task.Pulse
import core.game.world.GameWorld.Pulser
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.*
class MazeInterface : InteractionListener, EventHook<TickEvent>, MapArea {
companion object {
const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209
const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0]
const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left"
const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened"
val STARTING_POINTS = arrayOf(
Location(2928, 4553, 0),
Location(2917, 4553, 0),
Location(2908, 4555, 0),
Location(2891, 4589, 0),
Location(2891, 4595, 0),
Location(2891, 4595, 0),
Location(2926, 4597, 0),
Location(2931, 4597, 0),
// There's 2 more, but there isn't a door for them...
)
val REWARD_ITEM = intArrayOf(
Items.COINS_995,
Items.FEATHER_314,
Items.IRON_ARROW_884,
Items.CHAOS_RUNE_562,
Items.STEEL_ARROW_886,
Items.DEATH_RUNE_560,
Items.COAL_454,
Items.NATURE_RUNE_561,
Items.MITHRIL_ORE_448
)
val ITEM_DIVISOR = arrayOf(
1.0,
2.0,
3.0,
9.0,
12.0,
18.0,
45.0,
162.0,
180.0,
)
val CHEST_REWARDS = WeightBasedTable.create(
WeightedItem(Items.AIR_RUNE_556,15,15,1.0),
WeightedItem(Items.WATER_RUNE_555,10,10,1.0),
WeightedItem(Items.EARTH_RUNE_557,10,10,1.0),
WeightedItem(Items.FIRE_RUNE_554,10,10,1.0),
WeightedItem(Items.BRONZE_ARROW_882,20,20,1.0),
WeightedItem(Items.BRONZE_BOLTS_877,10,10,1.0),
WeightedItem(Items.IRON_ARROW_884,15,15,1.0),
WeightedItem(Items.ATTACK_POTION2_123,1,1,1.0),
WeightedItem(Items.STRENGTH_POTION2_117,1,1,1.0),
WeightedItem(Items.DEFENCE_POTION2_135,1,1,1.0),
)
fun initMaze(player: Player) {
setAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 300)
setVarp(player, MAZE_TIMER_VARP, (getAttribute<Int>(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3),false)
openOverlay(player, MAZE_TIMER_INTERFACE)
sendMessage(player, "You need to reach the maze center, then you'll be returned to where you were.")
sendNPCDialogue(player, NPCs.MYSTERIOUS_OLD_MAN_410, "You need to reach the maze center, then you'll be returned to where you were.")
}
fun calculateLoot(player: Player) {
val randomNumber = (0..8).random()
val totalLevel = player.getSkills().totalLevel.toDouble()
val rewardPotential = getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0).toDouble() / 300.0
val itemDivisor = ITEM_DIVISOR[randomNumber]
val itemQuantity = (totalLevel * rewardPotential * 3.33) / itemDivisor
// sendMessage(player, "Maze reward calculation: $totalLevel * $rewardPotential * 3.33 / $itemDivisor = $itemQuantity")
if (itemQuantity.toInt() > 0) {
addItemOrDrop(player, REWARD_ITEM[randomNumber], itemQuantity.toInt())
}
}
/**
* Chest Location to rotation mapping.
* This is needed as it is impossible to obtain the underlying chest scenery for the rotation.
* 0: Facing North, 1: Facing East, 2: Facing South, 3: Facing West
*/
val chestLocationRotationMap = mapOf(
Location(2930, 4595, 0).toString() to 2,
Location(2924, 4572, 0).toString() to 2,
Location(2925, 4573, 0).toString() to 0,
Location(2900, 4578, 0).toString() to 2,
Location(2901, 4560, 0).toString() to 1,
Location(2890, 4599, 0).toString() to 2,
Location(2896, 4591, 0).toString() to 2,
Location(2895, 4592, 0).toString() to 1,
Location(2901, 4560, 0).toString() to 3,
Location(2918, 4590, 0).toString() to 1,
Location(2917, 4590, 0).toString() to 3,
)
/**
* Chest Interaction workaround
*
* The issue here is that the walls(3626) of the Maze are overlapping some(not all) chest sceneries.
*
* The types for the wallScenery:
* Type 0 - flat panel |
* Type 2 - right angle panel with rotation 0:r 1:7 2:> 3:L
* Type 3 - corner post . for angle edges of walls
*/
fun overrideScenery(wallScenery: core.game.node.scenery.Scenery, chestSceneryId: Int): core.game.node.scenery.Scenery {
if (wallScenery.id == chestSceneryId) {
replaceScenery(wallScenery, Scenery.CHEST_3636, 30)
wallScenery.isActive = true
return wallScenery // Return the chest scenery as the wallScenery isn't there.
}
addScenery(Scenery.CHEST_3636, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10)
addScenery(wallScenery)
// replaceScenery(newChestScenery, Scenery.CHEST_3636, 3) // didn't work for an underlying scenery
// I did a world pulse since everyone will get to see the chest open.
Pulser.submit(object : Pulse(30) {
override fun pulse(): Boolean {
addScenery(Scenery.CHEST_3635, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10)
addScenery(wallScenery)
return true
}
})
// Return the chest scenery to replace PacketProcessor so that MISMATCH will not happen.
return core.game.node.scenery.Scenery(
chestSceneryId,
wallScenery.location,
chestLocationRotationMap[wallScenery.location.toString()] ?: 0
)
}
}
override fun defineListeners() {
// This somehow doesn't trigger as the scenery.id != objId (3626 != 3635)
on(Scenery.CHEST_3635, IntType.SCENERY, "open") { player, node ->
if (getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0 && getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0) < 10) {
animate(player, 536)
// val actualScenery = RegionManager.getObject(node.location.z, node.location.x, node.location.y, 3626)
val tableRoll = CHEST_REWARDS.roll()
addItemOrBank(player, tableRoll[0].id)
when (tableRoll[0].id){
Items.AIR_RUNE_556 -> sendItemDialogue(player, Items.AIR_RUNE_556, "You've found some air runes!")
Items.WATER_RUNE_555 -> sendItemDialogue(player, Items.WATER_RUNE_555, "You've found some water runes!")
Items.EARTH_RUNE_557 -> sendItemDialogue(player, Items.EARTH_RUNE_557, "You've found some earth runes!")
Items.FIRE_RUNE_554 -> sendItemDialogue(player, Items.FIRE_RUNE_554, "You've found some fire runes!")
Items.BRONZE_ARROW_882 -> sendItemDialogue(player, Items.BRONZE_ARROW_882, "You've found some bronze arrows!")
Items.BRONZE_BOLTS_877 -> sendItemDialogue(player, Items.BRONZE_BOLTS_877, "You've found some bronze bolts!")
Items.IRON_ARROW_884 -> sendItemDialogue(player, Items.IRON_ARROW_884, "You've found some iron arrows!")
Items.ATTACK_POTION2_123 -> sendItemDialogue(player, Items.ATTACK_POTION2_123, "You've found an attack potion!")
Items.STRENGTH_POTION2_117 -> sendItemDialogue(player, Items.STRENGTH_POTION2_117, "You've found a strength potion!")
Items.DEFENCE_POTION2_135 -> sendItemDialogue(player, Items.DEFENCE_POTION2_135, "You've found a defence potion!")
}
setAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0))
} else {
sendMessage(player,"You find nothing of interest.")
}
return@on true
}
on(Scenery.CHEST_3636, SCENERY, "search") { player, node ->
sendMessage(player,"You find nothing of interest.")
return@on true
}
on(Scenery.WALL_3626, IntType.SCENERY, "open") { player, node ->
sendMessage(player, "That bit doesn't open.") // 0xBrLo9woIY
return@on true
}
on(Scenery.WALL_3628, IntType.SCENERY, "open") { player, node ->
// Door opening workaround
// Ignore 3629(WALL_3629) and 3630(WALL_3630) in handleAutowalkDoor ignoreSecondDoor
DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery)
return@on true
}
on(Scenery.STRANGE_SHRINE_3634, IntType.SCENERY, "touch") { player, node ->
player.unhook(this)
closeOverlay(player)
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
lock(player, 6)
sendGraphics(Graphics(86, 0, 3), player.location)
animate(player,862)
return@queueScript delayScript(player, 6)
}
1 -> {
lock(player, 6)
sendGraphics(Graphics(1576, 0, 0), player.location)
animate(player,8939)
playAudio(player, Sounds.TELEPORT_ALL_200)
return@queueScript delayScript(player, 3)
}
2 -> {
returnPlayer(player)
sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941)
closeOverlay(player)
return@queueScript delayScript(player, 1)
}
3 -> {
calculateLoot(player)
removeAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT)
removeAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN)
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
return@on true
}
}
override fun process(entity: Entity, event: TickEvent) {
if (entity is Player) {
if (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0) {
setAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) - 1)
}
setVarp(entity, MAZE_TIMER_VARP, (getAttribute(entity, MAZE_ATTRIBUTE_TICKS_LEFT, 0) / 3), false)
}
}
override fun defineAreaBorders(): Array<ZoneBorders> {
return arrayOf(getRegionBorders(11591))
}
override fun getRestrictions(): Array<ZoneRestriction> {
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
}
override fun areaEnter(entity: Entity) {
if (entity is Player) {
sendMessage(entity, "Head for the center of the maze.")
entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12)
openOverlay(entity, MAZE_TIMER_INTERFACE)
}
}
override fun areaLeave(entity: Entity, logout: Boolean) {
if (entity is Player) {
entity.interfaceManager.restoreTabs()
closeOverlay(entity)
entity.unhook(this)
}
}
override fun entityStep(entity: Entity, location: Location, lastLocation: Location) {
if (entity is Player) {
entity.hook(Event.Tick, this)
}
}
}

View file

@ -0,0 +1,57 @@
package content.global.ame.events.maze
import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.*
import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.TeleportManager
import core.game.system.timer.impl.AntiMacro
import core.game.world.map.Location
import core.game.world.map.build.DynamicRegion
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.NPCs
import org.rs09.consts.Sounds
class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.MYSTERIOUS_OLD_MAN_410) {
override fun init() {
super.init()
sendChat("Aha, you'll do ${player.username}!")
face(player)
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
lock(player, 6)
sendGraphics(Graphics(1576, 0, 0), player.location)
animate(player,8939)
playAudio(player, Sounds.TELEPORT_ALL_200)
return@queueScript delayScript(player, 3)
}
1 -> {
MazeInterface.initMaze(player)
// Note: This event is NOT instanced:
// Sources:
// https://youtu.be/2gpzn9oNdy0 (2007)
// https://youtu.be/Tni1HURgnxg (2008)
// https://youtu.be/igdwDZOv9LU (2008)
// https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for."
// https://youtu.be/FMuKZm-Ikgs (2011)
// val region = DynamicRegion.create(11591)
kidnapPlayer(player, MazeInterface.STARTING_POINTS.random(), TeleportManager.TeleportType.INSTANT) // 10 random spots
AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941)
removeAttribute(player, MazeInterface.MAZE_ATTRIBUTE_CHESTS_OPEN)
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
}
override fun talkTo(npc: NPC) {
// Do nothing.
}
}

View file

@ -1,6 +1,7 @@
package content.global.ame.events.pillory
import content.global.ame.RandomEvents
import content.global.ame.returnPlayer
import core.api.*
import core.game.dialogue.FacialExpression
import core.game.interaction.IntType
@ -42,11 +43,10 @@ import org.rs09.consts.Sounds
class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
companion object {
const val PILLORY_LOCK_INTERFACE = 189
const val PILLORY_ATRRIBUTE_RETURN_LOC = "/save:original-loc"
const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys"
const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock"
const val PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct"
const val PILLORY_ATRRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct"
const val PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct"
const val PILLORY_ATTRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct"
val LOCATIONS = arrayOf(
// Varrock Cages
@ -64,8 +64,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
)
fun initPillory(player: Player) {
setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3)
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)
setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.")
}
@ -82,8 +82,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0)
player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0)
val numberToGetCorrect = getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3)
val correctCount = getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)
val numberToGetCorrect = getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
val correctCount = getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
for (i in 1.. 6) {
// Set if lock is red or green.
if (i <= correctCount) {
@ -101,12 +101,12 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1)
if (keys[buttonID] == lock) {
// CORRECT ANSWER
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + 1)
if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, -1)) {
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + 1)
if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, -1)) {
player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!")
sendMessage(player, "You've escaped!")
removeAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT)
removeAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER)
removeAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT)
removeAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER)
closeInterface(player)
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
@ -120,10 +120,9 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
1 -> {
val loot = RandomEvents.CERTER.loot!!.roll(player)[0]
addItemOrDrop(player, loot.id, loot.amount)
teleport(player, getAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0)))
returnPlayer(player)
sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941)
removeAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC)
closeInterface(player)
return@queueScript stopExecuting(player)
}
@ -137,19 +136,19 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
true,
"",
"Correct!",
"" + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + " down, " +
(getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)) + " to go!")
"" + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + " down, " +
(getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)) + " to go!")
// Animation for the star, but it doesn't work.
player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1), false)
sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1))
player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1), false)
sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1))
} else {
// WRONG ANSWER
player.dialogueInterpreter.close()
player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.")
if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) {
setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1)
if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) {
setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1)
}
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)
setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
closeInterface(player)
}
}
@ -201,7 +200,7 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
}
override fun getRestrictions(): Array<ZoneRestriction> {
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT)
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
}
override fun areaEnter(entity: Entity) {

View file

@ -1,10 +1,12 @@
package content.global.ame.events.pillory
import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.*
import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.TeleportManager
import core.game.system.timer.impl.AntiMacro
import core.game.world.map.Location
import core.game.world.update.flag.context.Graphics
@ -29,11 +31,9 @@ class PilloryNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(N
return@queueScript delayScript(player, 3)
}
1 -> {
if (getAttribute<Location?>(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, null) == null) {
setAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, player.location)
}
PilloryInterface.initPillory(player)
teleport(player, PilloryInterface.LOCATIONS.random()) // 9 random spots!
val dest = PilloryInterface.LOCATIONS.random() //9 random spots!
kidnapPlayer(player, dest, TeleportManager.TeleportType.INSTANT)
AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941)

View file

@ -0,0 +1,37 @@
package content.global.ame.events.quizmaster
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction
import org.rs09.consts.NPCs
class QuizMasterBorders : MapArea {
override fun defineAreaBorders(): Array<ZoneBorders> {
return arrayOf(getRegionBorders(7754))
}
override fun getRestrictions(): Array<ZoneRestriction> {
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
}
override fun areaEnter(entity: Entity) {
if (entity is Player) {
entity.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 12)
face(entity, Location(1952, 4768, 1))
animate(entity,2378)
openDialogue(entity, QuizMasterDialogueFile(), NPC(NPCs.QUIZ_MASTER_2477))
}
}
override fun areaLeave(entity: Entity, logout: Boolean) {
if (entity is Player) {
entity.interfaceManager.restoreTabs()
//closeOverlay(entity)
}
}
}

View file

@ -0,0 +1,129 @@
package content.global.ame.events.quizmaster
import content.global.ame.returnPlayer
import core.ServerConstants
import core.api.*
import core.api.utils.WeightBasedTable
import core.api.utils.WeightedItem
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player
import core.tools.END_DIALOGUE
import org.rs09.consts.Components
import org.rs09.consts.Items
class QuizMasterDialogueFile : DialogueFile() {
companion object {
const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191
const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct"
const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer"
/*
// Golden Models:
8828 ADAMANT_BATTLEAXE_1371
8829 SALMON_329
8830 TROUT_333
8831 NECKLACE
8832 WOODEN_SHIELD_1171
8833 BRONZE_MED_HELM_1139
8834 RING
8835 SECATEURS_5329
8836 BRONZE_SWORD_1277
8837 GARDENING_TROWEL_5325
*/
val sets = arrayOf(
intArrayOf(8828, 8829, 8829),
intArrayOf(8831, 8837, 8835),
intArrayOf(8830, 8832, 8833),
intArrayOf(8835, 8834, 8831),
intArrayOf(8837, 8836, 8828),
)
fun randomQuestion(player: Player): Int {
val randomSet = intArrayOf(*sets.random())
val answer = intArrayOf(*randomSet)[0]
randomSet.shuffle()
val correctButton = randomSet.indexOf(answer) + 2 // buttons are 3,4,5
player.packetDispatch.sendModelOnInterface(randomSet[0], QUIZMASTER_INTERFACE, 6, 512)
player.packetDispatch.sendModelOnInterface(randomSet[1], QUIZMASTER_INTERFACE, 7, 512)
player.packetDispatch.sendModelOnInterface(randomSet[2], QUIZMASTER_INTERFACE, 8, 512)
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 6, 512,0,0)
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 7, 512,0,0)
player.packetDispatch.sendAngleOnInterface(QUIZMASTER_INTERFACE, 8, 512,0,0)
return correctButton
}
// Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas.
val tableRoll = WeightBasedTable.create(
WeightedItem(Items.LAMP_6796, 1, 1, 1.0, false),
WeightedItem(Items.CABBAGE_1965, 1, 1, 1.0, false),
WeightedItem(Items.DIAMOND_1601, 1, 1, 1.0, false),
WeightedItem(Items.BUCKET_1925, 1, 1, 1.0, false),
WeightedItem(Items.FLIER_956, 1, 1, 1.0, false),
WeightedItem(Items.OLD_BOOT_685, 1, 1, 1.0, false),
WeightedItem(Items.BODY_RUNE_559, 1, 1, 1.0, false),
WeightedItem(Items.ONION_1957, 1, 1, 1.0, false),
WeightedItem(Items.MITHRIL_SCIMITAR_1329, 1, 1, 1.0, false),
WeightedItem(Items.CASKET_405, 1, 1, 1.0, false),
WeightedItem(Items.STEEL_PLATEBODY_1119, 1, 1, 1.0, false),
WeightedItem(Items.NATURE_RUNE_561, 20, 20, 1.0, false),
)
}
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> npc(FacialExpression.FRIENDLY,"WELCOME to the GREATEST QUIZ SHOW in the", "whole of ${ServerConstants.SERVER_NAME}:", "<col=8A0808>O D D</col> <col=8A088A>O N E</col> <col=08088A>O U T</col>").also { stage++ }
1 -> player(FacialExpression.THINKING, "I'm sure I didn't ask to take part in a quiz show...").also { stage++ }
2 -> npc(FacialExpression.FRIENDLY,"Please welcome our newest contestant:", "<col=FF0000>${player?.username}</col>!", "Just pick the O D D O N E O U T.", "Four questions right, and then you win!").also { stage++ }
3 -> {
setAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, randomQuestion(player!!))
player!!.interfaceManager.openChatbox(QUIZMASTER_INTERFACE)
stage++
}
4-> {
if (buttonID == getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER, 0)) {
// Correct Answer
setAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) + 1)
if (getAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) >= 4) {
npc(FacialExpression.FRIENDLY,"<col=08088A>CONGRATULATIONS!</col>", "You are a <col=8A0808>WINNER</col>!", "Please choose your <col=08088A>PRIZE</col>!")
stage = 5
} else {
npc(FacialExpression.FRIENDLY,"Wow, you're a smart one!", "You're absolutely RIGHT!", "Okay, next question!")
stage = 3
}
} else {
// Wrong Answer
npc(FacialExpression.FRIENDLY,"WRONG!", "That's just WRONG!", "Okay, next question!")
stage = 3
}
}
// Random Item should be "Mystery Box", but the current MYSTERY_BOX_6199 is already inauthentically used by Giftmas.
5 -> options("1000 Coins", "Random Item").also { stage++ }
6 -> {
resetAnimator(player!!)
returnPlayer(player!!)
when (buttonID) {
1 -> {
queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int ->
addItemOrDrop(player!!, Items.COINS_995, 1000)
return@queueScript stopExecuting(player!!)
}
}
2 -> {
queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int ->
addItemOrDrop(player!!, tableRoll.roll()[0].id)
return@queueScript stopExecuting(player!!)
}
}
}
removeAttributes(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER)
stage = END_DIALOGUE
end()
}
}
}
}

View file

@ -0,0 +1,65 @@
package content.global.ame.events.quizmaster
import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.*
import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.TeleportManager
import core.game.system.timer.impl.AntiMacro
import core.game.world.map.Location
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.NPCs
import org.rs09.consts.Sounds
/**
* Quiz Master NPC:
*
* https://www.youtube.com/watch?v=EFAWSiPTfcM
* https://www.youtube.com/watch?v=caWn7pE2mkE
* https://www.youtube.com/watch?v=Bc1gAov2o4w
* https://www.youtube.com/watch?v=oHU8-MUarxE
* https://www.youtube.com/watch?v=wvjYiF4v9tI
* https://www.youtube.com/watch?v=dC6rlSnXEfw
*/
class QuizMasterNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.QUIZ_MASTER_2477) {
override fun init() {
super.init()
sendChat("Hey ${player.username}! It's your lucky day!")
queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
lock(player, 6)
sendGraphics(Graphics(1576, 0, 0), player.location)
animate(player,8939)
playAudio(player, Sounds.TELEPORT_ALL_200)
return@queueScript delayScript(player, 3)
}
1 -> {
kidnapPlayer(player, Location(1952, 4764, 1), TeleportManager.TeleportType.INSTANT)
setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0)
AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941)
sendMessage(player, "Answer four questions correctly in a row to be teleported back where you came from.")
sendMessage(player, "You will need to relog in if you lose the quiz dialog.") // Inauthentic, but there to notify the player in case.
return@queueScript delayScript(player, 6)
}
2 -> {
face(player, Location(1952, 4768, 1))
animate(player,2378)
// This is not needed as when you enter the QuizMasterBorders, it should fire off the dialogue
// openDialogue(player, QuizMasterDialogueFile(), this.asNpc())
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
}
override fun talkTo(npc: NPC) {
openDialogue(player, QuizMasterDialogueFile(), this.asNpc())
}
}

View file

@ -4,17 +4,14 @@ import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import java.lang.Integer.max
val ids = 391..396
val ids = (391..396).toList()
class RiverTrollRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(391){
override fun talkTo(npc: NPC) {}
override fun init() {
super.init()
val index = max(0, (player.properties.combatLevel / 20) - 1)
val id = ids.toList()[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat("Fishies be mine, leave dem fishies!")

View file

@ -4,17 +4,14 @@ import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import kotlin.math.max
val ids = 413..418
val ids = (413..418).toList()
class RockGolemRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(413){
override fun talkTo(npc: NPC) {}
override fun init() {
super.init()
val index = max(0,(player.properties.combatLevel / 20) - 1)
val id = ids.toList()[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat("Raarrrgghh! Flee human!")

View file

@ -4,15 +4,13 @@ import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import kotlin.math.*
class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(425){
val ids = (425..430).toList()
override fun talkTo(npc: NPC) {}
override fun init() {
super.init()
val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1))
val id = ids[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat("Leave this place!")

View file

@ -32,4 +32,8 @@ class StrangePlantBehavior() : NPCBehavior(NPCs.STRANGE_PLANT_408) {
override fun onDeathStarted(self: NPC, killer: Entity) {
AntiMacro.terminateEventNpc(killer.asPlayer())
}
}
override fun getXpMultiplier(self: NPC, attacker: Entity): Double {
return super.getXpMultiplier(self, attacker) / 16.0
}
}

View file

@ -1,4 +1,4 @@
package content.global.ame.events.supriseexam
package content.global.ame.events.surpriseexam
import core.game.component.Component
import core.game.dialogue.FacialExpression

View file

@ -1,7 +1,7 @@
package content.global.ame.events
import core.game.node.entity.player.Player
import content.global.ame.events.supriseexam.SurpriseExamUtils
import content.global.ame.events.surpriseexam.SurpriseExamUtils
import core.game.dialogue.DialogueFile
import core.game.system.timer.impl.AntiMacro

View file

@ -1,4 +1,4 @@
package content.global.ame.events.supriseexam
package content.global.ame.events.surpriseexam
import core.game.dialogue.DialogueFile
import core.tools.END_DIALOGUE

View file

@ -1,4 +1,4 @@
package content.global.ame.events.supriseexam
package content.global.ame.events.surpriseexam
import core.game.node.entity.npc.NPC
import org.rs09.consts.Components

View file

@ -1,4 +1,4 @@
package content.global.ame.events.supriseexam
package content.global.ame.events.surpriseexam
import core.game.component.Component
import core.game.node.entity.player.Player
@ -10,6 +10,7 @@ import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import content.global.handlers.iface.ExperienceInterface
import core.api.MapArea
import core.api.removeItem
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction
@ -23,7 +24,7 @@ class SupriseExamListeners : InteractionListener, MapArea {
return@on true
}
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open"){ player, node ->
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open") { player, node ->
val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1)
if(correctDoor == -1){
@ -42,7 +43,7 @@ class SupriseExamListeners : InteractionListener, MapArea {
on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ ->
player.setAttribute("caller") { skill: Int, p: Player ->
if (p.inventory.remove(Item(Items.BOOK_OF_KNOWLEDGE_11640))) {
if (removeItem(p, Items.BOOK_OF_KNOWLEDGE_11640)) {
val level = p.skills.getStaticLevel(skill)
val experience = level * 15.0
p.skills.addExperience(skill, experience)

View file

@ -1,22 +1,18 @@
package content.global.ame.events.supriseexam
package content.global.ame.events.surpriseexam
import core.Server
import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.*
import core.game.node.entity.impl.PulseType
import core.game.node.entity.player.Player
import core.game.node.item.GroundItemManager
import core.game.node.item.Item
import core.game.system.task.Pulse
import core.game.world.map.Location
import org.rs09.consts.Components
import org.rs09.consts.Items
import core.ServerConstants
import core.game.node.entity.player.link.TeleportManager
object SurpriseExamUtils {
val SE_KEY_LOC = "/save:original-loc"
val SE_KEY_INDEX = "supexam:index"
val SE_LOGOUT_KEY = "suprise_exam"
val SE_DOOR_KEY = "supexam:door"
val INTER_PATTERN_CHILDS = intArrayOf(6,7,8)
val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13)
@ -30,20 +26,13 @@ object SurpriseExamUtils {
intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311)
)
fun teleport(player: Player){
if (getAttribute(player, SE_KEY_LOC, null) == null) {
player.setAttribute(SE_KEY_LOC, player.location)
}
registerLogoutListener(player, SE_LOGOUT_KEY){p ->
p.location = getAttribute(p, SE_KEY_LOC, ServerConstants.HOME_LOCATION)
}
player.properties.teleportLocation = Location.create(1886, 5025, 0)
fun teleport(player: Player) {
kidnapPlayer(player, Location.create(1886, 5025, 0), TeleportManager.TeleportType.INSTANT)
}
fun cleanup(player: Player){
player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC, ServerConstants.HOME_LOCATION)
clearLogoutListener(player, SE_LOGOUT_KEY)
removeAttributes(player, SE_KEY_LOC, SE_KEY_INDEX, SE_KEY_CORRECT)
returnPlayer(player)
removeAttributes(player, SE_KEY_INDEX, SE_KEY_CORRECT)
player.pulseManager.run(object : Pulse(2){
override fun pulse(): Boolean {
addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640)

View file

@ -4,17 +4,14 @@ import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import kotlin.math.max
val ids = 438..443
val ids = (438..443).toList()
class TreeSpiritRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(438){
override fun talkTo(npc: NPC) {}
override fun init() {
super.init()
val index = max(0,(player.properties.combatLevel / 20) - 1)
val id = ids.toList()[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat("Leave these woods and never return!")

View file

@ -4,15 +4,13 @@ import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import content.global.ame.RandomEventNPC
import core.api.utils.WeightBasedTable
import kotlin.math.*
class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(419){
val ids = (419..424).toList()
override fun talkTo(npc: NPC) {}
override fun init() {
super.init()
val index = max(0, min(ids.size, (player.properties.combatLevel / 20) - 1))
val id = ids[index]
val id = idForCombatLevel(ids, player)
this.transform(id)
this.attack(player)
sendChat("Brainsssss!")

View file

@ -7,8 +7,6 @@ import core.api.*
import core.game.bots.*
import core.game.ge.GrandExchange
import core.game.interaction.DestinationFlag
import core.game.interaction.IntType
import core.game.interaction.InteractionListeners
import core.game.interaction.MovementPulse
import core.game.node.Node
import core.game.node.entity.skill.Skills
@ -16,6 +14,7 @@ import core.game.node.item.Item
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import content.data.Quests
@PlayerCompatible
@ScriptName("Falador Cannonball Smelter")
@ -273,6 +272,6 @@ class CannonballSmelter : Script() {
skills.put(Skills.HITPOINTS,99)
skills.put(Skills.DEFENCE,99)
skills.put(Skills.SMITHING,35)
quests.add("Dwarf Cannon")
quests.add(Quests.DWARF_CANNON)
}
}

View file

@ -22,7 +22,7 @@ public class ManDialoguePlugin extends DialoguePlugin {
/**
* The NPC ids that use this dialogue plugin.
*/
private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 351, 352, 353, 354, 359, 360, 361, 362, 363, 726, 727, 728, 729, 730, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,};
private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,};
public ManDialoguePlugin() {
}

View file

@ -36,17 +36,21 @@ public final class ClanInterfacePlugin extends ComponentPlugin {
switch (component.getId()) {
case 589:
switch (button) {
case 9:
if (player.getInterfaceManager().getComponent(590) != null) {
player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'");
case 9:
if (player.getInterfaceManager().getComponent(590) != null) {
player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'");
return true;
}
ClanRepository.openSettings(player);
return true;
}
ClanRepository.openSettings(player);
return true;
case 14:
player.getDetails().getCommunication().toggleLootshare(player);
return true;
case 14:
if (player.getIronmanManager().checkRestriction()) {
return false;
}
player.getDetails().getCommunication().toggleLootshare(player);
return true;
}
break;
case 590:
final ClanRepository clan = ClanRepository.get(player.getName(), true);

View file

@ -10,6 +10,7 @@ import core.plugin.Initializable
import core.plugin.Plugin
import core.tools.Log
import org.rs09.consts.Sounds
import content.data.Quests
/**
* Represents the experience interface.
@ -78,15 +79,15 @@ class ExperienceInterface() : ComponentPlugin() {
}
private fun checkHerblore(player: Player): Boolean{
return (player.questRepository.isComplete("Druidic Ritual"))
return (player.questRepository.isComplete(Quests.DRUIDIC_RITUAL))
}
private fun checkSummoning(player: Player): Boolean{
return player.questRepository.isComplete("Wolf Whistle")
return player.questRepository.isComplete(Quests.WOLF_WHISTLE)
}
private fun checkRunecrafting(player: Player): Boolean{
return player.questRepository.isComplete("Rune Mysteries")
return player.questRepository.isComplete(Quests.RUNE_MYSTERIES)
}
companion object {

View file

@ -10,7 +10,7 @@ import core.game.world.GameWorld
import core.game.world.map.Location
import core.game.world.map.RegionManager
import core.tools.RandomFunction
import content.data.Quests
/**
* Handles the fairy ring interface
@ -179,7 +179,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
AKS(Location.create(2571, 2956, 0), "Feldip Hills: Jungle Hunter area", 25),
ALQ(Location.create(3597, 3495, 0), "Morytania: Haunted Woods east of Canifis", 27) {
override fun checkAccess(player: Player) : Boolean {
return requireQuest(player, "Priest in Peril", "to use this ring.")
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
}
},
ALS(Location.create(2644, 3495, 0), "Kandarin: McGrubor's Wood", 29),
@ -191,7 +191,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
BKQ(Location.create(3041, 4532, 0), "Other realms: Enchanted Valley", 39),
BKR(Location.create(3469, 3431, 0), "Morytania: Mort Myre, south of Canifis", 40) {
override fun checkAccess(player: Player) : Boolean {
return requireQuest(player, "Priest in Peril", "to use this ring.")
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
}
},
BLP(Location.create(2437, 5126, 0), "Dungeons: TzHaar area", 42),
@ -199,7 +199,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
BLR(Location.create(2740, 3351, 0), "Kandarin: Legends' Guild", 44),
CIP(Location.create(2513, 3884, 0), "Islands: Miscellania", 46) {
override fun checkAccess(player: Player): Boolean {
return requireQuest(player, "Fremennik Trials", "to use this ring.")
return requireQuest(player, Quests.THE_FREMENNIK_TRIALS, "to use this ring.")
}
},
CIQ(Location.create(2528, 3127, 0), "Kandarin: North-west of Yanille", 47),
@ -208,7 +208,7 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
CKR(Location.create(2801, 3003, 0), "Karamja: South of Tai Bwo Wannai Village", 56),
CKS(Location.create(3447, 3470, 0), "Morytania: Canifis", 57) {
override fun checkAccess(player: Player) : Boolean {
return requireQuest(player, "Priest in Peril", "to use this ring.")
return requireQuest(player, Quests.PRIEST_IN_PERIL, "to use this ring.")
}
},
CLP(Location.create(3082, 3206, 0), "Islands: South of Draynor Village", 58),

View file

@ -9,6 +9,7 @@ import core.plugin.Initializable;
import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
import content.data.Quests;
/**
* Represents the prayer interface.
@ -27,7 +28,7 @@ public final class PrayerTabInterface extends ComponentPlugin {
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
final PrayerType type = PrayerType.get(button);
if (type == PrayerType.CHIVALRY || type == PrayerType.PIETY)
if (!hasRequirement(player, "King's Ransom"))
if (!hasRequirement(player, Quests.KINGS_RANSOM))
return true;
if (type == null) {
return true;

View file

@ -10,12 +10,13 @@ import kotlin.math.*
import java.util.*
import org.rs09.consts.*
import content.data.Quests
object QuestTabUtils {
@JvmStatic
fun showRequirementsInterface (player: Player, button: Int) {
val questName = getNameForButton (button)
val questReq = QuestRequirements.values().filter { it.questName.equals(questName, true) }.firstOrNull() ?: return
fun showRequirementsInterface(player: Player, button: Int) {
val questName = getNameForButton(button)
val questReq = QuestRequirements.values().filter { it.quest.questName == questName }.firstOrNull() ?: return
var (isMet, unmetReqs) = QuestReq(questReq).evaluate(player)
var messageList = ArrayList<String>()
@ -27,7 +28,7 @@ object QuestTabUtils {
closeInterface(player)
for (req in unmetReqs) {
if (req is QuestReq)
questList.add(req.questReq.questName)
questList.add(req.questReq.quest.questName)
else if (req is SkillReq) {
if (statMap[req.skillId] == null || (statMap[req.skillId] != null && statMap[req.skillId]!! < req.level))
statMap[req.skillId] = req.level
@ -82,163 +83,163 @@ object QuestTabUtils {
openInterface(player, Components.QUESTJOURNAL_SCROLL_275)
}
fun getNameForButton (button: Int) : String {
val name = when (button) {
10 -> "Myths of the White Lands"
11 -> "Myths of the White Lands"
private fun getNameForButton(button: Int) : String {
val quest = when (button) {
10 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
11 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
12 -> "Free Quests"
13 -> "Black Knights' Fortress"
14 -> "Cook's Assistant"
15 -> "Demon Slayer"
16 -> "Doric's Quest"
17 -> "Dragon Slayer"
18 -> "Ernest the Chicken"
19 -> "Goblin Diplomacy"
20 -> "Imp Catcher"
21 -> "The Knight's Sword"
22 -> "Pirate's Treasure"
23 -> "Prince Ali Rescue"
24 -> "The Restless Ghost"
25 -> "Romeo & Juliet"
26 -> "Rune Mysteries"
27 -> "Sheep Shearer"
28 -> "Shield of Arrav"
29 -> "Vampire Slayer"
30 -> "Witch's Potion"
13 -> Quests.BLACK_KNIGHTS_FORTRESS.questName
14 -> Quests.COOKS_ASSISTANT.questName
15 -> Quests.DEMON_SLAYER.questName
16 -> Quests.DORICS_QUEST.questName
17 -> Quests.DRAGON_SLAYER.questName
18 -> Quests.ERNEST_THE_CHICKEN.questName
19 -> Quests.GOBLIN_DIPLOMACY.questName
20 -> Quests.IMP_CATCHER.questName
21 -> Quests.THE_KNIGHTS_SWORD.questName
22 -> Quests.PIRATES_TREASURE.questName
23 -> Quests.PRINCE_ALI_RESCUE.questName
24 -> Quests.THE_RESTLESS_GHOST.questName
25 -> Quests.ROMEO_JULIET.questName
26 -> Quests.RUNE_MYSTERIES.questName
27 -> Quests.SHEEP_SHEARER.questName
28 -> Quests.SHIELD_OF_ARRAV.questName
29 -> Quests.VAMPIRE_SLAYER.questName
30 -> Quests.WITCHS_POTION.questName
31 -> "Members' Quests"
32 -> "Animal Magnetism"
33 -> "Between a Rock..."
34 -> "Big Chompy Bird Hunting"
35 -> "Biohazard"
36 -> "Cabin Fever"
37 -> "Clock Tower"
38 -> "Contact!"
39 -> "Zogre Flesh Eaters"
40 -> "Creature of Fenkenstrain"
41 -> "Darkness of Hallowvale"
42 -> "Death to the Dorgeshuun"
43 -> "Death Plateau"
44 -> "Desert Treasure"
45 -> "Devious Minds"
46 -> "The Dig Site"
47 -> "Druidic Ritual"
48 -> "Dwarf Cannon"
49 -> "Eadgar's Ruse"
50 -> "Eagles' Peak"
51 -> "Elemental Workshop I"
52 -> "Elemental Workshop II"
53 -> "Enakhra's Lament"
54 -> "Enlightened Journey"
55 -> "The Eyes of Glouphrie"
56 -> "Fairytale I - Growing Pains"
57 -> "Fairytale II - Cure a Queen"
58 -> "Family Crest"
59 -> "The Feud"
60 -> "Fight Arena"
61 -> "Fishing Contest"
62 -> "Forgettable Tale..."
63 -> "The Fremennik Trials"
64 -> "Waterfall Quest"
65 -> "Garden of Tranquillity"
66 -> "Gertrude's Cat"
67 -> "Ghosts Ahoy"
68 -> "The Giant Dwarf"
69 -> "The Golem"
70 -> "The Grand Tree"
71 -> "The Hand in the Sand"
72 -> "Haunted Mine"
73 -> "Hazeel Cult"
74 -> "Heroes' Quest"
75 -> "Holy Grail"
76 -> "Horror from the Deep"
77 -> "Icthlarin's Little Helper"
78 -> "In Aid of the Myreque"
79 -> "In Search of the Myreque"
80 -> "Jungle Potion"
81 -> "Legend's Quest"
82 -> "Lost City"
83 -> "The Lost Tribe"
84 -> "Lunar Diplomacy"
85 -> "Making History"
86 -> "Merlin's Crystal"
87 -> "Monkey Madness"
88 -> "Monk's Friend"
89 -> "Mountain Daughter"
90 -> "Mourning's End Part I"
91 -> "Mourning's End Part II"
92 -> "Murder Mystery"
93 -> "My Arm's Big Adventure"
94 -> "Nature Spirit"
95 -> "Observatory Quest"
96 -> "One Small Favour"
97 -> "Plague City"
98 -> "Priest in Peril"
99 -> "Rag and Bone Man"
100 -> "Ratcatchers"
101 -> "Recipe for Disaster"
102 -> "Recruitment Drive"
103 -> "Regicide"
104 -> "Roving Elves"
105 -> "Royal Trouble"
106 -> "Rum Deal"
107 -> "Scorpion Catcher"
108 -> "Sea Slug"
109 -> "The Slug Menace"
110 -> "Shades of Mort'ton"
111 -> "Shadow of the Storm"
112 -> "Sheep Herder"
113 -> "Shilo Village"
114 -> "A Soul's Bane"
115 -> "Spirits of the Elid"
116 -> "Swan Song"
117 -> "Tai Bwo Wannai Trio"
118 -> "A Tail of Two Cats"
119 -> "Tears of Guthix"
120 -> "Temple of Ikov"
121 -> "Throne of Miscellania"
122 -> "The Tourist Trap"
123 -> "Witch's House"
124 -> "Tree Gnome Village"
125 -> "Tribal Totem"
126 -> "Troll Romance"
127 -> "Troll Stronghold"
128 -> "Underground Pass"
129 -> "Wanted!"
130 -> "Watchtower"
131 -> "Cold War"
132 -> "The Fremennik Isles"
133 -> "Tower of Life"
134 -> "The Great Brain Robbery"
135 -> "What Lies Below"
136 -> "Olaf's Quest"
137 -> "Another Slice of H.A.M"
138 -> "Dream Mentor"
139 -> "Grim Tales"
140 -> "King's Ransom"
141 -> "The Path of Glouphrie"
142 -> "Back to my Roots"
143 -> "Land of the Goblins"
144 -> "Dealing with Scabaras"
145 -> "Wolf Whistle"
146 -> "As a First Resort..."
147 -> "Catapult Construction"
148 -> "Kennith's Concerns"
149 -> "Legacy of Seergaze"
150 -> "Perils of Ice Mountain"
151 -> "TokTz-Ket-Dill"
152 -> "Smoking Kills"
153 -> "Rocking Out"
154 -> "Spirit of Summer"
155 -> "Meeting History"
156 -> "All Fired Up"
157 -> "Summer's End"
158 -> "Defender of Varrock"
159 -> "Swept Away"
160 -> "While Guthix Sleeps"
161 -> "In Pyre Need"
162 -> "Myths of the White Lands"
32 -> Quests.ANIMAL_MAGNETISM.questName
33 -> Quests.BETWEEN_A_ROCK.questName
34 -> Quests.BIG_CHOMPY_BIRD_HUNTING.questName
35 -> Quests.BIOHAZARD.questName
36 -> Quests.CABIN_FEVER.questName
37 -> Quests.CLOCK_TOWER.questName
38 -> Quests.CONTACT.questName
39 -> Quests.ZOGRE_FLESH_EATERS.questName
40 -> Quests.CREATURE_OF_FENKENSTRAIN.questName
41 -> Quests.DARKNESS_OF_HALLOWVALE.questName
42 -> Quests.DEATH_TO_THE_DORGESHUUN.questName
43 -> Quests.DEATH_PLATEAU.questName
44 -> Quests.DESERT_TREASURE.questName
45 -> Quests.DEVIOUS_MINDS.questName
46 -> Quests.THE_DIG_SITE.questName
47 -> Quests.DRUIDIC_RITUAL.questName
48 -> Quests.DWARF_CANNON.questName
49 -> Quests.EADGARS_RUSE.questName
50 -> Quests.EAGLES_PEAK.questName
51 -> Quests.ELEMENTAL_WORKSHOP_I.questName
52 -> Quests.ELEMENTAL_WORKSHOP_II.questName
53 -> Quests.ENAKHRAS_LAMENT.questName
54 -> Quests.ENLIGHTENED_JOURNEY.questName
55 -> Quests.THE_EYES_OF_GLOUPHRIE.questName
56 -> Quests.FAIRYTALE_I_GROWING_PAINS.questName
57 -> Quests.FAIRYTALE_II_CURE_A_QUEEN.questName
58 -> Quests.FAMILY_CREST.questName
59 -> Quests.THE_FEUD.questName
60 -> Quests.FIGHT_ARENA.questName
61 -> Quests.FISHING_CONTEST.questName
62 -> Quests.FORGETTABLE_TALE.questName
63 -> Quests.THE_FREMENNIK_TRIALS.questName
64 -> Quests.WATERFALL_QUEST.questName
65 -> Quests.GARDEN_OF_TRANQUILITY.questName
66 -> Quests.GERTRUDES_CAT.questName
67 -> Quests.GHOSTS_AHOY.questName
68 -> Quests.THE_GIANT_DWARF.questName
69 -> Quests.THE_GOLEM.questName
70 -> Quests.THE_GRAND_TREE.questName
71 -> Quests.THE_HAND_IN_THE_SAND.questName
72 -> Quests.HAUNTED_MINE.questName
73 -> Quests.HAZEEL_CULT.questName
74 -> Quests.HEROES_QUEST.questName
75 -> Quests.HOLY_GRAIL.questName
76 -> Quests.HORROR_FROM_THE_DEEP.questName
77 -> Quests.ICTHLARINS_LITTLE_HELPER.questName
78 -> Quests.IN_AID_OF_THE_MYREQUE.questName
79 -> Quests.IN_SEARCH_OF_THE_MYREQUE.questName
80 -> Quests.JUNGLE_POTION.questName
81 -> Quests.LEGENDS_QUEST.questName
82 -> Quests.LOST_CITY.questName
83 -> Quests.THE_LOST_TRIBE.questName
84 -> Quests.LUNAR_DIPLOMACY.questName
85 -> Quests.MAKING_HISTORY.questName
86 -> Quests.MERLINS_CRYSTAL.questName
87 -> Quests.MONKEY_MADNESS.questName
88 -> Quests.MONKS_FRIEND.questName
89 -> Quests.MOUNTAIN_DAUGHTER.questName
90 -> Quests.MOURNINGS_END_PART_I.questName
91 -> Quests.MOURNINGS_END_PART_II.questName
92 -> Quests.MURDER_MYSTERY.questName
93 -> Quests.MY_ARMS_BIG_ADVENTURE.questName
94 -> Quests.NATURE_SPIRIT.questName
95 -> Quests.OBSERVATORY_QUEST.questName
96 -> Quests.ONE_SMALL_FAVOUR.questName
97 -> Quests.PLAGUE_CITY.questName
98 -> Quests.PRIEST_IN_PERIL.questName
99 -> Quests.RAG_AND_BONE_MAN.questName
100 -> Quests.RATCATCHERS.questName
101 -> Quests.RECIPE_FOR_DISASTER.questName
102 -> Quests.RECRUITMENT_DRIVE.questName
103 -> Quests.REGICIDE.questName
104 -> Quests.ROVING_ELVES.questName
105 -> Quests.ROYAL_TROUBLE.questName
106 -> Quests.RUM_DEAL.questName
107 -> Quests.SCORPION_CATCHER.questName
108 -> Quests.SEA_SLUG.questName
109 -> Quests.THE_SLUG_MENACE.questName
110 -> Quests.SHADES_OF_MORTTON.questName
111 -> Quests.SHADOW_OF_THE_STORM.questName
112 -> Quests.SHEEP_HERDER.questName
113 -> Quests.SHILO_VILLAGE.questName
114 -> Quests.A_SOULS_BANE.questName
115 -> Quests.SPIRITS_OF_THE_ELID.questName
116 -> Quests.SWAN_SONG.questName
117 -> Quests.TAI_BWO_WANNAI_TRIO.questName
118 -> Quests.A_TAIL_OF_TWO_CATS.questName
119 -> Quests.TEARS_OF_GUTHIX.questName
120 -> Quests.TEMPLE_OF_IKOV.questName
121 -> Quests.THRONE_OF_MISCELLANIA.questName
122 -> Quests.THE_TOURIST_TRAP.questName
123 -> Quests.WITCHS_HOUSE.questName
124 -> Quests.TREE_GNOME_VILLAGE.questName
125 -> Quests.TRIBAL_TOTEM.questName
126 -> Quests.TROLL_ROMANCE.questName
127 -> Quests.TROLL_STRONGHOLD.questName
128 -> Quests.UNDERGROUND_PASS.questName
129 -> Quests.WANTED.questName
130 -> Quests.WATCHTOWER.questName
131 -> Quests.COLD_WAR.questName
132 -> Quests.THE_FREMENNIK_ISLES.questName
133 -> Quests.TOWER_OF_LIFE.questName
134 -> Quests.THE_GREAT_BRAIN_ROBBERY.questName
135 -> Quests.WHAT_LIES_BELOW.questName
136 -> Quests.OLAFS_QUEST.questName
137 -> Quests.ANOTHER_SLICE_OF_HAM.questName
138 -> Quests.DREAM_MENTOR.questName
139 -> Quests.GRIM_TALES.questName
140 -> Quests.KINGS_RANSOM.questName
141 -> Quests.THE_PATH_OF_GLOUPHRIE.questName
142 -> Quests.BACK_TO_MY_ROOTS.questName
143 -> Quests.LAND_OF_THE_GOBLINS.questName
144 -> Quests.DEALING_WITH_SCABARAS.questName
145 -> Quests.WOLF_WHISTLE.questName
146 -> Quests.AS_A_FIRST_RESORT.questName
147 -> Quests.CATAPULT_CONSTRUCTION.questName
148 -> Quests.KENNITHS_CONCERNS.questName
149 -> Quests.LEGACY_OF_SEERGAZE.questName
150 -> Quests.PERILS_OF_ICE_MOUNTAIN.questName
151 -> Quests.TOKTZ_KET_DILL.questName
152 -> Quests.SMOKING_KILLS.questName
153 -> Quests.ROCKING_OUT.questName
154 -> Quests.SPIRIT_OF_SUMMER.questName
155 -> Quests.MEETING_HISTORY.questName
156 -> Quests.ALL_FIRED_UP.questName
157 -> Quests.SUMMERS_END.questName
158 -> Quests.DEFENDER_OF_VARROCK.questName
159 -> Quests.SWEPT_AWAY.questName
160 -> Quests.WHILE_GUTHIX_SLEEPS.questName
161 -> Quests.IN_PYRE_NEED.questName
162 -> Quests.MYTHS_OF_THE_WHITE_LANDS.questName
else -> ""
}
return name
return quest as String
}
}

View file

@ -13,6 +13,7 @@ import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
import org.rs09.consts.Scenery
import org.rs09.consts.Sounds
import content.data.Quests
@Suppress("unused")
class EctophialListener : InteractionListener {
@ -37,7 +38,7 @@ class EctophialListener : InteractionListener {
}
on(Items.ECTOPHIAL_4251, IntType.ITEM, "empty") { player, node ->
if (!hasRequirement(player, "Ghosts Ahoy"))
if (!hasRequirement(player, Quests.GHOSTS_AHOY))
return@on true
if (player.isTeleBlocked) {

View file

@ -1,5 +1,6 @@
package content.global.handlers.item
import content.global.skill.slayer.SlayerUtils
import core.api.*
import content.global.skill.slayer.Tasks
import org.rs09.consts.Items
@ -41,7 +42,8 @@ class EnchantedGemDialogue() : DialogueFile() {
if(getSlayerTask(player!!) == Tasks.JAD) {
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill TzTok-Jad!")
} else {
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${getSlayerTaskName(player!!)}s; only ${getSlayerTaskKillsRemaining(player!!)} more to go.")
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "You're currently assigned to kill ${SlayerUtils.pluralise(
getSlayerTaskName(player!!))}; only ${getSlayerTaskKillsRemaining(player!!)} more to go.")
}
setVarp(player!!, 2502, getSlayerTaskFlags(player!!) shr 4)
stage = 1

View file

@ -4,6 +4,7 @@ import core.api.*
import core.game.node.entity.player.link.quest.QuestRepository
import org.rs09.consts.Items
import core.game.interaction.InteractionListener
import content.data.Quests
class ItemQuestRequirementListener : InteractionListener {
@ -106,7 +107,7 @@ class ItemQuestRequirementListener : InteractionListener {
/*
onEquip(fremennikIslesEquipment) { player, _ ->
if (!isQuestComplete(player, "Fremennik Isles")) {
if (!isQuestComplete(player, Quests.THE_FREMENNIK_ISLES)) {
sendMessage(player, "You must have completed The Fremennik Isles to equip this.")
return@onEquip false
}
@ -114,7 +115,7 @@ class ItemQuestRequirementListener : InteractionListener {
}
onEquip(fremennikIslesDuringQuestEquipment){ player, _ ->
if (questStage(player, "Fremennik Isles") > 0) {
if (questStage(player, Quests.THE_FREMENNIK_ISLES) > 0) {
sendMessage(player, "You must have started The Fremennik Isles to equip this.")
return@onEquip false
}
@ -123,23 +124,23 @@ class ItemQuestRequirementListener : InteractionListener {
*/
onEquip(fremennikTrialsEquipment) { player, _ ->
return@onEquip hasRequirement(player, "Fremennik Trials")
return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_TRIALS)
}
onEquip(fremennikIslesEquipment) {player, _ ->
return@onEquip hasRequirement(player, "The Fremennik Isles")
return@onEquip hasRequirement(player, Quests.THE_FREMENNIK_ISLES)
}
onEquip(avasBackpacks){ player, _ ->
return@onEquip hasRequirement(player, "Animal Magnetism")
return@onEquip hasRequirement(player, Quests.ANIMAL_MAGNETISM)
}
onEquip(lostCityWeapons){ player, _ ->
return@onEquip hasRequirement(player, "Lost City")
return@onEquip hasRequirement(player, Quests.LOST_CITY)
}
onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ ->
return@onEquip hasRequirement(player, "Legend's Quest")
return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST)
}
onEquip(questCapes) { player, _ ->
@ -152,84 +153,84 @@ class ItemQuestRequirementListener : InteractionListener {
}
onEquip(Items.WOLFBANE_2952){ player, _ ->
return@onEquip hasRequirement(player, "Priest in Peril")
return@onEquip hasRequirement(player, Quests.PRIEST_IN_PERIL)
}
onEquip(Items.ANCIENT_MACE_11061){ player, _ ->
return@onEquip hasRequirement(player, "Another Slice of H.A.M")
return@onEquip hasRequirement(player, Quests.ANOTHER_SLICE_OF_HAM)
}
onEquip(Items.ANCIENT_STAFF_4675){ player, _ ->
return@onEquip hasRequirement(player, "Desert Treasure")
return@onEquip hasRequirement(player, Quests.DESERT_TREASURE)
}
onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ ->
return@onEquip hasRequirement(player, "Elemental Workshop I")
return@onEquip hasRequirement(player, Quests.ELEMENTAL_WORKSHOP_I)
}
onEquip(crystalEquipment){ player, _ ->
return@onEquip hasRequirement(player, "Roving Elves")
return@onEquip hasRequirement(player, Quests.ROVING_ELVES)
}
onEquip(dragonSlayerEquipment) {player, _ ->
return@onEquip hasRequirement(player, "Dragon Slayer")
return@onEquip hasRequirement(player, Quests.DRAGON_SLAYER)
}
onEquip(Items.DRAGON_SCIMITAR_4587) {player, _ ->
return@onEquip hasRequirement(player, "Monkey Madness")
return@onEquip hasRequirement(player, Quests.MONKEY_MADNESS)
}
onEquip(Items.GLOVES_7462) {player, _ ->
return@onEquip hasRequirement(player, "Recipe for Disaster")
return@onEquip hasRequirement(player, Quests.RECIPE_FOR_DISASTER)
}
onEquip(Items.SLAYER_HELMET_13263) {player, _ ->
return@onEquip hasRequirement(player, "Smoking Kills")
return@onEquip hasRequirement(player, Quests.SMOKING_KILLS)
}
onEquip (Items.DRAGON_HALBERD_3204) {player, _ ->
return@onEquip hasRequirement(player, "Regicide")
return@onEquip hasRequirement(player, Quests.REGICIDE)
}
onEquip (Items.CLIMBING_BOOTS_3105) {player, _ ->
return@onEquip hasRequirement(player, "Death Plateau")
return@onEquip hasRequirement(player, Quests.DEATH_PLATEAU)
}
onEquip (godBooks) {player, _ ->
return@onEquip hasRequirement(player, "Horror from the Deep")
return@onEquip hasRequirement(player, Quests.HORROR_FROM_THE_DEEP)
}
onEquip (pharaohScepters) {player, _ ->
return@onEquip hasRequirement(player, "Icthlarin's Little Helper")
return@onEquip hasRequirement(player, Quests.ICTHLARINS_LITTLE_HELPER)
}
onEquip (Items.DRAGON_SQ_SHIELD_1187) {player, _ ->
//because I know people won't believe it: https://runescape.wiki/w/Dragon_sq_shield?oldid=899636
return@onEquip hasRequirement(player, "Legend's Quest")
return@onEquip hasRequirement(player, Quests.LEGENDS_QUEST)
}
onEquip (initiateArmour) {player, _ ->
return@onEquip hasRequirement(player, "Recruitment Drive")
return@onEquip hasRequirement(player, Quests.RECRUITMENT_DRIVE)
}
onEquip (proselyteArmour) {player, _ ->
return@onEquip hasRequirement(player, "The Slug Menace")
return@onEquip hasRequirement(player, Quests.THE_SLUG_MENACE)
}
onEquip (spiritShields) {player, _ ->
return@onEquip hasRequirement(player, "Summer's End")
return@onEquip hasRequirement(player, Quests.SUMMERS_END)
}
onEquip (Items.DRAGON_MACE_1434) {player, _ ->
return@onEquip hasRequirement(player, "Heroes' Quest")
return@onEquip hasRequirement(player, Quests.HEROES_QUEST)
}
onEquip (Items.DRAGON_BATTLEAXE_1377) {player, _ ->
return@onEquip hasRequirement(player, "Heroes' Quest")
return@onEquip hasRequirement(player, Quests.HEROES_QUEST)
}
onEquip (Items.DARKLIGHT_6746) {player, _ ->
return@onEquip hasRequirement(player, "Shadow of the Storm")
return@onEquip hasRequirement(player, Quests.SHADOW_OF_THE_STORM)
}
}
}

View file

@ -8,6 +8,7 @@ import core.game.node.entity.player.Player;
import core.plugin.Initializable;
import core.plugin.Plugin;
import content.region.morytania.quest.naturespirit.NSUtils;
import content.data.Quests;
/**
* Handles the Silver Sickle (b) to collect Mort Myre Fungus.
@ -28,7 +29,7 @@ public final class SilverSicklePlugin extends OptionHandler {
switch (option) {
case "operate":
case "cast bloom":
if(player.getQuestRepository().getQuest("Nature Spirit").getStage(player) >= 75) {
if(player.getQuestRepository().getQuest(Quests.NATURE_SPIRIT).getStage(player) >= 75) {
player.getPacketDispatch().sendAnimation(9021);
NSUtils.castBloom(player);
} else {

View file

@ -1,15 +1,14 @@
package content.global.handlers.item
import core.api.inInventory
import core.api.removeItem
import core.api.teleport
import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.Companion.ARDOUGNE_TELE_ATTRIBUTE
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.node.item.Item
import core.game.world.map.Location
import core.api.hasRequirement;
import content.data.Quests
import core.cache.def.impl.ItemDefinition;
@ -17,23 +16,23 @@ class TeleTabsListener : InteractionListener {
enum class TeleTabs(val item: Int, val location: Location, val exp: Double, val requirementCheck: (Player) -> Boolean = { true }) {
ADDOUGNE_TELEPORT(8011, Location.create(2662, 3307, 0), 61.0, {
player -> hasRequirement(player, "Plague City");
player -> getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false)
}),
AIR_ALTAR_TELEPORT(13599, Location.create(2978, 3296, 0), 0.0),
ASTRAL_ALTAR_TELEPORT(13611, Location.create(2156, 3862, 0), 0.0, {
player -> hasRequirement(player, "Lunar Diplomacy");
player -> hasRequirement(player, Quests.LUNAR_DIPLOMACY);
}),
BLOOD_ALTAR_TELEPORT(13610, Location.create(3559, 9778, 0), 0.0, {
player -> hasRequirement(player, "Legacy of Seergaze");
player -> hasRequirement(player, Quests.LEGACY_OF_SEERGAZE);
}),
BODY_ALTAR_TELEPORT(13604, Location.create(3055, 3443, 0), 0.0),
CAMELOT_TELEPORT(8010, Location.create(2757, 3477, 0), 55.5),
CHAOS_ALTAR_TELEPORT(13606, Location.create(3058, 3593, 0), 0.0),
COSMIC_ALTAR_TELEPORT(13605, Location.create(2411, 4380, 0), 0.0, {
player -> hasRequirement(player, "Lost City");
player -> hasRequirement(player, Quests.LOST_CITY);
}),
DEATH_ALTAR_TELEPORT(13609, Location.create(1863, 4639, 0), 0.0, {
player -> hasRequirement(player, "Mourning's End Part II");
player -> hasRequirement(player, Quests.MOURNINGS_END_PART_II);
}),
EARTH_ALTAR_TELEPORT(13602, Location.create(3304, 3472, 0), 0.0),
FALADOR_TELEPORT(8009, Location.create(2966, 3380, 0), 47.0),
@ -45,11 +44,11 @@ class TeleTabsListener : InteractionListener {
MIND_ALTAR_TELEPORT(13600, Location.create(2979, 3510, 0), 0.0),
NATURE_ALTAR_TELEPORT(13607, Location.create(2868, 3013, 0), 0.0),
TELEKINETIC_GRAB(8022, Location.create(2836, 3285, 0), 0.0, {
player -> hasRequirement(player, "Dragon Slayer");
player -> hasRequirement(player, Quests.DRAGON_SLAYER);
}),
VARROCK_TELEPORT(8007, Location.create(3212, 3423, 0), 35.00),
WATCH_TOWER_TELEPORT(8012, Location.create(2548, 3114, 0), 68.00, {
player -> hasRequirement(player, "Watchtower");
player -> hasRequirement(player, Quests.WATCHTOWER);
}),
WATER_ALTAR_TELEPORT(13601, Location.create(3182, 3162, 0), 0.0);
@ -68,9 +67,17 @@ class TeleTabsListener : InteractionListener {
val tabEnum = TeleTabs.forId(tab)
if (tabEnum != null && inInventory(player,tab)) {
val tabloc = tabEnum.location
if (inInventory(player, tab) && tabEnum.requirementCheck(player)) {
if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) {
removeItem(player, Item(node.id, 1))
if (inInventory(player, tab)) {
if (tabEnum.requirementCheck(player)){
if (teleport(player, tabloc, TeleportManager.TeleportType.TELETABS)) {
removeItem(player, Item(node.id, 1))
}
}
else {
when (tabEnum){
TeleTabs.ADDOUGNE_TELEPORT -> sendMessage(player, "You need to complete Plague City to use this tablet.")
else -> sendMessage(player, "You do not have the requirements to use this tablet.")
}
}
}
}

View file

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

View file

@ -1,56 +0,0 @@
package content.global.handlers.item.withnpc
import core.api.Container
import core.api.*
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
class CatOnArdougneCivilian: InteractionListener {
private val civilians = intArrayOf(
NPCs.CIVILIAN_785,
NPCs.CIVILIAN_786,
NPCs.CIVILIAN_787
)
private val cats = intArrayOf(
Items.PET_CAT_1561,
Items.PET_CAT_1562,
Items.PET_CAT_1563,
Items.PET_CAT_1564,
Items.PET_CAT_1565,
Items.PET_CAT_1566,
Items.OVERGROWN_CAT_1567,
Items.OVERGROWN_CAT_1568,
Items.OVERGROWN_CAT_1569,
Items.OVERGROWN_CAT_1570,
Items.OVERGROWN_CAT_1571,
Items.OVERGROWN_CAT_1572,
Items.LAZY_CAT_6551,
Items.LAZY_CAT_6552,
Items.LAZY_CAT_6553,
Items.LAZY_CAT_6554,
Items.WILY_CAT_6555,
Items.WILY_CAT_6556,
Items.WILY_CAT_6557,
Items.WILY_CAT_6558,
Items.WILY_CAT_6559,
Items.WILY_CAT_6560,
Items.HELL_CAT_7582,
Items.OVERGROWN_HELLCAT_7581,
Items.LAZY_HELL_CAT_7584,
Items.WILY_HELLCAT_7585,
)
override fun defineListeners() {
onUseWith(IntType.NPC,cats,*civilians){ player, used, _ ->
sendItemDialogue(player,Items.DEATH_RUNE_560,"You hand over the cat.<br>You are given 100 Death Runes.")
player.familiarManager.removeDetails(used.id)
removeItem(player,used,Container.INVENTORY)
addItem(player,Items.DEATH_RUNE_560,100)
return@onUseWith true
}
}
}

View file

@ -10,27 +10,27 @@ import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import core.game.world.GameWorld.Pulser
import content.data.Quests
class GCItemOnCat : InteractionListener {
override fun defineListeners() {
val GERTCAT = "Gertrude's Cat"
val BEND_DOWN = 827
onUseWith(IntType.NPC, Items.BUCKET_OF_MILK_1927, NPCs.GERTRUDES_CAT_2997) { player, used, with ->
if(getQuestStage(player, GERTCAT) == 20 && removeItem(player, used.asItem())){
if(getQuestStage(player, Quests.GERTRUDES_CAT) == 20 && removeItem(player, used.asItem())){
addItem(player, Items.BUCKET_1925)
animate(player, BEND_DOWN) //bend down
sendChat(with.asNpc(), "Mew!")
setQuestStage(player, GERTCAT, 30)
setQuestStage(player, Quests.GERTRUDES_CAT, 30)
}
return@onUseWith true
}
onUseWith(IntType.NPC, Items.DOOGLE_SARDINE_1552, NPCs.GERTRUDES_CAT_2997){ player, used, with ->
if(getQuestStage(player, GERTCAT) == 30 && removeItem(player, used.asItem())){
if(getQuestStage(player, Quests.GERTRUDES_CAT) == 30 && removeItem(player, used.asItem())){
animate(player, BEND_DOWN)
sendChat(with.asNpc(), "Mew!")
setQuestStage(player, GERTCAT, 40)
setQuestStage(player, Quests.GERTRUDES_CAT, 40)
}
return@onUseWith true
}
@ -42,7 +42,7 @@ class GCItemOnCat : InteractionListener {
onUseWith(IntType.NPC, Items.THREE_LITTLE_KITTENS_13236, NPCs.GERTRUDES_CAT_2997){ player, used, with ->
if(removeItem(player, used.asItem())){
setQuestStage(player, GERTCAT, 60)
setQuestStage(player, Quests.GERTRUDES_CAT, 60)
//below copied verbatim from original, I don't like it.
Pulser.submit(object : Pulse(1) {
var count = 0

View file

@ -14,6 +14,7 @@ import core.game.world.map.path.Pathfinder;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import content.data.Quests;
/**
* Represents the plugin used to handle the use with interactions.
@ -50,7 +51,7 @@ public final class GertrudeCatUsePlugin extends UseWithHandler {
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
final NPC npc = ((NPC) event.getUsedWith());
final Quest quest = player.getQuestRepository().getQuest("Gertrude's Cat");
final Quest quest = player.getQuestRepository().getQuest(Quests.GERTRUDES_CAT);
if (event.getUsedItem().getId() == 1927 && quest.getStage(player) == 20) {
if (player.getInventory().remove(event.getUsedItem())) {
player.getInventory().add(EMPTY_BUCKET);

View file

@ -5,20 +5,19 @@ import org.rs09.consts.Items
import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import content.data.Quests
class RopeOnLadyKeli : InteractionListener {
override fun defineListeners() {
val PAR = "Prince Ali Rescue"
onUseWith(IntType.NPC, Items.ROPE_954, NPCs.LADY_KELI_919) { player, used, with ->
if(getQuestStage(player, PAR) in 40..50 && getAttribute(player, "guard-drunk", false)){
if(getQuestStage(player, Quests.PRINCE_ALI_RESCUE) in 40..50 && getAttribute(player, "guard-drunk", false)){
if(removeItem(player, used.asItem())){
sendDialogue(player, "You overpower Keli, tie her up, and put her in a cupboard.")
setQuestStage(player, PAR, 50)
setQuestStage(player, Quests.PRINCE_ALI_RESCUE, 50)
setAttribute(player, "keli-gone", getWorldTicks() + 350)
}
} else {
if (getQuestStage(player, PAR) == 40){
if (getQuestStage(player, Quests.PRINCE_ALI_RESCUE) == 40){
sendMessage(player, "You need to do something about the guard first.")
}
}

View file

@ -1,7 +1,7 @@
package content.global.handlers.item.withobject
import content.data.Quests
import core.api.*
import content.region.kandarin.quest.dwarfcannon.DwarfCannon
import core.game.node.Node
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
@ -19,8 +19,8 @@ class AmmoMouldOnFurnace : InteractionListener {
private fun cannonBallOnUseWithHandler(player: Player, used: Node, with: Node): Boolean {
face(player, with.centerLocation)
if(!isQuestComplete(player, DwarfCannon.NAME)) {
sendDialogue(player, "You need to complete the ${DwarfCannon.NAME} quest in order to do this.")
if(!isQuestComplete(player, Quests.DWARF_CANNON)) {
sendDialogue(player, "You need to complete the ${Quests.DWARF_CANNON} quest in order to do this.")
return true
}
if (getDynLevel(player, Skills.SMITHING) < levelRequirement) {

View file

@ -15,6 +15,7 @@ import core.game.node.scenery.Scenery;
import core.plugin.Plugin;
import core.plugin.Initializable;
import core.plugin.ClassScanner;
import content.data.Quests;
/**
* Represents the option handler used for smithing.
@ -68,7 +69,7 @@ public final class SmithingPlugin extends UseWithHandler {
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
if (((Scenery) event.getUsedWith()).getId() == 2782 && !player.getQuestRepository().isComplete("Doric's Quest")) {
if (((Scenery) event.getUsedWith()).getId() == 2782 && !player.getQuestRepository().isComplete(Quests.DORICS_QUEST)) {
player.getDialogueInterpreter().sendDialogue("Property of Doric the Dwarf.");
return true;
}

View file

@ -7,6 +7,7 @@ import core.game.node.item.GroundItemManager;
import core.game.node.item.Item;
import core.plugin.Initializable;
import core.game.world.map.Location;
import content.data.Quests;
/**
* Represents a rat npc.
@ -51,7 +52,7 @@ public class RatNPC extends AbstractNPC {
super.finalizeDeath(killer);
if (killer instanceof Player) {
final Player p = ((Player) killer);
if (p.getQuestRepository().getQuest("Witch's Potion").isStarted(p)) {
if (p.getQuestRepository().getQuest(Quests.WITCHS_POTION).isStarted(p)) {
GroundItemManager.create(RAT_TAIL, getLocation(), p);
}
}

View file

@ -17,6 +17,7 @@ import org.rs09.consts.NPCs
import org.rs09.consts.Sounds
import core.game.world.map.Location
import core.game.world.map.Direction
import content.data.Quests
private val sheepIds = intArrayOf(
NPCs.SHEEP_42,
@ -74,7 +75,7 @@ class SheepBehavior : NPCBehavior(*sheepIds), InteractionListener {
val sheep = node as NPC
sheep.faceTemporary(player, 1)
if (sheep.id == NPCs.SHEEP_3579) {
if (player.questRepository.getQuest("Sheep Shearer").isStarted(player)) {
if (player.questRepository.getQuest(Quests.SHEEP_SHEARER).isStarted(player)) {
setAttribute(player, ATTR_IS_PENGUIN_SHEEP_SHEARED, true)
}
animate(player, Animation(893))

View file

@ -72,7 +72,7 @@ public final class FieldPickingPlugin extends OptionHandler {
player.dispatch(new ResourceProducedEvent(reward.getId(), reward.getAmount(), node, -1));
if (plant.name().startsWith("NETTLES") && (player.getEquipment().get(EquipmentContainer.SLOT_HANDS) == null || player.getEquipment().get(EquipmentContainer.SLOT_HANDS) != null && !player.getEquipment().get(EquipmentContainer.SLOT_HANDS).getName().contains("glove"))) {
player.getPacketDispatch().sendMessage("You have been stung by the nettles!");
player.getImpactHandler().manualHit(player, 2, HitsplatType.POISON);
player.getImpactHandler().manualHit(player, 6, HitsplatType.POISON);
return true;
}
if (plant.respawn != -1 && plant != PickingPlant.FLAX) {

View file

@ -7,6 +7,7 @@ import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.plugin.Initializable;
import core.plugin.Plugin;
import content.data.Quests;
import static core.api.ContentAPIKt.*;
@ -82,7 +83,7 @@ public class SearchOptionPlugin extends OptionHandler {
player.getInventory().add(new Item(946));
return true;
}
if (node.getId() == 12799 && hasRequirement(player, "In Aid of the Myreque")) {
if (node.getId() == 12799 && hasRequirement(player, Quests.IN_AID_OF_THE_MYREQUE)) {
openBankAccount(player);
return true;
}

View file

@ -11,18 +11,21 @@ class SignpostListener : InteractionListener {
override fun defineListeners() {
on(Scenery.SIGNPOST_18493, IntType.SCENERY, "read") { player, node ->
if (node.asScenery().location.equals(Location(3235, 3228))) {
// Authentic
setInterfaceText(player, "Head north towards Fred's farm, and the windmill.", 135, 3) // North
setInterfaceText(player, "South to the swamps of Lumbridge.", 135, 9) // South
setInterfaceText(player, "Cross the bridge and head east to Al Kharid or north to Varrock.", 135, 8) // East
setInterfaceText(player, "West to the Lumbridge Castle and Draynor Village. Beware the goblins!", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else if (node.asScenery().location.equals(Location(3261, 3230))) {
// Authentic
setInterfaceText(player, "North to farms and Varrock.", 135, 3) // North
setInterfaceText(player, "The River Lum lies to the south.", 135, 9) // South
setInterfaceText(player, "East to Al Kharid - toll gate; bring some money.", 135, 8) // East
setInterfaceText(player, "West to Lumbridge.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else if (node.asScenery().location.equals(Location(2983, 3278))) {
// Authentic
setInterfaceText(player, "North to the glorious White Knights' city of Falador.", 135, 3) // North
setInterfaceText(player, "South to Rimmington.", 135, 9) // South
setInterfaceText(player, "East to Port Sarim and Draynor Village.", 135, 8) // East
@ -45,12 +48,14 @@ class SignpostListener : InteractionListener {
}
on(Scenery.SIGNPOST_24263, IntType.SCENERY, "read") { player, node ->
if (node.asScenery().location.equals(Location(3268, 3332))) {
// Authentic
setInterfaceText(player, "Sheep lay this way.", 135, 3) // North
setInterfaceText(player, "South through farms to Al Kharid and Lumbridge.", 135, 9) // South
setInterfaceText(player, "East to Al Kharid mine and follow the path north to Varrock east gate.", 135, 8) // East
setInterfaceText(player, "West to Champion's Guild and Varrock south gate.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else if (node.asScenery().location.equals(Location(3283, 3333))) {
// Authentic
setInterfaceText(player, "North to Varrock mine and Varrock east gate.", 135, 3) // North
setInterfaceText(player, "South to large Mining area and Al Kharid.", 135, 9) // South
setInterfaceText(player, "Follow the path east to the Dig Site.", 135, 8) // East
@ -66,7 +71,13 @@ class SignpostListener : InteractionListener {
return@on true
}
on(Scenery.SIGNPOST_4132, IntType.SCENERY, "read") { player, node ->
if (node.asScenery().location.equals(Location(3166, 3286))) {
if (node.asScenery().location.equals(Location(3223, 3427))) {
setInterfaceText(player, "North to Varrock Palace.", 135, 3) // North
setInterfaceText(player, "South to the Champion's Guild.", 135, 9) // South
setInterfaceText(player, "East to the Dig Site.", 135, 8) // East
setInterfaceText(player, "West to Barbarian Village and Falador.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else if (node.asScenery().location.equals(Location(3166, 3286))) {
setInterfaceText(player, "North to the windmill.", 135, 3) // North
setInterfaceText(player, "South to a fishing pond next to Fred's farm.", 135, 9) // South
setInterfaceText(player, "East to Lumbridge.", 135, 8) // East
@ -133,6 +144,56 @@ class SignpostListener : InteractionListener {
}
return@on true
}
on(Scenery.SIGNPOST_4135, IntType.SCENERY, "read") { player, node ->
if (node.asScenery().location.equals(Location(3448, 3486))) {
setInterfaceText(player, "North to the Slayer Tower.", 135, 3) // North
setInterfaceText(player, "South to Mort Myre Swamp.", 135, 9) // South
setInterfaceText(player, "East to Canifis.", 135, 8) // East
setInterfaceText(player, "West to Varrock.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else {
setInterfaceText(player, "North to unknown.", 135, 3) // North
setInterfaceText(player, "South to unknown.", 135, 9) // South
setInterfaceText(player, "East to unknown.", 135, 8) // East
setInterfaceText(player, "West to unknown.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
}
return@on true
}
on(Scenery.SIGNPOST_31296, IntType.SCENERY, "read") { player, node ->
if (node.asScenery().location.equals(Location(3304, 3109))) {
// Authentic
setInterfaceText(player, "North to Al Kharid.", 135, 3) // North
setInterfaceText(player, "South to the Desert Mining Camp and Pollnivneach.", 135, 9) // South
setInterfaceText(player, "East and across the river to the Ruins of Uzer.", 135, 8) // East
setInterfaceText(player, "West to the Kalphite Lair.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else {
setInterfaceText(player, "North to unknown.", 135, 3) // North
setInterfaceText(player, "South to unknown.", 135, 9) // South
setInterfaceText(player, "East to unknown.", 135, 8) // East
setInterfaceText(player, "West to unknown.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
}
return@on true
}
on(Scenery.STONE_SIGNPOST_11630, IntType.SCENERY, "read") { player, node ->
// Authentic // https://youtu.be/vvHXKTOh_g4
if (node.asScenery().location.equals(Location(2967, 3412))) {
setInterfaceText(player, "North to Goblin Village.", 135, 3) // North
setInterfaceText(player, "South to Falador.", 135, 9) // South
setInterfaceText(player, "East to Varrock.", 135, 8) // East
setInterfaceText(player, "West to Taverley.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
} else {
setInterfaceText(player, "North to unknown.", 135, 3) // North
setInterfaceText(player, "South to unknown.", 135, 9) // South
setInterfaceText(player, "East to unknown.", 135, 8) // East
setInterfaceText(player, "West to unknown.", 135, 12) // West
openInterface(player, Components.AIDE_COMPASS_135)
}
return@on true
}
}
/**
* Old handlers of Signpost. Not all should be opening the AIDE_COMPASS.

View file

@ -9,6 +9,7 @@ import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import content.data.Quests;
/**
* Handles the bar squeezing shortcut.
@ -61,7 +62,7 @@ public class BarSqueezeShortcut extends AgilityShortcut {
@Override
public boolean checkRequirements(Player player) {
if (!player.getQuestRepository().isComplete("Priest in Peril") && !(player.getLocation().getY() >= 3159 && player.getLocation().getY() <= 3161)) {
if (!player.getQuestRepository().isComplete(Quests.PRIEST_IN_PERIL) && !(player.getLocation().getY() >= 3159 && player.getLocation().getY() <= 3161)) {
player.getDialogueInterpreter().sendDialogue("You need to have completed Priest in Peril in order to do this.");
return false;
}

View file

@ -15,6 +15,7 @@ import core.plugin.Initializable;
import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
import content.data.Quests;
/**
* Handles a tunnel shortcut.
@ -73,7 +74,7 @@ public class TunnelShortcut extends AgilityShortcut {
@Override
public void run(final Player player, Scenery object, String option, boolean failed) {
if (object.getId() == 14922) {
if (!hasRequirement(player, "Swan Song"))
if (!hasRequirement(player, Quests.SWAN_SONG))
return;
}
player.lock(6);

View file

@ -3,6 +3,7 @@ package content.global.skill.construction;
import core.game.node.entity.player.Player;
import org.rs09.consts.Items;
import core.game.node.entity.skill.Skills;
import content.data.Quests;
/**
* Family crest types.
@ -16,7 +17,7 @@ public enum CrestType implements CrestRequirement {
@Override
public boolean eligible(Player player) {
return player.getQuestRepository().isComplete("Shield of Arrav");
return player.getQuestRepository().isComplete(Quests.SHIELD_OF_ARRAV);
}
},
ASGARNIA("the symbol of Asgarnia"), // no requirements
@ -24,21 +25,21 @@ public enum CrestType implements CrestRequirement {
@Override
public boolean eligible(Player player) {
return player.getQuestRepository().isComplete("The Lost Tribe");
return player.getQuestRepository().isComplete(Quests.THE_LOST_TRIBE);
}
},
DRAGON("a dragon") { // requires Dragon Slayer
@Override
public boolean eligible(Player player) {
return player.getQuestRepository().isComplete("Dragon Slayer");
return player.getQuestRepository().isComplete(Quests.DRAGON_SLAYER);
}
},
FAIRY("a fairy") { // requries Lost City
@Override
public boolean eligible(Player player) {
return player.getQuestRepository().isComplete("Lost City");
return player.getQuestRepository().isComplete(Quests.LOST_CITY);
}
},
GUTHIX("the symbol of Guthix") { // Requires 70+ Prayer

View file

@ -20,7 +20,6 @@ import core.game.world.GameWorld;
import org.rs09.consts.Sounds;
import java.awt.*;
import java.nio.ByteBuffer;
import static core.api.ContentAPIKt.*;
import static core.api.regionspec.RegionSpecificationKt.fillWith;
@ -99,36 +98,6 @@ public final class HouseManager {
}
public void save(ByteBuffer buffer) {
buffer.put((byte) location.ordinal());
buffer.put((byte) style.ordinal());
if (hasServant()) {
servant.save(buffer);
} else {
buffer.put((byte) -1);
}
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
Room room = rooms[z][x][y];
if (room != null) {
buffer.put((byte) z).put((byte) x).put((byte) y);
buffer.put((byte) room.getProperties().ordinal());
buffer.put((byte) room.getRotation().toInteger());
for (int i = 0; i < room.getHotspots().length; i++) {
if (room.getHotspots()[i].getDecorationIndex() > -1) {
buffer.put((byte) i);
buffer.put((byte) room.getHotspots()[i].getDecorationIndex());
}
}
buffer.put((byte) -1);
}
}
}
}
buffer.put((byte) -1);//Eof
}
public void parse(JSONObject data){
location = HouseLocation.values()[Integer.parseInt( data.get("location").toString())];
style = HousingStyle.values()[Integer.parseInt( data.get("style").toString())];
@ -155,28 +124,6 @@ public final class HouseManager {
}
}
public void parse(ByteBuffer buffer) {
location = HouseLocation.values()[buffer.get() & 0xFF];
style = HousingStyle.values()[buffer.get() & 0xFF];
servant = Servant.parse(buffer);
int z = 0;
while ((z = buffer.get()) != -1) {
if (z == 3) {
hasDungeon = true;
}
int x = buffer.get();
int y = buffer.get();
Room room = rooms[z][x][y] = new Room(RoomProperties.values()[buffer.get() & 0xFF]);
room.configure(style);
room.setRotation(Direction.get(buffer.get() & 0xFF));
int spot = 0;
while ((spot = buffer.get()) != -1) {
room.getHotspots()[spot].setDecorationIndex(buffer.get() & 0xFF);
}
}
}
/**
* Prepares for entering the player's house.
* @param player
@ -257,7 +204,7 @@ public final class HouseManager {
}
/**
* Leaves this house.
* Leaves this house through the portal.
* @param player The player leaving.
*/
public static void leave(Player player) {
@ -268,7 +215,6 @@ public final class HouseManager {
if (house.isInHouse(player)) {
player.animate(Animation.RESET);
player.getProperties().setTeleportLocation(house.location.getExitLocation());
removeAttribute(player, "original-loc");
}
}

View file

@ -3,11 +3,12 @@ package content.global.skill.construction;
import core.game.node.entity.Entity;
import core.game.node.entity.player.Player;
import core.game.world.map.build.DynamicRegion;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.map.RegionManager;
import core.game.world.map.Region;
import core.game.system.task.Pulse;
import core.game.world.map.zone.ZoneRestriction;
import static core.api.ContentAPIKt.*;
@ -81,14 +82,16 @@ public final class HouseZone extends MapZone {
if (e instanceof Player) {
Player p = (Player) e;
HouseManager.leave(p);
return true;
}
return true;
return super.death(e, killer);
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player p = (Player) e;
// The below tears down the house if the owner was the one who left
if (house == p.getHouseManager()) {
house.expelGuests(p);
int toRemove = previousRegion;
@ -109,7 +112,11 @@ public final class HouseZone extends MapZone {
}
});
}
// Clear logout listener and original-loc (if appropriate)
clearLogoutListener(p, "houselogout");
if (!getAttribute(p, "kidnapped-by-random", false)) {
removeAttribute(p, "/save:original-loc");
}
return true;
}
return true;

View file

@ -5,8 +5,6 @@ import core.game.node.entity.npc.NPC;
import core.game.node.item.Item;
import org.json.simple.JSONObject;
import java.nio.ByteBuffer;
/**
* Represents a player's servant.
* @author Emperor
@ -44,26 +42,9 @@ public final class Servant extends NPC {
}
/**
* Saves the servant details.
* @param buffer The buffer to write on.
*/
public void save(ByteBuffer buffer) {
buffer.put((byte) type.ordinal());
buffer.putShort((byte) uses);
if (item == null) {
buffer.putShort((short) -1);
} else {
buffer.putShort((short) item.getId());
buffer.putInt(item.getAmount());
}
buffer.put((byte) (greet ? 1 : 0));
}
/**
* Parses the servant from the buffer.
* Parses the servant from the save file.
* @return The servant.
*/
public static Servant parse(JSONObject data){
int type = Integer.parseInt( data.get("type").toString());
Servant servant = new Servant(ServantType.values()[type]);
@ -77,21 +58,6 @@ public final class Servant extends NPC {
return servant;
}
public static Servant parse(ByteBuffer buffer) {
int type = buffer.get();
if (type == -1) {
return null;
}
Servant servant = new Servant(ServantType.values()[type]);
servant.uses = buffer.getShort() & 0xFFFF;
int itemId = buffer.getShort() & 0xFFFF;
if ((short) itemId != -1) {
servant.item = new Item(itemId, buffer.getInt());
}
servant.greet = buffer.get() == 1;
return servant;
}
/**
* Gets the item value.
* @return The item.

View file

@ -17,6 +17,8 @@ import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
import static content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.ARDOUGNE_TELE_ATTRIBUTE;
/**
* PortalChamberPlugin
* @author Clayton Williams
@ -87,6 +89,12 @@ public class PortalChamberPlugin extends OptionHandler {
}
for (Locations l : Locations.values()) {
if (l.name().contains(identifier)) {
if (l == Locations.ARDOUGNE){
if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){
player.sendMessage("You do not have the requirements to direct the portal there");
return;
}
}
Item[] runes = l.runes;
if (!player.getInventory().containsItems(runes)) {
player.sendMessage("You do not have the required runes to build this portal");
@ -130,6 +138,12 @@ public class PortalChamberPlugin extends OptionHandler {
case "enter":
String objectName = object.getName();
for (Locations l : Locations.values()) {
if (l == Locations.ARDOUGNE){
if (player.getAttribute(ARDOUGNE_TELE_ATTRIBUTE, false)){
player.sendMessage("You do not have the requirements to enter this portal.");
return false;
}
}
if (objectName.toLowerCase().contains(l.name().toLowerCase())) {
player.teleport(l.location);
if (player.getHouseManager().isInHouse(player) && node.getId() == 13635) {

View file

@ -10,6 +10,7 @@ import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.Skills
import content.global.skill.construction.Decoration
import content.region.kandarin.ardougne.quest.plaguecity.PlagueCityListeners.Companion.ARDOUGNE_TELE_ATTRIBUTE
import core.game.node.entity.combat.spell.MagicStaff
import core.game.node.item.Item
import core.game.system.task.Pulse
@ -84,6 +85,11 @@ class LecternPlugin : OptionHandler() {
player.sendMessages("You need the Bones to Peaches ability purchased from MTA before making these.", "This requirement doesn't apply to actually using the tabs.")
return false
}
if(this == ARDOUGNE && !getAttribute(player, ARDOUGNE_TELE_ATTRIBUTE, false)){
sendMessage(player, "You need to unlock Ardougne teleport before you can make a tablet.")
return false
}
var found = false
for (d in requiredDecorations) if (d.objectId == objectId) found = true
if (!found) {

View file

@ -360,7 +360,7 @@ public class HouseServantDialogue extends DialoguePlugin {
bankFetch(player, new Item(Items.MARBLE_BLOCK_8786));
break;
case 3: //magic stones
bankFetch(player, new Item(Items.MAGIC_STONE_4703));
bankFetch(player, new Item(Items.MAGIC_STONE_8788));
break;
}
break;

View file

@ -66,7 +66,7 @@ class CookingRewrite : InteractionListener {
}
companion object {
val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3039, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377)
val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3039, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 18170, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377)
@JvmStatic
fun cook(player: Player, `object`: Scenery?, initial: Int, product: Int, amount: Int) {

View file

@ -4,6 +4,8 @@ import content.global.skill.skillcapeperks.SkillcapePerks;
import core.game.event.ResourceProducedEvent;
import core.game.node.entity.impl.Animator;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.info.LogType;
import core.game.node.entity.player.info.PlayerMonitor;
import core.game.node.entity.player.link.audio.Audio;
import core.game.node.entity.skill.Skills;
import core.game.node.item.GroundItemManager;
@ -15,7 +17,8 @@ import core.tools.RandomFunction;
import org.rs09.consts.Items;
import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.playAudio;
import static core.api.ContentAPIKt.*;
import content.data.Quests;
public class StandardCookingPulse extends Pulse {
//range animation
@ -38,12 +41,17 @@ public class StandardCookingPulse extends Pulse {
private boolean burned = false;
public CookableItems properties;
private int initialAmount;
private int processedAmount;
public StandardCookingPulse(Player player, Scenery object, int initial, int product, int amount) {
this.player = player;
this.object = object;
this.initial = initial;
this.product = product;
this.amount = amount;
this.initialAmount = amountInInventory(player, initial);
this.processedAmount = 0;
}
@Override
@ -72,7 +80,7 @@ public class StandardCookingPulse extends Pulse {
this.experience = 0;
if (properties != null) {
// Handle Cook's Assistant range
if (object.getId() == LUMBRIDGE_RANGE && !player.getQuestRepository().isComplete("Cook's Assistant")) {
if (object.getId() == LUMBRIDGE_RANGE && !player.getQuestRepository().isComplete(Quests.COOKS_ASSISTANT)) {
player.getPacketDispatch().sendMessage("You need to have completed the Cook's Assistant quest in order to use that range.");
return false;
}
@ -169,6 +177,11 @@ public class StandardCookingPulse extends Pulse {
player.getInventory().add(productItem);
player.dispatch(new ResourceProducedEvent(productItem.getId(), 1, object, initialItem.getId()));
player.getSkills().addExperience(Skills.COOKING, experience, true);
processedAmount++;
if (processedAmount > initialAmount) {
PlayerMonitor.log(player, LogType.DUPE_ALERT, "cooked item (" + player.getName() + ", " + initialItem.getName() + "): initialAmount " + initialAmount + ", processedAmount " + processedAmount);
}
player.incrementAttribute("/save:stats_manager:food_cooked", 1);
} else {
player.dispatch(new ResourceProducedEvent(CookableItems.getBurnt(initial).getId(), 1, object, initialItem.getId()));
player.getInventory().add(CookableItems.getBurnt(initial));

View file

@ -0,0 +1,44 @@
package content.global.skill.cooking.recipe
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.skill.Skills
import org.rs09.consts.Items
class HangoverRecipe : InteractionListener {
companion object{
private const val SNAPE_GRASS = Items.SNAPE_GRASS_231
private const val HANGOVER_CURE = Items.HANGOVER_CURE_1504
private const val BUCKET_OF_MILK = Items.BUCKET_OF_MILK_1927
private const val CHOCOLATE_DUST = Items.CHOCOLATE_DUST_1975
private const val CHOCOLATE_MILK = Items.CHOCOLATEY_MILK_1977
}
override fun defineListeners() {
onUseWith(IntType.ITEM, CHOCOLATE_DUST, BUCKET_OF_MILK) { player, _, _ ->
if(hasLevelDyn(player, Skills.COOKING, 4)){
if(removeItem(player, CHOCOLATE_DUST) and removeItem(player, BUCKET_OF_MILK)){
addItem(player, CHOCOLATE_MILK)
sendItemDialogue(player, CHOCOLATE_MILK, "You mix the chocolate into the bucket.")
}
}
else {
sendDialogue(player, "You need a Cooking level of at least 4 to make chocolate milk.")
}
return@onUseWith true
}
onUseWith(IntType.ITEM, SNAPE_GRASS, CHOCOLATE_MILK) { player, _, _ ->
if (removeItem(player, SNAPE_GRASS) && removeItem(player, CHOCOLATE_MILK))
{
sendItemDialogue(player, HANGOVER_CURE, "You mix the snape grass into the bucket.")
addItem(player, HANGOVER_CURE)
return@onUseWith true
}
return@onUseWith false
}
}
}

View file

@ -66,6 +66,12 @@ class LightSourceLighter : UseWithHandler(590,36,38){
lightSource ?: return false
// For Sea Slug Quest - No lighting of any torch on the fishing platform.
if(event.player.location.isInRegion(11059)) {
event.player.sendMessage("Your tinderbox is damp from the sea crossing. It won't work here.")
return true
}
if(!light(event.player,used,lightSource)){
event.player.sendMessage("You need a Firemaking level of at least ${lightSource.levelRequired} to light this.")
}

View file

@ -109,7 +109,7 @@ class CropHarvester : OptionHandler() {
if (patch.patch.type in livesBased) {
patch.rollLivesDecrement(
getDynLevel(player, Skills.FARMING),
requiredItem == Items.MAGIC_SECATEURS_7409
inInventory(player, Items.MAGIC_SECATEURS_7409) //add ||inEquipment() check when Fairy Tale pt 1 has been implemented
)
} else {
patch.harvestAmt--

View file

@ -154,7 +154,8 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
PatchType.FRUIT_TREE_PATCH -> setVarbit(player, patch.varbit, plantable!!.value + plantable!!.stages + 20)
PatchType.BUSH_PATCH -> setVarbit(player, patch.varbit, 250 + (plantable!!.ordinal - Plantable.REDBERRY_SEED.ordinal))
PatchType.CACTUS_PATCH -> setVarbit(player, patch.varbit, 31)
else -> log(this::class.java, Log.WARN, "Invalid setting of isCheckHealth for patch type: " + patch.type.name)
PatchType.TREE_PATCH -> setVarbit(player, patch.varbit, plantable!!.value + plantable!!.stages)
else -> log(this::class.java, Log.WARN, "Invalid setting of isCheckHealth for patch type: " + patch.type.name + "at" + patch.name)
}
} else {
when(patch.type){

View file

@ -12,6 +12,7 @@ import core.game.interaction.QueueStrength
import core.tools.StringUtils
import core.tools.prependArticle
import org.rs09.consts.Sounds
import content.data.Quests
class UseWithPatchHandler : InteractionListener {
val RAKE = Items.RAKE_5341
@ -39,7 +40,7 @@ class UseWithPatchHandler : InteractionListener {
val usedItem = used.asItem()
if (patch == FarmingPatch.TROLL_STRONGHOLD_HERB) {
if (!hasRequirement(player, "My Arm's Big Adventure"))
if (!hasRequirement(player, Quests.MY_ARMS_BIG_ADVENTURE))
return@onUseWith true
}
@ -263,51 +264,53 @@ class UseWithPatchHandler : InteractionListener {
sendMessage(player, "You need ${prependArticle(requiredItem.asItem().name.lowercase())} to plant that.")
return@onUseWith true
}
player.lock()
if (removeItem(player, plantItem)) {
when (requiredItem) {
Items.SPADE_952 -> {
animate(player, spadeDigAnim)
playAudio(player, Sounds.DIGSPADE_1470)
queueScript(player, 0, QueueStrength.WEAK) { stage: Int ->
when (stage) {
0 -> {
val (anim, sound) = when (requiredItem) {
Items.SPADE_952 -> Pair(spadeDigAnim, Sounds.DIGSPADE_1470)
else -> Pair(seedDibberAnim,Sounds.FARMING_DIBBING_2432)
}
animate(player, anim)
playAudio(player, sound)
val delay = if (patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || plantable == Plantable.SCARECROW) 3 else 0
return@queueScript delayScript(player,anim.duration + delay)
}
Items.SEED_DIBBER_5343 -> {
animate(player, seedDibberAnim)
playAudio(player, Sounds.FARMING_DIBBING_2432)
1 -> {
if (removeItem(player, plantItem)) {
if (plantable == Plantable.JUTE_SEED && patch == FarmingPatch.MCGRUBOR_HOPS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 0, 7)) {
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 7)
}
p.plant(plantable)
rewardXP(player, Skills.FARMING, plantable.plantingXP)
p.setNewHarvestAmount()
if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) {
addItem(player, Items.PLANT_POT_5350)
}
val itemAmount =
if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) "the"
else if (plantItem.amount == 1) "a"
else plantItem.amount
val itemName =
if (plantItem.amount == 1) plantable.displayName else StringUtils.plusS(
plantable.displayName
)
val patchName = p.patch.type.displayName()
if (plantable == Plantable.SCARECROW) {
sendMessage(player, "You place the scarecrow in the $patchName.")
} else {
sendMessage(player, "You plant $itemAmount $itemName in the $patchName.")
}
}
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
val delay = if (patch.type == PatchType.TREE_PATCH || patch.type == PatchType.FRUIT_TREE_PATCH || plantable == Plantable.SCARECROW) 0 else 3
submitIndividualPulse(player, object : Pulse(delay) {
override fun pulse(): Boolean {
if (plantable == Plantable.JUTE_SEED && patch == FarmingPatch.MCGRUBOR_HOPS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 0, 7)) {
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 7)
}
p.plant(plantable)
rewardXP(player, Skills.FARMING, plantable.plantingXP)
p.setNewHarvestAmount()
if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) {
addItem(player, Items.PLANT_POT_5350)
}
val itemAmount =
if (p.patch.type == PatchType.TREE_PATCH || p.patch.type == PatchType.FRUIT_TREE_PATCH) "the"
else if (plantItem.amount == 1) "a"
else plantItem.amount
val itemName = if (plantItem.amount == 1) plantable.displayName else StringUtils.plusS(plantable.displayName)
val patchName = p.patch.type.displayName()
if (plantable == Plantable.SCARECROW) {
sendMessage(player, "You place the scarecrow in the $patchName.")
} else {
sendMessage(player, "You plant $itemAmount $itemName in the $patchName.")
}
player.unlock()
return true
}
})
}
}
}
return@onUseWith true
}
}

View file

@ -24,7 +24,7 @@ enum class Fish(val id: Int, val level: Int, val experience: Double, val lowChan
LOBSTER(Items.RAW_LOBSTER_377, 40, 90.0, 0.16, 0.375),
BASS(Items.RAW_BASS_363, 46, 100.0, 0.078, 0.16),
SWORDFISH(Items.RAW_SWORDFISH_371, 50, 100.0, 0.105, 0.191),
LAVA_EEL(Items.RAW_LAVA_EEL_2148, 53, 30.0, 0.227, 0.379),
LAVA_EEL(Items.RAW_LAVA_EEL_2148, 53, 60.0, 0.227, 0.379),
MONKFISH(Items.RAW_MONKFISH_7944, 62, 120.0, 0.293, 0.356),
KARAMBWAN(Items.RAW_KARAMBWAN_3142, 65, 105.0, 0.414, 0.629),
SHARK(Items.RAW_SHARK_383, 76, 110.0, 0.121, 0.16),

View file

@ -1,51 +0,0 @@
/*
package core.game.node.entity.skill.fletching;
import core.game.dialogue.SkillDialogueHandler;
import core.game.dialogue.SkillDialogueHandler.SkillDialogue;
import core.game.node.entity.skill.fletching.items.bolts.Bolt;
import core.game.node.entity.skill.fletching.items.bolts.BoltPulse;
import org.crandor.game.interaction.NodeUsageEvent;
import org.crandor.game.interaction.UseWithHandler;
import org.crandor.game.node.entity.player.Player;
import org.crandor.net.packet.PacketRepository;
import org.crandor.net.packet.context.ChildPositionContext;
import org.crandor.net.packet.out.RepositionChild;
import org.crandor.plugin.InitializablePlugin;
import org.crandor.plugin.Plugin;
*/
/**
* Represents the bolt creating plugin.
* @author 'Vexia
* @version 1.0
*//*
@InitializablePlugin
public final class BoltCreatePlugin extends UseWithHandler {
*/
/**
* Constructs a new {@code BoltCreatePlugin} {@code Object}.
*//*
public BoltCreatePlugin() {
super(314);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (Bolt bolt : Bolt.values()) {
addHandler(bolt.getItem().getId(), ITEM_TYPE, this);
}
return this;
}
@Override
public boolean handle(final NodeUsageEvent event) {
final Player player = event.getPlayer();
}
}
*/

View file

@ -1,45 +0,0 @@
//package core.game.node.entity.skill.fletching;
//
//import core.game.dialogue.SkillDialogueHandler;
//import core.game.dialogue.SkillDialogueHandler.SkillDialogue;
//import core.game.node.entity.skill.fletching.items.gem.GemBolt;
//import core.game.node.entity.skill.fletching.items.gem.GemBoltPulse;
//import org.crandor.game.interaction.NodeUsageEvent;
//import org.crandor.game.interaction.UseWithHandler;
//import org.crandor.game.node.entity.player.Player;
//import org.crandor.net.packet.PacketRepository;
//import org.crandor.net.packet.context.ChildPositionContext;
//import org.crandor.net.packet.out.RepositionChild;
//import org.crandor.plugin.InitializablePlugin;
//import org.crandor.plugin.Plugin;
//
///**
// * Represents the plugin used to handle gem bolt making.
// * @author 'Vexia
// * @version 1.0
// */
//@InitializablePlugin
//public class BoltGemPlugin extends UseWithHandler {
//
// /**
// * Constructs a new {@code BoltGemPlugin} {@code Object}.
// */
// public BoltGemPlugin() {
// super(45, 46, 9187, 9188, 9189, 9190, 9191, 9192, 9193, 9194);
// }
//
// @Override
// public Plugin<Object> newInstance(Object arg) throws Throwable {
// for (GemBolt bolt : GemBolt.values()) {
// addHandler(bolt.getBase().getId(), ITEM_TYPE, this);
// }
// return this;
// }
//
// @Override
// public boolean handle(final NodeUsageEvent event) {
// final Player player = event.getPlayer();
//
// }
//
//}

View file

@ -1,49 +0,0 @@
/*
package core.game.node.entity.skill.fletching;
import core.game.node.entity.skill.fletching.items.darts.Dart;
import org.crandor.game.interaction.NodeUsageEvent;
import org.crandor.game.interaction.UseWithHandler;
import org.crandor.plugin.InitializablePlugin;
import org.crandor.plugin.Plugin;
import core.game.content.quest.touristrap.TouristTrap;
*/
/**
* Represents the plugin used to create a dart.
* @author 'Vexia
* @version 1.0
*//*
@InitializablePlugin
public final class DartCreatePlugin extends UseWithHandler {
*/
/**
* Constructs a new {@code DartCreatePlugin} {@code Object}.
*//*
public DartCreatePlugin() {
super(314);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (Dart dart : Dart.values()) {
addHandler(dart.getItem().getId(), ITEM_TYPE, this);
}
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
if (event.getPlayer().getQuestRepository().getQuest(TouristTrap.NAME).getStage(event.getPlayer()) < 60) {
event.getPlayer().getPacketDispatch().sendMessage("You need to start Tourist Trap in order to do this.");
return true;
}
event.getPlayer().getDialogueInterpreter().open(328933, event.getUsedItem(), event.getBaseItem());
return true;
}
}
*/

View file

@ -1,137 +0,0 @@
/*
package core.game.node.entity.skill.fletching;
import org.crandor.game.node.item.Item;
*/
/**
* Represents a fletching item to make.
* @author 'Vexia
*//*
public enum FletchItem {
ARROW_SHAFT(FletchType.LOG, new Item(52, 15), 1, 5), SHORTBOW(FletchType.LOG, new Item(50), 5, 5),
LONGBOW(FletchType.LOG, new Item(48), 10, 10),
OAK_SHORTBOW(FletchType.OAK, new Item(54), 20, 16.5),
OAK_LONGBOW(FletchType.OAK, new Item(56), 25, 25),
WILLOW_SHORTBOW(FletchType.WILLOW, new Item(60), 35, 33.3),
WILLOW_LONGBOW(FletchType.WILLOW, new Item(58), 40, 41.5),
MAPLE_SHORTBOW(FletchType.MAPLE, new Item(64), 50, 50),
MAPLE_LONGBOW(FletchType.MAPLE, new Item(62), 55, 58.3),
YEW_SHORTBOW(FletchType.YEW, new Item(68), 65, 55),
YEW_LONGBOW(FletchType.YEW, new Item(66), 70, 75),
MAGIC_SHORTBOW(FletchType.MAGIC, new Item(72), 80, 83.3),
MAGIC_LONGBOW(FletchType.MAGIC, new Item(70), 85, 91.5),
WOODEN_STOCK(FletchType.LOG, new Item(9440), 9, 6),
OAK_STOCK(FletchType.OAK, new Item(9442), 24, 16),
WILLOW_STOCK(FletchType.WILLOW, new Item(9444), 39, 22),
TEAK_STOCK(FletchType.TEAK, new Item(9446), 46, 27),
MAPLE_STOCK(FletchType.MAPLE, new Item(9448), 54, 32),
MAHOGANY_STOCK(FletchType.MAHOGANY, new Item(9450), 61, 41),
YEW_STOCK(FletchType.YEW, new Item(9452), 69, 50);
*/
/**
* Constructs a new {@code FletchItem.java} {@code Object}.
* @param type the type.
* @param product the product.
* @param level the level.
* @param experience the experience.
*//*
FletchItem(final FletchType type, final Item product, final int level, final double experience) {
this.type = type;
this.product = product;
this.level = level;
this.experience = experience;
}
*/
/**
* Represents the type this item pertaint o.
*//*
private FletchType type;
*/
/**
* Represents the product of this item.
*//*
private Item product;
*/
/**
* Represents the level.
*//*
private final int level;
*/
/**
* Represents the experience.
*//*
private final double experience;
*/
/**
* Gets the type.
* @return The type.
*//*
public FletchType getType() {
return type;
}
*/
/**
* Sets the type.
* @param type The type to set.
*//*
public void setType(FletchType type) {
this.type = type;
}
*/
/**
* Gets the product.
* @return The product.
*//*
public Item getProduct() {
return product;
}
*/
/**
* Sets the product.
* @param product The product to set.
*//*
public void setProduct(Item product) {
this.product = product;
}
*/
/**
* Gets the level.
* @return The level.
*//*
public int getLevel() {
return level;
}
*/
/**
* Gets the experience.
* @return The experience.
*//*
public double getExperience() {
return experience;
}
}
*/

View file

@ -1,88 +0,0 @@
/*
package core.game.node.entity.skill.fletching;
import org.crandor.game.component.Component;
import org.crandor.game.node.item.Item;
*/
/**
* Represents the multiple fletching types(log types)
* @author 'Vexia
*//*
public enum FletchType {
LOG(new Item(1511), FletchItem.ARROW_SHAFT, FletchItem.SHORTBOW, FletchItem.LONGBOW, FletchItem.WOODEN_STOCK), OAK(new Item(1521), FletchItem.OAK_SHORTBOW, FletchItem.OAK_LONGBOW, FletchItem.OAK_STOCK), WILLOW(new Item(1519), FletchItem.WILLOW_SHORTBOW, FletchItem.WILLOW_LONGBOW, FletchItem.WILLOW_STOCK), MAPLE(new Item(1517), FletchItem.MAPLE_SHORTBOW, FletchItem.MAPLE_LONGBOW, FletchItem.MAPLE_STOCK), TEAK(new Item(6333), FletchItem.TEAK_STOCK), MAHOGANY(new Item(6332), FletchItem.MAHOGANY_STOCK), YEW(new Item(1515), FletchItem.YEW_SHORTBOW, FletchItem.YEW_LONGBOW, FletchItem.YEW_STOCK), MAGIC(new Item(1513), FletchItem.MAGIC_SHORTBOW, FletchItem.MAGIC_LONGBOW);
*/
/**
* Constructs a new {@code FletchType} {@code Object}.
* @param log the log.
* @param items the item.s
*//*
FletchType(final Item log, final FletchItem... items) {
this.log = log;
this.items = items;
}
*/
/**
* Represents the log of this type.
*//*
private final Item log;
*/
/**
* Represents the fletching items of this type.
*//*
private FletchItem[] items;
*/
/**
* Gets the items.
* @return The items.
*//*
public FletchItem[] getItems() {
return items;
}
*/
/**
* Gets the log.
* @return The log.
*//*
public Item getLog() {
return log;
}
*/
/**
* Method used to get the component based on type.
* @return the component.
*//*
public Component getComponent() {
return items.length > 1 ? new Component(301 + items.length) : new Component(309);
}
*/
/**
* Method used to get the <code>FletchType</code> based on the log item.
* @param item the item.
* @return the fletch type.
*//*
public static FletchType forItem(final Item item) {
for (FletchType type : FletchType.values()) {
if (type.getLog().getId() == item.getId()) {
return type;
}
}
return null;
}
}
*/

Some files were not shown because too many files have changed in this diff Show more