diff --git a/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml b/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml index c7bb92bf2d..ad62e4e1d8 100644 --- a/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml +++ b/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml @@ -45,11 +45,21 @@ spawns = [ { id = "goblin_light_topless_spiked", x = 3185, y = 3244 }, { id = "goblin_light_grey_bald_spear", x = 3167, y = 3205 }, # 12850 + { id = "butterfly_3", x = 3255, y= 3226}, + { id = "butterfly_3", x = 3233, y= 3216}, + { id = "roddeck", x = 3232, y = 3237, direction = "WEST" }, + { id = "sigmund", x = 3209, y = 3219, level = 1 }, + { id = "guardsman_deshawn", x = 3206, y = 3214, level = 1 }, + { id = "guardsman_dante", x = 3211, y = 3227, level = 1 }, + { id = "guardsman_brawn", x = 3215, y = 3219, level = 1}, + { id = "guardsman_pazel", x = 3213, y = 3210, level = 1 }, + { id = "guardsman_peale", x = 3208, y = 3227}, + { id = "donie", x = 3219, y = 3247 }, { id = "imp", x = 3223, y = 3223 }, { id = "lumbridge_sage", x = 3238, y = 3219, direction = "WEST" }, { id = "lachtopher", x = 3225, y = 3238}, { id = "victoria", x = 3231, y = 3207}, - { id = "lumbridge_woman_5", x = 3227, y = 3240, level = 1 }, + { id = "lumbridge_woman_5", x = 3205, y = 3242, level = 1 }, { id = "lumbridge_woman_4", x = 3235, y = 3206 }, { id = "lumbridge_woman_3", x = 3224, y = 3242 }, { id = "lumbridge_woman_2", x = 3231, y = 3207, level = 1 }, diff --git a/data/area/misthalin/lumbridge/lumbridge.npcs.toml b/data/area/misthalin/lumbridge/lumbridge.npcs.toml index 4ee846fafa..2595ebe60f 100644 --- a/data/area/misthalin/lumbridge/lumbridge.npcs.toml +++ b/data/area/misthalin/lumbridge/lumbridge.npcs.toml @@ -57,6 +57,13 @@ id = 2244 categories = ["human"] examine = "He provides new players with useful information." +[donie] +id = 2238 +categories = ["human"] +collision = "outdoors" +wander_radius = 25 +examine = "A local farmer. She might be able to provide some useful information." + [border_guard_al_kharid] id = 925 categories = ["human"] @@ -98,6 +105,13 @@ wander_radius = 3 collision = "indoors" examine = "Duke Horacio of Lumbridge." +[sigmund] +id = 2082 +categories = ["human"] +wander_radius = 3 +collision = "indoors" +examine = "Advisor to the Duke of Lumbridge." + [cook_lumbridge] id = 278 categories = ["human"] @@ -105,6 +119,29 @@ wander_radius = 4 collision = "indoors" examine = "Lumbridge Castle's head cook." +[guardsman_dante] +id = 7885 +categories = ["human"] +wander_radius = 4 +collision = "indoors" +examine = "He tries to keep order around Lumbridge." + +[guardsman_deshawn] +clone = "guardsman_dante" +id = 7886 + +[guardsman_brawn] +clone = "guardsman_dante" +id = 7887 + +[guardsman_pazel] +clone = "guardsman_dante" +id = 7889 + +[guardsman_peale] +clone = "guardsman_dante" +id = 7890 + [lumbridge_man] id = 7873 max_hit_melee = 10 @@ -172,3 +209,8 @@ id = 7883 [lumbridge_woman_5] clone = "lumbridge_woman" id = 7884 + +[roddeck] +id = 8867 +categories = ["human"] +examine = "A helpful soul who loves dispensing advice." \ No newline at end of file diff --git a/data/area/misthalin/lumbridge/lumbridge.objs.toml b/data/area/misthalin/lumbridge/lumbridge.objs.toml index 342044989f..f55ef70603 100644 --- a/data/area/misthalin/lumbridge/lumbridge.objs.toml +++ b/data/area/misthalin/lumbridge/lumbridge.objs.toml @@ -102,4 +102,481 @@ examine = "A backpack belonging to the Lumbridge Sage" [scroll_desk] id = 8718 -examine = "A desk full of information scrolls." \ No newline at end of file +examine = "A desk full of information scrolls." + +[lumbridge_cannon] +id = 36780 +examine = "It doesn't look like it's been used recently" + +[lumbridge_cannonballs] +id = 36790 +examine = "Big, heavy metal balls." + +[lumbridge_wooden_defence] +id = 36928 +examine = "A wooden defensive structure." + +[lumbridge_barrel] +id = 45282 +examine = "A wooden barrel for storage." + +[lumbridge_sacks] +id = 45287 +examine = "These may have something in them." + +[lumbridge_standard] +id = 36925 +examine = "A standard of Lumbridge Castle." + +[lumbridge_bank_table] +id = 36789 +examine = "A table used by bank customers." + +[lumbridge_bank_leaflet] +id = 45504 +examine = "'Pay back all your debts by borrowing more money from us!' Clever." + +[lumbridge_bank_deposit_box] +id = 36788 +examine = "It lets you put the items into your bank." + +[lumbridge_closed_bank_booth] +id = 36787 +examine = "This booth is closed." + +[lumbridge_painting_watermill] +id = 36803 +examine = "A watermill. How charming." + +[lumbridge_painting_sunset] +id = 36804 +examine = "A sunset." + +[lumbridge_painting_mountains] +id = 36805 +examine = "A view of mountains." + +[lumbridge_painting_watermill_2] +id = 36811 +examine = "A watermill. How charming." + +[lumbridge_painting_valley] +id = 36814 +examine = "A river winding through a valley." + +[lumbridge_painting_watermill_3] +id = 38424 +examine = "A watermill. How charming." + +[lumbridge_standard_2] +id = 36924 +examine = "A blue standard." + +[lumbridge_standard_3] +id = 36926 +examine = "A standard of Lumbridge Castle." + +[lumbridge_axe_cabinet] +id = 36817 +examine = "A locked cabinet of decorative axes." + +[lumbridge_sword_cabinet] +id = 36818 +examine = "A locked cabinet of decorative swords." + +[lumbridge_bust] +id = 36938 +examine = "A stone bust of an ancient ruler." + +[lumbridge_bust_2] +id = 36939 +examine = "A stone bust of an ancient hero." + +[lumbridge_bust_3] +id = 36940 +examine = "A stone bust of an ancient hero." + +[lumbridge_wardrobe] +id = 36908 +examine = "A fancy place to store clothes." + +[lumbridge_bed] +id = 36941 +examine = "Great for sleeping in." + +[lumbridge_bed_2] +id = 36943 +examine = "Great for sleeping in." + +[lumbridge_closed_chest] +id = 37009 +examine = "I wonder what's inside." + +[lumbridge_closed_chest_2] +id = 6910 +examine = "It has a letter 'S' on the lock." + +[lumbridge_hanging_tapestry] +id = 36809 +examine = "I don't know art, but I like it!" + +[lumbridge_hanging_tapestry_2] +id = 36923 +examine = "I don't know art, but I like it." + +[lumbridge_suit_of_armour] +id = 36779 +examine = "A decorative suit of armour with a Lumbridge shield." + +[lumbridge_fireplace] +id = 36815 +examine = "A fire burns steadily in the grate." + +[lumbridge_barrel_2] +id = 36798 +examine = "A wooden barrel." + +[lumbridge_barrel_3] +id = 45283 +examine = "A wooden barrel for storage." + +[lumbridge_bush] +id = 36782 +examine = "Well-maintained." + +[lumbridge_hanging_meat] +id = 45317 +examine = "I can't take someone's food." + +[lumbridge_hanging_meat_2] +id = 45318 +examine = "I can't take someone's food." + +[lumbridge_shelves] +id = 36829 +examine = "Storage for cookery items." + +[lumbridge_cooking_pots] +id = 5609 +examine = "They could do with a wash." + +[lumbridge_cooking_pots_2] +id = 5610 +examine = "They could do with a wash." + +[lumbridge_stool] +id = 36837 +examine = "A wooden stool." + +[lumbridge_table] +id = 36910 +examine = "A banquet could be eaten from this." + +[lumbridge_ale_barrel] +id = 15674 +examine = "An ale barrel." + +[lumbridge_ale_barrel_2] +id = 15676 +examine = "An ale barrel." + +[lumbridge_shelves_2] +id = 32283 +examine = "Storage for cookery items." + +[lumbridge_shelves_3] +id = 32284 +examine = "Storage for all needs." + +[lumbridge_shelves_4] +id = 6904 +examine = "How exciting, some shelves." + +[lumbridge_large_table] +id = 12280 +examine = "A nice sturdy looking table." + +[lumbridge_table_2] +id = 8700 +examine = "For putting things on." + +[lumbridge_portrait] +id = 887 +examine = "A painting of the King looking royal." + +[lumbridge_small_table] +id = 12281 +examine = "A small wooden table." + +[lumbridge_sacks_2] +id = 32049 +examine = "These may have something in them." + +[lumbridge_crates] +id = 31139 +examine = "A pair of stacked storage crates." + +[lumbridge_winch] +id = 37336 +examine = "Used for pulling things up." + +[lumbridge_queen_statue] +id = 36749 +examine = "An expertly-carved statue of a former Queen of Misthalin." + +[lumbridge_king_statue] +id = 36751 +examine = "An expertly-carved statue of a former King of Misthalin." + +[lumbridge_clan_cup_plaque] +id = 55301 +examine = "Dedicated to the winners of the Clan Cup." + +[lumbridge_signpost_cow] +id = 31297 +examine = "An interesting sign." + +[lumbridge_signpost_death] +id = 31299 +examine = "An interesting sign." + +[lumbridge_daisies] +id = 1189 +examine = "Commonly found in grassy areas." + +[lumbridge_flower] +id = 1188 +examine = "Blooming!" + +[lumbridge_lantern] +id = 45269 +examine = "A light for my path." + +[lumbridge_painting_watermill_4] +id = 45258 +examine = "A watermill. How charming." + +[lumbridge_painting_sunset_2] +id = 45259 +examine = "A sunset." + +[roddecks_bookcase] +id = 49101 +examine = "Someone keeps books here." + +[lumbridge_grandfather_clock] +id = 45295 +examine = "Tick-tock, it's a clock." + +[lumbridge_stove] +id = 45316 +examine = "It's too small for me to cook anything in." + +[lumbridge_stool_2] +id = 45241 +examine = "A wooden stool." + +[lumbridge_wardrobe_2] +id = 45245 +examine = "A fancy place to store clothes." + +[lumbridge_bed_3] +id = 45230 +examine = "Great for sleeping in." + +[lumbridge_drawers_closed] +id = 45243 +examine = "A chest of drawers." + +[lumbridge_drawers_opened] +id = 45244 +examine = "A chest of drawers." + +[lumbridge_general_store_shelves] +id = 45249 +examine = "Storage for all needs." + +[lumbridge_general_store_shelves_2] +id = 45250 +examine = "Storage for all needs." + +[lumbridge_general_store_shelves_3] +id = 45251 +examine = "Storage for all needs." + +[lumbridge_general_store_stepladder] +id = 45296 +examine = "Lets you reach things on high shelves." + +[lumbridge_general_store_big_vase] +id = 45297 +examine = "An elegant ceramic pot tarnished with the dirt of a hundred years." + +[lumbridge_general_store_barrel] +id = 45285 +examine = "A barrel of unfinished staves and pieces of wood." + +[lumbridge_bed_4] +id = 45231 +examine = "Great for sleeping in." + +[lumbridge_shopkeer_table] +id = 45236 +examine = "An antique desk. The book belongs to the shopkeeper." + +[lumbridge_general_store_sign] +id = 45179 +examine = "The general store." + +[lumbridge_signpost_to_Draynor] +id = 36911 +examine = "North road to Draynor Village :: East road to Varrock." + +[lumbridge_bunk_bed] +id = 45232 +examine = "Great for sleeping in." + +[lumbridge_water_barrel] +id = 14353 +examine = "A barrel for collecting rainwater." + +[lumbridge_blacksmith_worker] +id = 45311 +examine = "He's working pretty hard." + +[lumbridge_workbench] +id = 45239 +examine = "This workbench belongs to the blacksmith, I should leave it alone." + +[lumbridge_workbench_2] +id = 45240 +examine = "I'd better not disturb the blacksmith's workbench." + +[lumbridge_smithing_tools] +id = 45320 +examine = "I can't take those, they belong to the blacksmith." + +[lumbridge_smithing_tools_2] +id = 45321 +examine = "The blacksmith will be needing these, I'd better not take them." + +[lumbridge_smithing_tools_3] +id = 45322 +examine = "I can't take those, they belong to the blacksmith." + +[lumbridge_chart_table] +id = 37672 +examine = "These look like Jack's old sea charts." + +[explorer_jack_trapdoor] +id = 45800 +examine = "It leads to Explorer Jack's cellar." + +[lumbridge_barrel_rocks] +id = 37586 +examine = "A barrel containing rocks and mining debris." + +[lumbridge_barrel_stack] +id = 37594 +examine = "A stack of wooden barrels." + +[lumbridge_water_barrel_2] +id = 37585 +examine = "A barrel full of rainwater." + +[lumbridge_liquid_barrel] +id = 37583 +examine = "It contains an indeterminate liquid." + +[lumbridge_bed_5] +id = 45229 +examine = "Great for sleeping in." + +[lumbridge_church_stand] +id = 36982 +examine = "A stand with lit candles." + +[lumbridge_church_stand_2] +id = 36983 +examine = "A stand with lit candles and hymns written on paper." + +[lumbridge_bookcase] +id = 45246 +examine = "A good source of books." + +[lumbridge_cooking_shelf] +id = 45253 +examine = "Contains various cooking supplies." + +[lumbridge_bobs_axe_hanging_banner] +id = 45260 +examine = "A tapestry showing a large axe." + +[lumbridge_bobs_axe_hanging_banner_2] +id = 45261 +examine = "A tapestry showing a large axe." + +[lumbridge_bobs_axe_display_axe] +id = 45262 +examine = "It's just for show." + +[lumbridge_bobs_axe_display_axes] +id = 45263 +examine = "These are for display purposes only." + +[lumbridge_bobs_axe_barrel_of_swords] +id = 45286 +examine = "These belong to Bob, I shouldn't take them." + +[lumbridge_broken_stool] +id = 45290 +examine = "A smashed stool." + +[lumbridge_broken_table] +id = 45292 +examine = "A smashed table." + +[lumbridge_broken_ladder] +id = 45293 +examine = "It's impossible to climb." + +[lumbridge_boxes] +id = 46237 +examine = "For storage. I wonder what's in there." + +[lumbridge_goblin_cook] +id = 45315 +examine = "He looks pretty busy." + +[lumbridge_spitroast] +id = 45313 +examine = "A spit over a roaring fire." + +[lumbridge_thistle] +id = 1174 +examine = "Spiky!" + +[lumbridge_plant] +id = 1392 +examine = "A leafy fern." + +[lumbridge_plant_2] +id = 1393 +examine = "A small bushy plant." + +[lumbridge_plant_3] +id = 1394 +examine = "A leafy shrub." + +[lumbridge_gravestone] +id = 404 +examine = "The inscription is worn away and unreadable." + +[lumbridge_gravestone_2] +id = 37005 +examine = "The inscription is worn away and unreadable." + +[lumbridge_gravestone_3] +id = 37006 +examine = "'Here lies...'is all I can read." + diff --git a/data/area/misthalin/lumbridge/lumbridge.teles.toml b/data/area/misthalin/lumbridge/lumbridge.teles.toml index 693ac96b50..d15e3de5ad 100644 --- a/data/area/misthalin/lumbridge/lumbridge.teles.toml +++ b/data/area/misthalin/lumbridge/lumbridge.teles.toml @@ -35,7 +35,7 @@ option = "Climb-down" tile = { x = 3247, y = 3197 } to = { x = 3877, y = 5526, level = 1 } -[36687] +[trapdoor_109_opened] option = "Climb-down" tile = { x = 3209, y = 3216 } delta = { x = -2, y = 6400 } @@ -150,42 +150,42 @@ option = "Climb-down" tile = { x = 3230, y = 3209, level = 1 } delta = { x = 3, level = -1 } -[36984] +[lumbridge_church_1st_floor_ladder_up_west] option = "Climb-up" tile = { x = 3241, y = 3213 } delta = { x = -2, level = 1 } -[36985] +[lumbridge_church_2nd_floor_ladder_down_west] option = "Climb-down" tile = { x = 3241, y = 3213, level = 1 } delta = { x = 2, level = -1 } -[36986] +[lumbridge_church_1st_floor_ladder_up_east] option = "Climb-up" tile = { x = 3246, y = 3213 } delta = { x = 2, level = 1 } -[36987] +[lumbridge_church_2nd_floor_ladder_down_east] option = "Climb-down" tile = { x = 3246, y = 3213, level = 1 } delta = { x = -2, level = -1 } -[36989] +[lumbridge_church_2nd_floor_ladder_up_west] option = "Climb-up" tile = { x = 3242, y = 3207, level = 1 } delta = { x = 1, y = -1, level = 1 } -[36991] +[lumbridge_church_3rd_floor_ladder_down_west] option = "Climb-down" tile = { x = 3242, y = 3207, level = 2 } delta = { x = -1, y = 1, level = -1 } -[36988] +[lumbridge_church_2nd_floor_ladder_up_east] option = "Climb-up" tile = { x = 3245, y = 3207, level = 1 } delta = { x = -1, y = -1, level = 1 } -[36990] +[lumbridge_church_3rd_floor_ladder_down_east] option = "Climb-down" tile = { x = 3245, y = 3207, level = 2 } delta = { x = 1, y = 1, level = -1 } diff --git a/data/area/misthalin/lumbridge/lumbridge_basement.teles.toml b/data/area/misthalin/lumbridge/lumbridge_basement.teles.toml index 194166a9f8..e5abdaf238 100644 --- a/data/area/misthalin/lumbridge/lumbridge_basement.teles.toml +++ b/data/area/misthalin/lumbridge/lumbridge_basement.teles.toml @@ -1,5 +1,5 @@ # 12950 lumbridge_basement -[27668] +[lumbridge_basement_ladder_up] option = "Climb-up" tile = { x = 3232, y = 5091 } to = { x = 3368, y = 3268 } diff --git a/data/area/misthalin/signposts.objs.toml b/data/area/misthalin/signposts.objs.toml index cd19a173d4..ec2be377b9 100644 --- a/data/area/misthalin/signposts.objs.toml +++ b/data/area/misthalin/signposts.objs.toml @@ -1,6 +1,6 @@ [direction_signpost_1] id = 2754 -examine = "" +examine = "This tells you which way is which." locations = [ { x = "3235", @@ -14,7 +14,7 @@ locations = [ [direction_signpost_2] id = 18493 -examine = "" +examine = "This tells you which way is which." locations = [ { x = "3261", @@ -44,7 +44,7 @@ locations = [ [direction_signpost_3] id = 24263 -examine = "" +examine = "This tells you which way is which." locations = [ { x = "3268", diff --git a/data/entity/npc/monster/goblin/goblin.npcs.toml b/data/entity/npc/monster/goblin/goblin.npcs.toml index ba20f58695..101844ddc1 100644 --- a/data/entity/npc/monster/goblin/goblin.npcs.toml +++ b/data/entity/npc/monster/goblin/goblin.npcs.toml @@ -57,7 +57,7 @@ respawn_delay = 35 drop_table = "goblin" combat_anims = "goblin" combat_sounds = "goblin" -examine = "An ugly, blue creature." +examine = "An ugly green creature." categories = ["goblins"] height = 30 diff --git a/data/entity/obj/obj.sounds.toml b/data/entity/obj/obj.sounds.toml index d014001a1d..590e16b869 100644 --- a/data/entity/obj/obj.sounds.toml +++ b/data/entity/obj/obj.sounds.toml @@ -19,3 +19,8 @@ id = 2400 [coffin_open] id = 54 +[drawer_close] +id = 63 + +[drawer_open] +id = 64 diff --git a/data/entity/obj/stairs_ladders.objs.toml b/data/entity/obj/stairs_ladders.objs.toml index 5422ad2c54..ed739f1778 100644 --- a/data/entity/obj/stairs_ladders.objs.toml +++ b/data/entity/obj/stairs_ladders.objs.toml @@ -102,4 +102,68 @@ examine = "I can climb down this." [canifis_ladder_up] id = 30575 -examine = "I can climb this." \ No newline at end of file +examine = "I can climb this." + +[29355] +id = 29355 +examine = "I can climb this." + +[36768] +id = 36768 +examine = "I can climb up this." + +[36769] +id = 36769 +examine = "I can climb up or down this." + +[36770] +id = 36770 +examine = "I can climb down this." + +[45483] +id = 45483 +examine = "Some wooden stairs." + +[45484] +id = 45484 +examine = "Some wooden stairs." + +[45481] +id = 45481 +examine = "Some wooden stairs." + +[45482] +id = 45482 +examine = "Some wooden stairs." + +[lumbridge_church_1st_floor_ladder_up_west] +id = 36984 +examine = "I can climp up this." + +[lumbridge_church_2nd_floor_ladder_down_west] +id = 36985 +examine = "I can climp down this." + +[lumbridge_church_1st_floor_ladder_up_east] +id = 36986 +examine = "I can climp up this." + +[lumbridge_church_2nd_floor_ladder_down_east] +id = 36987 +examine = "I can climp down this." + +[lumbridge_church_2nd_floor_ladder_up_east] +id = 36988 +examine = "I can climp up this." + +[lumbridge_church_2nd_floor_ladder_up_west] +id = 36989 +examine = "I can climp up this." + +[lumbridge_church_3rd_floor_ladder_down_east] +id = 36990 +examine = "I can climb down this." + +[lumbridge_church_3rd_floor_ladder_down_west] +id = 36991 +examine = "I can climb down this." \ No newline at end of file diff --git a/data/entity/obj/trapdoors.objs.toml b/data/entity/obj/trapdoors.objs.toml index 1949876e30..fef167f17b 100644 --- a/data/entity/obj/trapdoors.objs.toml +++ b/data/entity/obj/trapdoors.objs.toml @@ -173,3 +173,7 @@ examine = "I wonder what's down there." [trapdoor_108_closed] id = 21944 examine = "I wonder what's under it?" + +[trapdoor_109_opened] +id = 36687 +examine = "I wonder what's down there." diff --git a/data/quest/free/unstable_foundations/unstable_foundations.books.toml b/data/quest/free/unstable_foundations/unstable_foundations.books.toml new file mode 100644 index 0000000000..b103fe305c --- /dev/null +++ b/data/quest/free/unstable_foundations/unstable_foundations.books.toml @@ -0,0 +1,314 @@ +[roddecks_diary] +title = "Roddeck's Diary" +type = "long" +pages = [ + [ + "3rd Raktuber", + "Yet again it's raining.", + "Just when I wanted to", + "go for a walk to Draynor", + "Village with my new gorgeous", + "new walking stick and", + "maybe pop in for tea with", + "the Wise Old Man. How", + "typical. Ah, well, I'm sure", + "I can find some way to", + "pass the time.", + "", + "", + "", + "", + "Maybe I'll leaf through", + "some of those old books", + "that belonged to my late", + "uncle. He had such", + "strange interests,", + "Saradomin rest his soul." + ], + [ + "4th Raktuber", + "I believe I've found a", + "marvellous new hobby!", + "One of those old books", + "was a manual for rearing", + "pet dragons.", + "", + "I don't have a garden,", + "but I'm sure I can do", + "just as well keeping it in", + "my cellar; there's plenty", + "", + "", + "", + "", + "of space down there, and", + "it'll be out of the rain.", + "", + "I've written to the", + "Taverley pet shop to", + "order an egg and some", + "supplies." + ], + [ + "5th Raktuber", + "No sign of my egg yet", + "and it's still raining.", + "Never mind, I shall brave", + "the rain and take a walk", + "after all.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "6th Raktuber", + "Oh dear, I have such a", + "terrible cold." + ], + [ + "9th Raktuber", + "At last, I am feeling well", + "enough to resume my", + "diary. Furthermore, my", + "delivery has arrived far", + "sooner than I had hoped.", + "That postman is a", + "curious little chap, but he", + "certainly knows his trade.", + "Now, to unpack the egg", + "and get started...", + "", + "", + "", + "", + "11th Raktuber", + "Apparently, it takes ages", + "for these eggs to hatch.", + "How disappointing.", + "", + "I think I shall name it", + "Sottlepot if it's a boy-", + "dragon and Piddypins if", + "it's a girl-dragon." + ], + [ + "14th Raktuber", + "Little Sottlepot has", + "hatched! These dragons", + "really are marvellous", + "creatures.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "32nd Raktuber", + "I've had no time for this", + "diary recently; I seem to", + "find myself constantly", + "busy preparing minced", + "meat and bringing him", + "water.", + "He's growing so fast." + ], + [ + "15th Pentember", + "I must admit that I'm", + "starting to have second", + "thoughts about this little", + "project of mine.", + "", + "Sottlepot has grown so", + "large that I'm not", + "entirely sure he'll fit", + "through the trapdoor of", + "the cellar anymore.", + "", + "", + "", + "", + "Furthermore, no matter", + "how much I feed him, he", + "keeps...well...salivating", + "when he looks at me.", + "", + "He was a lot sweeter", + "when he was smaller. I", + "wonder if parenthood is", + "like this." + ], + [ + "20th Pentember", + "I'm becoming seriously", + "concerned about", + "Sottlepot. He's completely", + "smashed the pillars of my", + "cellar.", + "", + "Fortunately, I was able to", + "shore up the ceiling with", + "some bits of wood before", + "the whole cellar caved in!", + "", + "", + "", + "", + "Hmm, perhaps I should", + "have taken up carpentry", + "instead of raising a", + "dragon." + ], + [ + "21st Pentember", + "That blasted dragon", + "almost managed to break", + "the chains that were", + "holding him to the wall.", + "", + "If he gets loose there's no", + "way I'm going to be able", + "to restrain him again.", + "", + "", + "", + "", + "", + "", + "At risk of looking like", + "a complete nincompoop, I", + "think I'm going to have to", + "call someone to sort him", + "out before I lose control", + "oh him completely. The", + "White Knights might be", + "able to help." + ], + [ + "Post Scriptum", + "Saved at last! The White", + "Knights sent an agent in", + "response to my message.", + "", + "He couldn't have arrived at", + "a better time; I'd completely", + "lost control of the dragon,", + "and it had me cornered in a", + "cupboard in my own cellar!", + "", + "With the aid of a passing", + "adventurer, they managed to", + "kill the dragon, and then we", + "", + "tunnelled out of the cellar", + "into Jack's house because", + "the blasted dragon had burnt", + "my ladder.", + "", + "I've agreed to act as an", + "advisor for the adventurer,", + "since they are unfamiliar", + "with this country. Still, now", + "all that excitement is over,", + "I should try to find myself", + "a new hobby." + ], +] + +[manual_unstable_foundations] +title = "On The Care Of Dragons" +type = "long" +pages = [ + [ + "Dragons are the noblest", + "of creatures. While it", + "requires considerable skill", + "to keep them as pets, this", + "simple guide will help you", + "grasp the essentials.", + "", + "Firstly, you must ensure", + "you have adequate space", + "for the dragon -a large", + "garden or menagerie is", + "", + "", + "", + "", + "ideal. There should be", + "some shelter from the", + "elements and a plentiful", + "supply of food and water." + ], + [ + "Once you are prepared,", + "obtain a dragon's egg and", + "place it in a warm, dry", + "place. A dedicated", + "incubator is preferred, as", + "the temperature of a", + "cooking range is unlikely", + "to be suitable. After a few", + "days of this treatment", + "your egg will hatch.", + "", + "", + "", + "", + "", + "Do not leave your", + "dragon outside except in", + "warm weather until it has", + "attained a size of", + "approximately 12 inches.", + "When it is ready to be", + "introduced to its outdoor", + "habitat, keep a close eye", + "on its health to ensure it", + "does not develop scale rot", + "or lung-damp." + ], + [ + "It is essential, especially", + "in the first days, to keep", + "the dragon well fed. In", + "the wild, a mother dragon", + "will typically spend most", + "of her time feeding her", + "brood. Dragons require", + "copious quantities of raw", + "meat. For the first weeks", + "you should mince this", + "into a fine paste, having", + "", + "", + "", + "", + "removed all bones, but", + "once your dragon has", + "attained a size of", + "approximately 18 inches it", + "should be able to consume", + "meat on the bone. You", + "will rapidly learn what", + "form of sustenance your", + "dragon prefers." + ], + [ + "Dragon-owners are", + "strongly advised not to", + "bring their dragons", + "indoors once their flame", + "ducts have developed, as", + "this will typically lead to", + "inconvenient house-fires." + ], +] \ No newline at end of file diff --git a/data/quest/free/unstable_foundations/unstable_foundations.items.toml b/data/quest/free/unstable_foundations/unstable_foundations.items.toml index c9aa491ba3..a8bf766368 100644 --- a/data/quest/free/unstable_foundations/unstable_foundations.items.toml +++ b/data/quest/free/unstable_foundations/unstable_foundations.items.toml @@ -74,6 +74,7 @@ kept = "Reclaim" id = 15671 tradeable = false weight = 0.2 +book = "manual_unstable_foundations" examine = "Roddeck's book about the care of pet dragons." kept = "Reclaim" @@ -81,5 +82,6 @@ kept = "Reclaim" id = 15672 tradeable = false weight = 0.2 +book = "roddecks_diary" examine = "The diary of an elderly gentleman with eccentric habits." kept = "Reclaim" diff --git a/data/skill/woodcutting/birds_nest.drops.toml b/data/skill/woodcutting/birds_nest.drops.toml new file mode 100644 index 0000000000..32ff5bee7d --- /dev/null +++ b/data/skill/woodcutting/birds_nest.drops.toml @@ -0,0 +1,95 @@ +[birds_nest_table] +type = "all" +roll = 100 +drops = [ + { table = "birds_nest_seeds_1_table",chance = 64 }, + { table = "birds_nest_rings_table",chance = 32 }, + { table = "birds_nest_egg_table", chance = 4 } +] + +[birds_nest_seeds_1_table] +drops = [ + { id = "birds_nest_seeds_1" } +] + +[birds_nest_rings_table] +drops = [ + { id = "birds_nest_ring" } +] + +[birds_nest_egg_table] +roll = 100 +drops = [ + { id = "birds_nest_red_egg", chance = 25 }, + { id = "birds_nest_blue_egg", chance = 25 }, + { id = "birds_nest_green_egg", chance = 25 }, + { id = "birds_nest_raven_egg", chance = 25 } +] + +[birds_nest_seed_table] +roll = 1000 +drops = [ + { id = "acorn", chance = 214 }, + { id = "apple_tree_seed", chance = 170 }, + { id = "willow_seed", chance = 135 }, + { id = "banana_tree_seed", chance = 108 }, + { id = "orange_tree_seed", chance = 85 }, + { id = "curry_tree_seed", chance = 68} , + { id = "maple_seed", chance = 54 }, + { id = "pineapple_seed", chance = 42 }, + { id = "papaya_tree_seed", chance = 34 }, + { id = "yew_seed", chance = 27 }, + { id = "palm_tree_seed", chance = 22 }, + { id = "calquat_tree_seed", chance = 17 }, + { id = "magic_seed", chance = 13 }, + { id = "spirit_seed", chance = 11 }, +] + +[birds_nest_cheap_seed_table] +roll = 800 +drops = [ + { id = "spirit_seed", chance = 1 }, + { id = "magic_seed", chance = 1 }, + { id = "yew_seed", chance = 10 }, + { id = "maple_seed", chance = 10 }, + { id = "willow_seed", chance = 20 }, + { id = "acorn", chance = 30 }, + { id = "ranarr_seed", chance = 20 }, + { id = "sweetcorn_seed", amount = 3, chance = 120 }, + { id = "strawberry_seed", amount = 3, chance = 90 }, + { id = "limpwurt_seed", amount = 2, chance = 100 }, + { id = "watermelon_seed", amount = 2, chance = 90 }, + { id = "tomato_seed", amount = 6, chance = 110 }, + { id = "cabbage_seed", amount = 9, chance = 100 }, + { id = "evil_turnip_seed", amount = 2, chance = 90 }, +] + +[birds_nest_ring_table] +roll = 100 +drops = [ + { id = "gold_ring", chance = 35 }, + { id = "sapphire_ring", chance = 40 }, + { id = "emerald_ring", chance = 15 }, + { id = "ruby_ring", chance = 9 }, + { id = "diamond_ring", chance = 1 }, +] + +[birds_nest_egg_red_table] +drops = [ + { id = "birds_egg_red"}, +] + +[birds_nest_egg_blue_table] +drops = [ + { id = "birds_egg_blue"} +] + +[birds_nest_egg_green_table] +drops = [ + { id = "birds_egg_green"} +] + +[birds_nest_egg_raven_table] +drops = [ + { id = "raven_egg"} +] \ No newline at end of file diff --git a/data/skill/woodcutting/woodcutting.sounds.toml b/data/skill/woodcutting/woodcutting.sounds.toml index 224609da86..1f6250f703 100644 --- a/data/skill/woodcutting/woodcutting.sounds.toml +++ b/data/skill/woodcutting/woodcutting.sounds.toml @@ -1,2 +1,5 @@ [fell_tree] id = 2734 + +[bird_chirp] +id = 1516 \ No newline at end of file diff --git a/game/src/main/kotlin/content/area/banks/Leaflets.kts b/game/src/main/kotlin/content/area/banks/Leaflets.kts new file mode 100644 index 0000000000..89daae255d --- /dev/null +++ b/game/src/main/kotlin/content/area/banks/Leaflets.kts @@ -0,0 +1,14 @@ +package content.area.banks + +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory + +objectOperate("Take", "*_bank_leaflet") { + if (player.inventory.contains("leaflet")) { + player.message("You already have a copy of the leaflet.") + } else { + player.inventory.add("leaflet") + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/Donie.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/Donie.kts new file mode 100644 index 0000000000..685f9e7375 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/Donie.kts @@ -0,0 +1,247 @@ +package content.area.misthalin.lumbridge + +import content.entity.player.dialogue.Afraid +import content.entity.player.dialogue.Amazed +import content.entity.player.dialogue.Angry +import content.entity.player.dialogue.Chuckle +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.Sad +import content.entity.player.dialogue.Uncertain +import content.entity.player.dialogue.type.PlayerChoice +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.quest.questCompleted +import world.gregs.voidps.engine.entity.character.npc.npcOperate +import world.gregs.voidps.engine.entity.character.player.name +import world.gregs.voidps.type.random + +npcOperate("Talk-to", "donie") { + npc("Hello there, can I help you?") + when (random.nextInt(0, 4)) { + 0 -> choice { + whereAmI() + howToday() + anyQuests() + shoeLace() + } + 1 -> choice { + freeStuff() + anyQuests() + buyStick() + } + 2 -> choice { + whereAmI() + howToday() + anyQuests() + hairCut() + } + 3 -> choice { + anyQuests() + buyStick() + } + } +} + +suspend fun PlayerChoice.whereAmI(): Unit = option("Where am I") { + npc("This is the town of Lumbridge my friend.") + choice { + howToday() + anyQuests() + shoeLace() + } +} + +suspend fun PlayerChoice.howToday(): Unit = option("How are you today?") { + npc("Aye, not too bad thank you. Lovely weather in Gielinor this fine day.") + player("Weather?") + npc("Yes weather, you know.") + npc("The state or condition of the atmosphere at a time and place, with respect to variables such as temperature, moisture, wind velocity, and barometric pressure.") + player("...") + npc("Not just a pretty face eh? Ha ha ha.") +} + +suspend fun PlayerChoice.anyQuests(): Unit = option("Are there any quests I can do here?") { + npc("What kind of quest are you looking for?") + choice { + option("I fancy a bit of fight, anything dangerous?") { + npc("Hmm.. dangerous you say? What sort of creatures are you looking to fight?") + choice { + option("Big scary demons!") { + npc("You are a brave soul indeed.") + npc("Now that you mention it, I heard a rumour about a fortune-teller in Varrock who is rambling about some kind of grater evil.. sounds demon-like if you ask me.") + npc("Perhaps you could check it out if you are as brave as you say?") + if (player.questCompleted("demon_slayer")) { + player("I've already killed the demon Delrith. He was merely a stain on my sword when I was finished with him!") + npc("Well done! However I'm sure if you search around the world you will find more challenging foes to slay.") + } else { + player("Thanks for the tip, perhaps I will.") + } + } + option("Vampyres!") { + npc("Ha ha. I personally don't believe in such things. However, there is a man in Draynor Village who has been scaring the village folk with stories of vampyres.") + npc("He's named Morgan and can be found in one of the village houses. Perhaps you could see what the matter is?") + if (player.questCompleted("vampire_slayer")) { + player("Oh i have already killed that nasty blood-sucking vampyre. Draynor will be safe now.") + npc("Yeah, yeah of course you did. Everyone knows vampyres are not real...") + player("What! I did slay the beast..I really did.") + npc("You're not fooling anyone you know.") + player("..Huh.. But... Hey! I did... believe what you like.") + } else { + player("Thanks for the tip.") + } + } + option("Small.. something small would be good.") { + npc("Small? Small isn't really that dangerous though is it?") + player("Yes it can be! There could be anything from an evil chicken to a poisonous spider. They attack in numbers you know!") + npc("Point taken. Speaking of small monsters, I hear old Wizard Mizgog in the Wizards' Tower has just had his beads taken by a gang of mischievous imps.") + npc("Sounds like it could be a quest for you?") + if (player.questCompleted("imp_catcher")) { + player("Yes, I know of Mizgog and have already helped him with his imp problem.") + npc("Imps will be imps!") + } else { + player("Thanks for your help.") + } + } + option("Maybe another time.") + } + } + option("Something easy please, I'm new here.") { + npc("I can tell you about plenty of small easy tasks.") + npc("The Lumbridge cook has been having problems and the Duke is confused over some strange rocks") + choice("Tell me about..") { + option("The Lumbridge cook.") { + player("Tell me about the Lumbridge cook.") + npc("It's funny really, the cook would forget his head if it wasn't screwed on. This time he forgot to get ingredients for the Duke's birthday cake.") + npc("Perhaps you could help him? You will probably find him in the Lumbridge Castle kitchen.") + if (player.questCompleted("cooks_assistant")) { + player("I have already helped the cook in Lumbridge") + npc("Oh yes, so you have. I am sure the Duke will be pleased.") + } else { + player("Thank you. I shall go speak with him.") + } + } + option("The Duke's strange stones.") { + player("Tell me about the Duke's strange stones.") + npc("Well the Duke of Lumbridge has found a strange stone that no one seems to understand. Perhaps you could help him? You can probably find him upstairs in Lumbridge Castle.") + if (player.questCompleted("rune_mysteries")) { + player("Yes, I have already solved the rune mysteries.") + npc("Ah excellent. Thank you very much adventurer.") + } else { + player("Sounds mysterious. I may just do that. Thanks.") + } + } + option("Maybe another time.") + } + } + option("I'm a thinker rather than a fighter, anything skill oriented?") { + npc("Skills play a big part when you want to progress in knowledge. I know of a few skill-related quests that can get you started.") + npc("You may be able to help out Fred the farmer who is in need of someones crafting expertise.") + npc("Or, there's always Doric the dwarf who needs an errand running for him?") + choice("Tell me about..") { + option("Fred the farmer.") { + player("Tell me about Fred the farmer please.") + npc("You can find Fred next to the field of sheep in Lumbridge. Perhaps you should go and speak with him.") + if (player.questCompleted("sheep_shearer_miniquest")) { + player("I have already helped Fred the farmer. I sheared his sheep and made 20 balls of wool for him.") + player("He wouldn't let me kill his chickens though.") + npc("Lumbridge chickens do make good target practice.") + npc("You will have to wait until he isn't looking.") + } else { + player("Thanks, maybe I will.") + } + } + option("Doric the dwarf.") { + player("Tell me about Doric the dwarf.") + npc("Doric the dwarf is located north of Falador. He might be able to help you with smithing. You should speak to him. He may let you use his anvils.") + if (player.questCompleted("dorics_quest")) { + player("Yes, I've been to see Doric already. He was happy to let me use his anvils after I ran a small errand for him.") + npc("Oh, good. Thank you ${player.name}!") + } else { + player("Thanks for the tip.") + } + } + option("Maybe another time.") + } + } + option("I want to do all kinds of things, do you know of anything like that?") { + npc("Of course I do. Gielinor is a huge place you know, now let me think...") + npc("Hetty the witch in Rimmington might be able to offer help in the ways of magical abilities..") + npc("Also, pirates are currently docked in Port Sarim, Where pirates are, treasure is never far away...") + npc("Or you could go and help out Ernest who got lost in Draynor Manor, spooky place that.") + choice("Tell me about..") { + option("Hetty the witch.") { + player("Tell me about Hetty the witch.") + npc("Hetty the witch can be found in Rimmington, south of Falador. She's currently working on some new potions. Perhaps you could give her a hand? She might be able to offer help with your magical abilities.") + if (player.questCompleted("witches_potion_miniquest")) { + player("Yes, I have already been to see Hetty. She gave me super cosmic powers after I helped out with her potion! I could probably destroy you with a single thought.") + npc("Did she really?") + player("No, not really.") + npc("Right...") + } else { + player("Thanks. Let's hope she doesn't turn me into a potato or something..") + } + } + option("Pirate's Treasure.") { + player("Tell me about Pirate's Treasure.") + npc("RedBeard Frank in Port Sarim's bar, the Rusty Anchor might be able to tell you about the rumored treasure that is buried somewhere in the world.") + if (player.questCompleted("pirates_treasure")) { + player("Yarr! I already found the booty!") + npc("Yarr indeed my friend. A most excellent find.") + player("Yarr!") + npc("Yarrr!") + player("YARRR!") + npc("Right, that's enough of that!") + player("..Sorry.") + } else { + player("Sounds adventurous, I may have to check that out. Thank you.") + } + } + option("Ernest and Draynor Manor.") { + player("Tell me about Ernest please.") + npc("The best place to start would be at the gate to Draynor Manor. There you will find Veronica who will be able to tell you more.") + npc("I suggest you tread carefully in that place; it's haunted.") + if (player.questCompleted("ernest_the_chicken")) { + player("Yeah, I found Ernest already. Professor Oddstein had turned him into a chicken!") + npc("A chicken!?") + player("Yeah a chicken. It could have been worse though.") + npc("Very true, poor guy.") + } else { + player("Sounds like fun. I've never been to a Haunted Manor before.") + } + } + option("Maybe another time.") + } + } + option("Maybe another time.") + } +} + +suspend fun PlayerChoice.shoeLace(): Unit = option("Your shoe lace is untied.") { + npc("No it's not!") + player("No you're right. I have nothing to back that up.") + npc("Fool! Leave me alone!") +} + +suspend fun PlayerChoice.buyStick(): Unit = option("Can i buy your stick?") { + npc("It's not a stick! I'll have you know it's a very powerful staff!") + player("Really? Show me what it can do!") + npc("Um..It's a bit low on power at the moment..") + player("It's a stick isn't it?") + npc("...Ok it's a stick.. But only while I save up for a staff. Zaff in Varrock square sells them in his shop.") + player("Well good luck with that.") +} + +suspend fun PlayerChoice.freeStuff(): Unit = option("Do you have anything of value which I can have?") { + npc("Are you asking for free stuff?") + player("Well... er... yes.") + npc("No I do not have anything I can give you. If I did have anything of value I wouldn't want to give it away.") +} + +suspend fun PlayerChoice.hairCut(): Unit = option("Where can I get a haircut like yours?") { + npc("Yes, it does look like you need a hairdresser.") + player("Oh thanks!") + npc("No problem. The hairdresser in Falador will probably be able to sort you out.") + npc("The Lumbridge general store sells useful maps if you don't know the way.") +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/ExplorerJack.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/ExplorerJack.kts index 2981a5548a..0a43072f18 100644 --- a/game/src/main/kotlin/content/area/misthalin/lumbridge/ExplorerJack.kts +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/ExplorerJack.kts @@ -5,25 +5,32 @@ import content.achievement.Tasks.isCompleted import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.RollEyes import content.entity.player.dialogue.Talk +import content.entity.player.dialogue.Uncertain import content.entity.player.dialogue.type.choice import content.entity.player.dialogue.type.npc import content.entity.player.dialogue.type.player import world.gregs.voidps.engine.client.message import world.gregs.voidps.engine.client.sendScript +import world.gregs.voidps.engine.client.ui.dialogue.talkWith import world.gregs.voidps.engine.client.variable.BitwiseValues import world.gregs.voidps.engine.data.Settings import world.gregs.voidps.engine.data.definition.VariableDefinitions import world.gregs.voidps.engine.entity.character.npc.NPCOption +import world.gregs.voidps.engine.entity.character.npc.NPCs import world.gregs.voidps.engine.entity.character.npc.npcOperate import world.gregs.voidps.engine.entity.character.player.Player import world.gregs.voidps.engine.entity.character.player.chat.inventoryFull +import world.gregs.voidps.engine.entity.obj.objectOperate import world.gregs.voidps.engine.inject import world.gregs.voidps.engine.inv.add import world.gregs.voidps.engine.inv.inventory import world.gregs.voidps.engine.inv.transact.TransactionError import world.gregs.voidps.engine.inv.transact.operation.AddItem.add +val npcs: NPCs by inject() + npcOperate("Talk-to", "explorer_jack") { if (player["introducing_explorer_jack_task", "uncompleted"] == "uncompleted") { npc("Ah! Welcome to ${Settings["server.name"]}, lad. My name's Explorer jack. I'm an explorer by trade, and I'm one of the Taskmasters around these parts") @@ -144,3 +151,11 @@ fun completedAllBeginner(player: Player): Boolean { null } ?: false } + +objectOperate("Open", "explorer_jack_trapdoor") { + val explorerJack = npcs[player.tile.regionLevel].first { it.id.startsWith("explorer_jack") } + player.talkWith(explorerJack) + npc("I say, there's nothing interesting in my cellar! Better go exploring elsewhere, eh?") + player("What's down there?") + npc("Crates, boxes, shelves - nothing you won't see in dozens of houses across Runescape. Go on, explore somewhere else!") +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/LumbridgeBookcase.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/LumbridgeBookcase.kts new file mode 100644 index 0000000000..1279331956 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/LumbridgeBookcase.kts @@ -0,0 +1,15 @@ +package content.area.misthalin.lumbridge + +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate +import world.gregs.voidps.type.random + +objectOperate("Search", "lumbridge_bookcase") { + player.message("You search the books...") + delay(2) + when (random.nextInt(0, 3)) { + 0 -> player.message("None of them look very interesting.") + 1 -> player.message("You find nothing to interest you.") + 2 -> player.message("You don't find anything that you'd ever want to read.") + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/Victoria.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/Victoria.kts index a56584ed43..46eabb4df9 100644 --- a/game/src/main/kotlin/content/area/misthalin/lumbridge/Victoria.kts +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/Victoria.kts @@ -12,21 +12,21 @@ import world.gregs.voidps.engine.suspend.SuspendableContext npcOperate("Talk-to", "victoria") { player("Good day.") npc("To you too, traveller. I am Victoria. Tell me, have you seen my brother, Lachtopher, around the town?") - choice { - option("Yes, I've seen Lachtopher.") { + choice("What would you like to say?") { + option("Yes, I've seen Lachtopher.") { npc("Ah, he'll have asked you for money, no doubt. I hope you didn't give him any.") - choice { - option("No, I didn't give him a single coin.") { + choice("What would you like to say?") { + option("No, I didn't give him a single coin.") { npc("Oh, good! If you had, then you would never have got it back. My brother is such a waste of space. I've been lending him things for years and he never gives them back.") timesChange() } - option("Yes, I loaned him money, just like he asked.") { + option("Yes, I loaned him money, just like he asked.") { npc("Oh dear. I'm sorry to tell you this, but that's the last you'll see of that money. My brother is such a waste of space. I've been lending him things for years and he never gives them back.") timesChange() } } } - option("No, I haven't seen him.") { + option("No, I haven't seen him.") { npc("Well, if you do meet him, he'll ask you for money, no doubt. Please don't give him any.") player("Why not?") npc("Sorry to tell you this, but if you lend him money you'll never see it again. My brother is such a waste of space. I've been lending him things for years and he never gives them back.") @@ -36,6 +36,7 @@ npcOperate("Talk-to", "victoria") { } suspend fun SuspendableContext.timesChange() { + player("Oh dear. Has he always been this way?") npc("Yes, but it never used to be this bad. You see...") npc("Lachtopher used to live on the east side of the river, before it was overrun with goblins. Although he didn't have a steady job, he used to help out around farms when he needed cash.") npc("Then, one day, the Duke told us it was no longer safe to live on the east riverbank, so some villagers had to move across here.") diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kts new file mode 100644 index 0000000000..937e7aaf40 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kts @@ -0,0 +1,90 @@ +package content.area.misthalin.lumbridge.castle + +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.type.PlayerChoice +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import world.gregs.voidps.engine.entity.character.npc.npcOperate +import world.gregs.voidps.type.random + +npcOperate("Talk-to", "guardsman_*") { + when (random.nextInt(0, 5)) { + 0 -> player("Howdy.") + 1 -> player("Salutations!") + 2 -> player("Good day.") + 3 -> player("Nice to meet you.") + 4 -> player("Greetings.") + } + when (random.nextInt(0, 3)) { + 0 -> npc("Well met, adventurer.") + 1 -> npc("Well, hello there.") + 2 -> npc("Good day to you, adventurer.") + } + choice("What would you like to say?") { + tellMeGuardsmen() + aroundHere() + tellMeLumbridge() + whatAreGuarding() + option("Bye.") + } +} + +suspend fun PlayerChoice.tellMeGuardsmen(): Unit = option("Tell me about the Lumbridge Guardsmen.") { + when (random.nextInt(0, 2)) { + 0 -> npc("I won't pretend that we're an elite fighting force, but we know how to work with the castle's defences. That means just a few of us can hold a fairly strong defence, if we ever need to.") + 1 -> npc("I spoke to a few people who asked me about joining the Lumbridge Guardsmen. To be asked, you need to be a true local. I mean, when the call to arms is raised, you don't want your troops to be scattered across the world: they need to be waiting here, ready to spring in to action.") + } + choice("What would you like to say?") { + tellMeGuardsmen() + aroundHere() + tellMeLumbridge() + whatAreGuarding() + option("Bye.") + } +} + +suspend fun PlayerChoice.aroundHere(): Unit = option("What is there to do around here?") { + when (random.nextInt(0, 2)) { + 0 -> npc("If you're interested in learning to make leather armour, there's the cow field to get hides. Then, you can take your the hides to a tanner.") + 1 -> npc("If you'd like to make a bit of spending money, try speaking to the skill tutors. They go through a lot of supplies, so I'm sure they'd be happy to pay you to make the supplies they need.") + } + choice("What would you like to say?") { + tellMeGuardsmen() + aroundHere() + tellMeLumbridge() + whatAreGuarding() + option("Bye.") + } +} + +suspend fun PlayerChoice.tellMeLumbridge(): Unit = option("Tell me about Lumbridge.") { + when (random.nextInt(0, 3)) { + 0 -> npc("It used to be much nicer here, before the goblins overran the east side of town. You'd think that the Guardsmen would be sent to flush them out, but for every one we slay, three more appear in its place.") + 1 -> npc("If I'm honest, I don't much care for it here. I understand why so many do enjoy the lifestyle, but I long for the city life. If I do well in my job here, perhaps I could move to Varrock, or Falador, and join the guards there.") + 2 -> npc("I suppose it's a good place to find your feet in the world. There's reasonable fishing in the river, and with lots of farmland around it's rare that you go hungry. Yes, there's plenty worse places you could live in than Lumbridge.") + } + choice("What would you like to say?") { + tellMeGuardsmen() + aroundHere() + tellMeLumbridge() + whatAreGuarding() + option("Bye.") + } +} + +suspend fun PlayerChoice.whatAreGuarding(): Unit = option("What exactly are you guarding?") { + when (random.nextInt(0, 2)) { + 0 -> npc("Peace, happiness, tranquillity, that sort of thing. So, let me know if you see anything upsetting. Dragons in cellars, goblins under beds, that sort of thing.") + 1 -> npc("I suppose I'm guarding the castle, and the Lumbridge way of life. Although, there was once a dragon near here, and I helped defend the castle from it. That was an exciting time!") + } + choice("What would you like to say?") { + tellMeGuardsmen() + aroundHere() + tellMeLumbridge() + whatAreGuarding() + option("Bye.") + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeWinch.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeWinch.kts new file mode 100644 index 0000000000..d2ec3d4088 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeWinch.kts @@ -0,0 +1,10 @@ +package content.area.misthalin.lumbridge.castle + +import content.entity.sound.areaSound +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate + +objectOperate("Operate", "lumbridge_winch") { + player.message("It seems the winch is jammed. You can't move it.") + areaSound("lever", target.tile) +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/Sigmund.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/Sigmund.kts new file mode 100644 index 0000000000..b5f05b1cfb --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/Sigmund.kts @@ -0,0 +1,28 @@ +package content.area.misthalin.lumbridge.castle + +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.character.npc.npcOperate + +npcOperate("Talk-to", "sigmund") { + npc("Can I help you?") + choice { + option("Do you have any quests for me?") { + npc("I hear the Duke has a task for an adventurer. Otherwise, if you want to make yourself useful, there are always evil monsters to slay.") + player("Okay, I might just do that.") + } + option("Who are you?") { + npc("I'm the Duke's advisor.") + player("Can you give me any advice then?") + npc("I only advice the Duke. But if you want to make yourself useful, there are evil goblins to slay on the other side of the river.") + } + } +} + +npcOperate("Pickpocket", "sigmund") { + player.message("Sigmund doesn't seem to have anything of value.") +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/Roddeck.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/Roddeck.kts new file mode 100644 index 0000000000..c347129b9e --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/Roddeck.kts @@ -0,0 +1,35 @@ +package content.area.misthalin.lumbridge.roddecks_house + +import content.entity.player.dialogue.Chuckle +import content.entity.player.dialogue.Happy +import content.entity.player.dialogue.Neutral +import content.entity.player.dialogue.Quiz +import content.entity.player.dialogue.RollEyes +import content.entity.player.dialogue.type.PlayerChoice +import content.entity.player.dialogue.type.choice +import content.entity.player.dialogue.type.npc +import world.gregs.voidps.engine.entity.character.npc.npcOperate + +npcOperate("Talk-to", "roddeck") { + npc("Greetings! I am Roddeck. What can i do for you today?") + choice("What would you like to say?") { + option("Who are you?") { + npc("My name is Roddeck, and I am the Advisor. Whenever people in Runescape are in need of advice, they click on the Advisor button to seek my help.") + npc("Apart from that, I'm just an elderly gentleman of Lumbridge, and this is my house.") + npc("Now, was there anything else you wanted?") + choice { + anyAdvice() + noThanks() + } + } + anyAdvice() + noThanks() + } +} + +suspend fun PlayerChoice.anyAdvice(): Unit = option("Can you offer me any advice?") { + npc("Advice? Certainly, certainly! Click my Advisor button whenever you have a question.") +} + +suspend fun PlayerChoice.noThanks(): Unit = option("Nothing, thanks.") { +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksBookcase.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksBookcase.kts new file mode 100644 index 0000000000..aee4dc98fe --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksBookcase.kts @@ -0,0 +1,19 @@ +package content.area.misthalin.lumbridge.roddecks_house + +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory + +objectOperate("Search", "roddecks_bookcase") { + if (player.inventory.contains("roddecks_diary") && player.inventory.contains("manual_unstable_foundations")) { + player.message("There's nothing particularly interesting here.") + } else { + if (!player.inventory.contains("roddecks_diary")) { + player.inventory.add("roddecks_diary") + } + if (!player.inventory.contains("manual_unstable_foundations")) { + player.inventory.add("manual_unstable_foundations") + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksHouseDrawers.kts b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksHouseDrawers.kts new file mode 100644 index 0000000000..112ff42513 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/roddecks_house/RoddecksHouseDrawers.kts @@ -0,0 +1,24 @@ +package content.area.misthalin.lumbridge.roddecks_house + +import content.entity.sound.areaSound +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate +import world.gregs.voidps.engine.entity.obj.replace +import world.gregs.voidps.engine.timer.toTicks +import java.util.concurrent.TimeUnit + +objectOperate("Open", "lumbridge_drawers_closed") { + player.anim("open_chest") + areaSound("drawer_open", target.tile) + target.replace(target.id.replace("_closed", "_opened"), ticks = TimeUnit.MINUTES.toTicks(3)) +} + +objectOperate("Close", "lumbridge_drawers_opened") { + player.anim("close_chest") + areaSound("drawer_close", target.tile) + target.replace(target.id.replace("_opened", "_closed"), ticks = TimeUnit.MINUTES.toTicks(3)) +} + +objectOperate("Search", "lumbridge_drawers_opened") { + player.message("Nothing terribly interesting in here.") +} diff --git a/game/src/main/kotlin/content/entity/obj/Boxes.kts b/game/src/main/kotlin/content/entity/obj/Boxes.kts new file mode 100644 index 0000000000..924aae2d5f --- /dev/null +++ b/game/src/main/kotlin/content/entity/obj/Boxes.kts @@ -0,0 +1,8 @@ +package content.entity.obj + +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.entity.obj.objectOperate + +objectOperate("Search", "lumbridge_boxes") { + player.message("There is nothing interesting in these boxes.") +} diff --git a/game/src/main/kotlin/content/skill/woodcutting/BirdsNest.kts b/game/src/main/kotlin/content/skill/woodcutting/BirdsNest.kts new file mode 100644 index 0000000000..8371a60be6 --- /dev/null +++ b/game/src/main/kotlin/content/skill/woodcutting/BirdsNest.kts @@ -0,0 +1,59 @@ +package content.skill.woodcutting + +import content.entity.player.inv.inventoryOptions +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.data.definition.ItemDefinitions +import world.gregs.voidps.engine.entity.item.drop.DropTables +import world.gregs.voidps.engine.entity.item.drop.ItemDrop +import world.gregs.voidps.engine.inject +import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.inv.replace + +val drops: DropTables by inject() +val itemDefinitions: ItemDefinitions by inject() + +inventoryOptions("Search", "inventory") { + val tableId = when { + item.id == "birds_nest_ring" -> "birds_nest_ring_table" + item.id == "birds_nest_seeds_1" -> "birds_nest_seed_table" + item.id == "birds_nest_seeds_2" -> "birds_nest_cheap_seed_table" + item.id == "birds_nest_red_egg" -> "birds_nest_egg_red_table" + item.id == "birds_nest_green_egg" -> "birds_nest_egg_green_table" + item.id == "birds_nest_blue_egg" -> "birds_nest_egg_blue_table" + item.id == "birds_nest_raven_egg" -> "birds_nest_egg_raven_table" + else -> return@inventoryOptions + } + + val table = drops.get(tableId) ?: return@inventoryOptions + val items = mutableListOf() + table.role(list = items) + + val drop = items.firstOrNull() ?: return@inventoryOptions + val itemId = drop.id + val itemAmount = drop.amount?.start ?: 1 + + if (player.inventory.isFull()) { + player.message("Your inventory is too full to take anything out of the bird's nest.") + return@inventoryOptions + } + + val itemName = itemDefinitions.get(drop.id).name.lowercase() + if (player.inventory.replace(slot, item.id, "birds_nest_empty")) { + player.inventory.add(itemId, itemAmount) + } + + if (itemId.contains("acorn") || itemId.contains("orange") || itemId.contains("apple_tree") || itemId.contains("emerald")) { + if (itemAmount > 1) { + player.message("You take $itemAmount ${itemName}s out of the bird's nest.") + } else { + player.message("You take an $itemName out of the bird's nest.") + } + } else { + if (itemAmount > 1) { + player.message("You take $itemAmount ${itemName}s out of the bird's nest.") + } else { + player.message("You take a $itemName out of the bird's nest.") + } + } +} diff --git a/game/src/main/kotlin/content/skill/woodcutting/Woodcutting.kts b/game/src/main/kotlin/content/skill/woodcutting/Woodcutting.kts index 0d071aa4e8..2878677450 100644 --- a/game/src/main/kotlin/content/skill/woodcutting/Woodcutting.kts +++ b/game/src/main/kotlin/content/skill/woodcutting/Woodcutting.kts @@ -17,18 +17,24 @@ import world.gregs.voidps.engine.entity.character.player.skill.level.Interpolati import world.gregs.voidps.engine.entity.character.player.skill.level.Level import world.gregs.voidps.engine.entity.character.player.skill.level.Level.has import world.gregs.voidps.engine.entity.item.Item +import world.gregs.voidps.engine.entity.item.drop.DropTables +import world.gregs.voidps.engine.entity.item.floor.FloorItems import world.gregs.voidps.engine.entity.obj.GameObject import world.gregs.voidps.engine.entity.obj.GameObjects import world.gregs.voidps.engine.entity.obj.objectOperate import world.gregs.voidps.engine.inject import world.gregs.voidps.engine.inv.add +import world.gregs.voidps.engine.inv.equipment import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.map.collision.random import world.gregs.voidps.engine.suspend.awaitDialogues import world.gregs.voidps.type.random val players: Players by inject() val definitions: ObjectDefinitions by inject() val objects: GameObjects by inject() +val floorItems: FloorItems by inject() +val drops: DropTables by inject() val minPlayers = 0 val maxPlayers = 2000 @@ -75,10 +81,10 @@ objectOperate("Chop*") { } if (success(player.levels.get(Skill.Woodcutting), hatchet, tree)) { player.experience.add(Skill.Woodcutting, tree.xp) + tryDropNest(player, ivy) if (!addLog(player, tree) || deplete(tree, target)) { break } - if (ivy) { player.message("You successfully chop away some ivy.") } @@ -88,6 +94,24 @@ objectOperate("Chop*") { player.softTimers.stop("woodcutting") } +fun tryDropNest(player: Player, ivy: Boolean) { + val dropChance = 254 + if (random.nextInt(dropChance) != 0) return + val table = drops.get("birds_nest_table") ?: return + + val hasRabbitFoot = player.equipment.contains("strung_rabbit_foot") + val totalWeight = if (hasRabbitFoot) 95 else 100 + + val drop = table.role(totalWeight).firstOrNull() ?: return + + val source = if (ivy) "ivy" else "tree" + player.message("A bird's nest falls out of the $source!") + areaSound("bird_chirp", player.tile) + + val dropTile = player.tile.toCuboid(1).random(player) ?: player.tile + floorItems.add(tile = dropTile, id = drop.id, amount = drop.amount?.start ?: 1, disappearTicks = 50) +} + fun success(level: Int, hatchet: Item, tree: Tree): Boolean { val lowHatchetChance = calculateChance(hatchet, tree.hatchetLowDifference) val highHatchetChance = calculateChance(hatchet, tree.hatchetHighDifference)