From 09e92e9256da463fb426ddc1e26db7bb606ec7e8 Mon Sep 17 00:00:00 2001 From: aidan Date: Mon, 1 Dec 2025 09:24:21 -0600 Subject: [PATCH] initial commit. --- Server/data/configs/npc_spawns.json | 10 +- Server/data/configs/object_configs.json | 10 +- .../handlers/AbandonedMineListeners.kt | 150 ++++++++++++++++++ .../quest/hauntedmine/HauntedMine.kt | 139 ++++++++++++++++ .../quest/hauntedmine/HauntedMineListeners.kt | 19 +++ .../quest/hauntedmine/ZealotDialogue.kt | 108 +++++++++++++ .../main/core/game/requirement/Requirement.kt | 2 +- 7 files changed, 433 insertions(+), 5 deletions(-) create mode 100644 Server/src/main/content/region/morytania/handlers/AbandonedMineListeners.kt create mode 100644 Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMine.kt create mode 100644 Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMineListeners.kt create mode 100644 Server/src/main/content/region/morytania/quest/hauntedmine/ZealotDialogue.kt diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 46a5a18e7..e5e5395ae 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -157,7 +157,7 @@ }, { "npc_id": "47", - "loc_data": "{2821,3170,0,1,1}-{3341,3267,0,1,5}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{2339,9356,0,1,0}-{2354,9390,0,1,0}-{2361,9403,0,1,0}-{2362,9347,0,1,0}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2568,9620,0,1,0}-{2573,9612,0,1,0}-{2579,9631,0,1,0}-{2580,9600,0,1,0}-{2580,9614,0,1,0}-{2580,9620,0,1,0}-{2580,9626,0,1,0}-{2583,9632,0,1,0}-{2584,9625,0,1,0}-{2584,9637,0,1,0}-{2589,9644,0,1,0}-{2590,9601,0,1,0}-{2590,9638,0,1,0}-{2591,9601,0,1,0}-{2591,9621,0,1,0}-{2594,9636,0,1,0}-{2594,9644,0,1,0}-{2597,9604,0,1,0}-{2607,9615,0,1,0}-{2608,9628,0,1,0}-{2614,9651,0,1,0}-{2614,9656,0,1,0}-{2615,9647,0,1,0}-{2615,9661,0,1,0}-{2616,9633,0,1,0}-{2618,9630,0,1,0}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3233,3237,0,1,7}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}-{3001,3202,0,1,5}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{2801,3158,0,1,2}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{3021,3205,0,1,6}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{2531,3325,0,1,3}-{2530,3327,0,1,5}-{2521,3331,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-" + "loc_data": "{2821,3170,0,1,1}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3341,3267,0,1,5}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{2339,9356,0,1,0}-{2354,9390,0,1,0}-{2361,9403,0,1,0}-{2362,9347,0,1,0}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2568,9620,0,1,0}-{2573,9612,0,1,0}-{2579,9631,0,1,0}-{2580,9600,0,1,0}-{2580,9614,0,1,0}-{2580,9620,0,1,0}-{2580,9626,0,1,0}-{2583,9632,0,1,0}-{2584,9625,0,1,0}-{2584,9637,0,1,0}-{2589,9644,0,1,0}-{2590,9601,0,1,0}-{2590,9638,0,1,0}-{2591,9601,0,1,0}-{2591,9621,0,1,0}-{2594,9636,0,1,0}-{2594,9644,0,1,0}-{2597,9604,0,1,0}-{2607,9615,0,1,0}-{2608,9628,0,1,0}-{2614,9651,0,1,0}-{2614,9656,0,1,0}-{2615,9647,0,1,0}-{2615,9661,0,1,0}-{2616,9633,0,1,0}-{2618,9630,0,1,0}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3233,3237,0,1,7}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}-{3001,3202,0,1,5}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{2801,3158,0,1,2}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{3021,3205,0,1,6}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{2531,3325,0,1,3}-{2530,3327,0,1,5}-{2521,3331,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-" }, { "npc_id": "48", @@ -1221,7 +1221,7 @@ }, { "npc_id": "412", - "loc_data": "{3341,3478,0,1,0}-{3343,3484,0,1,0}-{3345,3484,0,1,0}-{3350,3493,0,1,0}-{3353,3494,0,1,0}-{3361,3484,0,1,0}-{3364,3489,0,1,0}-{3370,3497,0,1,0}-{3379,3478,0,1,0}-{3379,3484,0,1,0}-{3387,3483,0,1,0}-{3388,3494,0,1,0}-{3389,3483,0,1,0}-{3588,3472,0,1,0}-{3598,3509,0,1,0}-{3599,3486,0,1,0}-{3607,3462,0,1,0}-{3611,3499,0,1,0}-{3613,3482,0,1,0}-{3627,3511,0,1,0}-{3628,3473,0,1,0}-{3636,3466,0,1,0}-{3639,3510,0,1,0}-{3411,3536,0,1,0}-{3418,3522,0,1,0}-{3425,3525,0,1,0}-{3429,3522,0,1,0}-{3432,3527,0,1,0}-{3434,3521,0,1,0}-{3445,3526,0,1,0}-{2728,10122,0,1,1}-{2735,10123,0,1,3}-{2733,10129,0,1,1}-{2728,10133,0,1,6}-{2722,10133,0,1,6}-{2736,10137,0,1,1}-{2732,10142,0,1,0}-{2726,10142,0,1,6}-{2729,10140,0,1,3}-{2720,10144,0,1,6}-{2712,10142,0,1,3}-{3565,3503,0,1,0}-{3567,3481,0,1,0}-{3580,3491,0,1,0}-" + "loc_data": "{3341,3478,0,1,0}-{3343,3484,0,1,0}-{3345,3484,0,1,0}-{3350,3493,0,1,0}-{3353,3494,0,1,0}-{3361,3484,0,1,0}-{3364,3489,0,1,0}-{3370,3497,0,1,0}-{3379,3478,0,1,0}-{3379,3484,0,1,0}-{3387,3483,0,1,0}-{3388,3494,0,1,0}-{3389,3483,0,1,0}-{3588,3472,0,1,0}-{3598,3509,0,1,0}-{3599,3486,0,1,0}-{3607,3462,0,1,0}-{3611,3499,0,1,0}-{3613,3482,0,1,0}-{3627,3511,0,1,0}-{3628,3473,0,1,0}-{3636,3466,0,1,0}-{3639,3510,0,1,0}-{3411,3536,0,1,0}-{3418,3522,0,1,0}-{3425,3525,0,1,0}-{3429,3522,0,1,0}-{3432,3527,0,1,0}-{3434,3521,0,1,0}-{3445,3526,0,1,0}-{3419,9646,0,1,0}-{3418,9642,0,1,0}-{3414,9643,0,1,0}-{3411,9644,0,1,0}-{3410,9641,0,1,0}-{3409,9638,0,1,0}-{3419,9630,0,1,0}-{3421,9629,0,1,0}-{3433,9638,0,1,0}-{3434,9636,0,1,0}-{3436,9636,0,1,0}-{3423,9625,0,1,0}-{2728,10122,0,1,1}-{2735,10123,0,1,3}-{2733,10129,0,1,1}-{2728,10133,0,1,6}-{2722,10133,0,1,6}-{2736,10137,0,1,1}-{2732,10142,0,1,0}-{2726,10142,0,1,6}-{2729,10140,0,1,3}-{2720,10144,0,1,6}-{2712,10142,0,1,3}-{3565,3503,0,1,0}-{3567,3481,0,1,0}-{3580,3491,0,1,0}-" }, { "npc_id": "419", @@ -3385,7 +3385,7 @@ }, { "npc_id": "1223", - "loc_data": "{3585,3478,0,1,0}-{3586,3480,0,1,0}-{3586,3496,0,1,0}-{3592,3477,0,1,0}-{3593,3458,0,1,0}-{3593,3508,0,1,0}-{3595,3491,0,1,0}-{3597,3479,0,1,0}-{3607,3466,0,1,0}-{3617,3477,0,1,0}-{3618,3514,0,1,0}-{3631,3471,0,1,0}-{3631,3499,0,1,0}-{3632,3459,0,1,0}-{3632,3475,0,1,0}-{3638,3472,0,1,0}-{3646,3467,0,1,0}-" + "loc_data": "{3585,3478,0,1,0}-{3586,3480,0,1,0}-{3586,3496,0,1,0}-{3592,3477,0,1,0}-{3593,3458,0,1,0}-{3593,3508,0,1,0}-{3595,3491,0,1,0}-{3597,3479,0,1,0}-{3607,3466,0,1,0}-{3617,3477,0,1,0}-{3618,3514,0,1,0}-{3631,3471,0,1,0}-{3631,3499,0,1,0}-{3632,3459,0,1,0}-{3632,3475,0,1,0}-{3638,3472,0,1,0}-{3646,3467,0,1,0}-{3460,3241,0,1,0}-{3459,3237,0,1,0}-{3456,3234,0,1,0}-{3458,3230,0,1,0}-{3457,3227,0,1,0}-{3456,3223,0,1,0}-" }, { "npc_id": "1227", @@ -3855,6 +3855,10 @@ "npc_id": "1526", "loc_data": "{2443,3089,0,0,0}-" }, + { + "npc_id": "1528", + "loc_data": "{3443,3256,0,1,0}-" + }, { "npc_id": "1544", "loc_data": "{2911,10175,0,0,4}-{2912,10175,0,0,4}-{2913,10175,0,0,4}-{2914,10175,0,0,4}-{2909,10173,0,0,4}-{2910,10173,0,0,4}-{2911,10173,0,0,4}-{2912,10173,0,0,4}-{2913,10173,0,0,4}-{2909,10171,0,0,4}-{2910,10171,0,0,4}-{2911,10169,0,0,4}-{2912,10169,0,0,4}-{2913,10169,0,0,4}-" diff --git a/Server/data/configs/object_configs.json b/Server/data/configs/object_configs.json index ae364fd37..3c0478db1 100644 --- a/Server/data/configs/object_configs.json +++ b/Server/data/configs/object_configs.json @@ -7625,7 +7625,7 @@ }, { "examine": "It looks cramped and dark.", - "ids": "4920,4921,4922" + "ids": "4920,4921,4922,20524" }, { "examine": "These stairs seem to have been hewn out of the rock itself.", @@ -20730,5 +20730,13 @@ { "examine": "Rough but adequate.", "ids": "14918" + }, + { + "examine": "This door is blocked by a huge slab of stone.", + "ids": "20528" + }, + { + "examine": "A door leading somewhere.", + "ids": "20527" } ] \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/handlers/AbandonedMineListeners.kt b/Server/src/main/content/region/morytania/handlers/AbandonedMineListeners.kt new file mode 100644 index 000000000..3c6a2cddc --- /dev/null +++ b/Server/src/main/content/region/morytania/handlers/AbandonedMineListeners.kt @@ -0,0 +1,150 @@ +package content.region.morytania.handlers + +import core.api.animate +import core.api.forceMove +import core.api.forceWalk +import core.api.location +import core.api.teleport +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.world.map.Location +import org.rs09.consts.Scenery + +/* + * This covers general listeners for the Abandoned Mine that aren't part of the Haunted Mine quest. + * + * Outside mine: Region 13618 - 3442 3254 0 + * Mine level 1: Region 13718 - 3426 9636 0 + * Mine level 2: Region 11079 - 2792 4584 0 + * Mine level 3: Region 10822 - 2717 4502 0 + * Mine level 4: Region 11078 - 2761 4500 0 + * Mine level 5: Region 10821 - 2723 4550 0 + * Mine level 6: Region 11077 - 2805 4455 0 + * + * */ + +class AbandonedMineListeners : InteractionListener { + + override fun defineListeners() { + + // stairs that go to level 2. the doors down there require the crystal mine key to unlock. + on(Scenery.STAIRS_4919, IntType.SCENERY, "Walk-down") { player, node -> + teleport(player, Location.create(2792, 4592, 0)) + } + + // stairs that go from level 2 to outside. the doors on level 2 require the crystal mine key to unlock. + on(Scenery.STAIRS_4923, IntType.SCENERY, "Walk-up") { player, node -> + teleport(player, Location.create(3453, 3242, 0)) + } + + // minecart to climb over to get to mine entrance + on(Scenery.MINE_CART_4918, IntType.SCENERY, "Climb-over") { player, node -> + //todo check agility + //todo fix the animation + if (player.location == node.location.transform(-1, 0, 0)) { + forceMove(player, node.location.transform(-1, 0, 0), node.location.transform(1, 0, 0), 1, 1, null, 839) + } else if (player.location == node.location.transform(1, 0, 0)) { + forceMove(player, node.location.transform(1, 0, 0), node.location.transform(-1, 0, 0), 1, 1, null, 839) + } + return@on true + } + + // entrance to Tarn's Lair + // ::setvarp 382 0 11 to finish haunted mine and activate entrance. + // ::setvarp 382 0 0 to reset haunted mine. + on(Scenery.ENTRANCE_20527, IntType.SCENERY, "Enter") { player, node -> + teleport(player, Location.create(3166, 4547, 0)) + } + + // from tarn's lair back to mine + on(Scenery.PASSAGEWAY_20814, IntType.SCENERY, "Enter") { player, node -> + teleport(player, Location.create(3424, 9660, 0)) + } + + // entrance from outside (main) to mine level 1 + on(Scenery.CART_TUNNEL_4913, IntType.SCENERY, "Crawl-down") { player, node -> + animate(player, 844) + teleport(player, Location.create(3436, 9637, 0)) + } + + // mine level 1 back to entrance + on(Scenery.CART_TUNNEL_4920, IntType.SCENERY, "Crawl-through") { player, node -> + animate(player, 844) + teleport(player, Location.create(3441, 3232, 0)) + } + + // mine level 1 to outside (west) + on(Scenery.CART_TUNNEL_4921, IntType.SCENERY, "Crawl-through") { player, node -> + animate(player, 844) + teleport(player, Location.create(3429, 3233, 0)) + } + + // mine level 1 to outside (west) + on(Scenery.CART_TUNNEL_20524, IntType.SCENERY, "Crawl-through") { player, node -> + animate(player, 844) + teleport(player, Location.create(3428, 3225, 0)) + } + + // outside (west) to mine level 1 + on(Scenery.CART_TUNNEL_4914, IntType.SCENERY, "Crawl-down") { player, node -> + animate(player, 844) + teleport(player, Location.create(3405, 9631, 0)) + } + + // outside (west) to mine level 1 + on(Scenery.CART_TUNNEL_4915, IntType.SCENERY, "Crawl-down") { player, node -> + animate(player, 844) + teleport(player, Location.create(3409, 9623, 0)) + } + + // mine level 1 to mine level 2 + on(Scenery.LADDER_4965, IntType.SCENERY, "Climb-down") { player, node -> + // ladder 4965 is reused in two locations, so we have to see which one the player is interacting with + val loc = player.location + + // Check around a 1-tile radius of the north ladder + if (loc.z == 0 && + loc.x in 3412..3414 && + loc.y in 9632..9634) { + + animate(player, 828) + teleport(player, Location.create(2774, 4577, 0)) + + // Check around a 1-tile radius of the south ladder + } else if (loc.z == 0 && + loc.x in 3421..3423 && + loc.y in 9624..9626) { + + animate(player, 828) + teleport(player, Location.create(2783, 4569, 0)) + } + + return@on true + } + + // mine level 2 to mine level 1 + on(Scenery.LADDER_4966, IntType.SCENERY, "Climb-up") { player, node -> + // ladder 4965 is reused in two locations, so we have to see which one the player is interacting with + val loc = player.location + + // Check around a 1-tile radius of the north ladder + if (loc.z == 0 && + loc.x in 2772..2774 && + loc.y in 4576..4578) { + + animate(player, 828) + teleport(player, Location.create(3412, 9633, 0)) + + // Check around a 1-tile radius of the south ladder + } else if (loc.z == 0 && + loc.x in 2781..2783 && + loc.y in 4568..4570) { + + animate(player, 828) + teleport(player, Location.create(3422, 9624, 0)) + } + + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMine.kt b/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMine.kt new file mode 100644 index 000000000..b01d64190 --- /dev/null +++ b/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMine.kt @@ -0,0 +1,139 @@ +package content.region.morytania.quest.hauntedmine + +import content.data.Quests +import core.api.* +import core.game.node.entity.player.link.quest.Quest +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.plugin.Initializable +import org.rs09.consts.Items + +/* + * Haunted Mine Quest + * + * Some of the sources used: + * https://www.youtube.com/watch?v=g3F4tC1KOck (primary) + * https://www.youtube.com/watch?v=CD77NeKz1J4 (secondary) + * https://web.archive.org/web/20081216051045/http://runescape.wikia.com/wiki/Haunted_Mine + * + */ + +// todo re-add terror dogs (and wall beasts?) to slayer tasks once done with this quest and tarns' lair. + +// todo check meleeswinghandler to verify salve att bonus, salve damage bonus, and salve undead targets. + +// Output of ./get-varp.sh 72 +// if (VARP[382] == 11) return 2; if (VARP[382] == 0) return 0; return 1; }; if (arg0 == 41) + +@Initializable +class HauntedMine : Quest(Quests.HAUNTED_MINE,73 ,72 ,2 ,382, 0, 1, 11) { + + companion object { + const val questName = "Haunted Mine" + + const val attributeKilledTreusDayth = "/save:quest:hauntedmine-killedtreusdayth" // True after you've killed Treus Dayth. + const val attributeKeyMentioned = "/save:quest:hauntedmine-keymentioned" // True after the player asks about a way into the mines. + } + + // Quest Journal ref: https://youtu.be/CD77NeKz1J4?si=AxNEg5YZU5oJ3T11&t=231 + // The video fragment matches the current RS3 journal: https://runescape.wiki/w/Transcript:Haunted_Mine/Journal + override fun drawJournal(player: Player, stage: Int) { + super.drawJournal(player, stage) + var line = 12 + var stage = getStage(player) + + var started = getQuestStage(player, Quests.HAUNTED_MINE) > 0 + + if(!started){ + line(player, "I can start this quest by speaking to the !!Zealot?? at the", line++, false) + line(player, "entrance of the Abandoned Mine in south !!Morytania??.", line++, false) + line(player, "I must be able to defeat a !!level 95 monster??, and need the", line++, false) // git gud + line(player, "following skill levels:", line++, false) + line(player, "Level 35 Crafting", line++, hasLevelStat(player, Skills.CRAFTING, 35)) // to cut a salve shard from the crystal outcrop + line(player, "Level 15 Agility", line++, hasLevelStat(player, Skills.AGILITY, 15)) // to go over a minecart at the entrance to the mine + line(player, "I also need to have completed the following quests:", line++, false) + line(player, "Priest in Peril", line++, isQuestComplete(player, Quests.PRIEST_IN_PERIL)) // to be able to access Morytania + limitScrolling(player, line, true) + } + if(stage >= 1) { // set stage 1 after talking to Zealot. + line(player, "I met a fanatic Saradominist just outside the Morytanian", line++, stage > 1) + line(player, "mines. He told me that the mines had been sealed, but", line++, stage > 1) + line(player, "contained within them !!crystals?? of a great power over evil.", line++, stage > 1) + } + if (stage >= 2) { // set stage 2 after first entering the mine. + line(player, "I managed to get into the mines via a thin tunnel high up in", line++, stage > 2) + line(player, "the mountains.", line++, stage > 2) + } + if (stage >= 3) { // set stage 3 after entering level 4 (fungus and cart level) + line(player, "Now I must reach the !!lower levels?? where apparently the", line++, stage > 3) + line(player, "!!crystals?? can be found.", line++, stage > 3) + } + if (stage >= 4) { // set stage 4 after going down the lift to level 5 + line(player, "I managed to start the !!lift?? which allowed me to get to", line++, stage > 4) + line(player, "the !!lower levels??.", line++, stage > 4) + line(player, "Now I can continue my search for the !!crystals??.", line++, stage > 4) + } + if (stage >= 5) { // set stage 5 if you go down to level 6 without a fungus. + line(player, "The !!lower levels?? of the mine were too !!dark?? to navigate.", line++, stage > 5) + } + if (stage >= 6) { // set stage 6 if you go down to level 6 with a fungus. + line(player, "I had to use a !!glowing fungus?? from the upper levels", line++, stage > 6) + line(player, "to !!Light?? the way.", line++, stage > 6) + } + if (stage >= 7) { // set stage 7 after you've killed dayth. + line(player, "I found a !!key?? in the !!lower levels??. I had to fight a", line++, stage > 7) + line(player, "powerful !!ghost?? who tried to prevent me taking it.", line++, stage > 7) + } + if (stage >= 8) { // set stage 8 after you cut a shard. + line(player, "I used this !!key?? to reach the legendary !!crystals??, from", line++, stage > 8) + line(player, "which I cut a !!salve shard?? to aid in fighting the undead.", line++, stage > 8) + } + if (stage >= 100) { // complete quest after you've cut a shard. + line++ + line(player,"QUEST COMPLETE!", line++, false) + } + limitScrolling(player, line, false) + } + + override fun reset(player: Player) { + removeAttribute(player, attributeKilledTreusDayth) + + setVarbit(player, 382, 0, true) // resets the quest and closes tarn's door. + } + + override fun setStage(player: Player, stage: Int) { + super.setStage(player, stage) + this.updateVarps(player) + } + + override fun updateVarps(player: Player) { + + // Stage Varbits + if(getQuestStage(player, Quests.HAUNTED_MINE) == 0) { + setVarbit(player, 382, 0, true) // marks quest as red + } + if(getQuestStage(player, Quests.HAUNTED_MINE) >= 100) { + setVarbit(player, 382, 1, true) // marks quest as yellow + } + if(getQuestStage(player, Quests.HAUNTED_MINE) >= 100) { + setVarbit(player, 382, 11, true) // marks quest as green and opens tarn's door + } + } + + override fun finish(player: Player) { + var ln = 10 + super.finish(player) + player.packetDispatch.sendString("You have completed the Haunted Mine Quest!", 277, 4) + player.packetDispatch.sendItemZoomOnInterface(Items.SALVE_AMULET_4081,230,277,5) + + drawReward(player, "2 quest points", ln++) + drawReward(player, "22,000 Strength XP", ln++) + drawReward(player, "Access to Tarn's Lair", ln++) + + rewardXP(player, Skills.STRENGTH, 22000.0) + } + + override fun newInstance(`object`: Any?): Quest { + return this + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMineListeners.kt b/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMineListeners.kt new file mode 100644 index 000000000..7b8ae397c --- /dev/null +++ b/Server/src/main/content/region/morytania/quest/hauntedmine/HauntedMineListeners.kt @@ -0,0 +1,19 @@ +package content.region.morytania.quest.hauntedmine + +import core.api.* +import core.game.interaction.InteractionListener +import org.rs09.consts.Items + +class HauntedMineListeners : InteractionListener { + + override fun defineListeners() { + + onUseWith(ITEM, Items.SALVE_SHARD_4082, Items.BALL_OF_WOOL_1759) { player, used, _ -> + removeItem(player, Items.SALVE_SHARD_4082) + removeItem(player, Items.BALL_OF_WOOL_1759) + addItem(player, Items.SALVE_AMULET_4081) + sendMessage(player, "You string the salve amulet.") + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/morytania/quest/hauntedmine/ZealotDialogue.kt b/Server/src/main/content/region/morytania/quest/hauntedmine/ZealotDialogue.kt new file mode 100644 index 000000000..a1237ca1c --- /dev/null +++ b/Server/src/main/content/region/morytania/quest/hauntedmine/ZealotDialogue.kt @@ -0,0 +1,108 @@ +package content.region.morytania.quest.hauntedmine + +import content.data.Quests +import core.api.* +import core.game.dialogue.* +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.tools.END_DIALOGUE +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +@Initializable +class ZealotDialogue (player: Player? = null) : DialoguePlugin(player) { + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + openDialogue(player, ZealotDialogueFile(), npc) + return true + } + override fun newInstance(player: Player): DialoguePlugin { + return ZealotDialogue(player) + } + override fun getIds(): IntArray { + return intArrayOf(NPCs.ZEALOT_1528) + } +} + +// Dialogue formatted mostly by ovenbread's scriptConvert.html +class ZealotDialogueFile : DialogueFile() { + override fun handle(componentID: Int, buttonID: Int) { + when (getQuestStage(player!!, Quests.HAUNTED_MINE)){ + + // dialogue before starting the quest + 0 -> when (stage) { + 0 -> playerl(FacialExpression.FRIENDLY, "Hello there.").also { stage++ } + 1 -> npcl(FacialExpression.FRIENDLY, "State thy allegiance stranger.").also { stage++ } + 2 -> showTopics( + Topic(FacialExpression.FRIENDLY, "I follow the path of Saradomin.", 3), + Topic(FacialExpression.FRIENDLY, "I serve only Zamorak.", 11), + Topic(FacialExpression.FRIENDLY, "My beliefs are in accord with the teachings of Guthix.", 21), + Topic(FacialExpression.FRIENDLY, "I have no particular allegiance.", 27), + ) + 3 -> npcl(FacialExpression.FRIENDLY, "Ah, a wise choice my friend. But if you truly follow Saradomin, what brings you to these evil lands?").also { stage++ } + 4 -> showTopics( + ) + 5 -> npcl(FacialExpression.FRIENDLY, "A noble cause indeed. One that I can sympathise with, for I myself am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { stage++ } + 6 -> npcl(FacialExpression.FRIENDLY, "Then leave me, I have no time to listen to your poisonous tongue.").also { stage++ } + 7 -> npcl(FacialExpression.FRIENDLY, "Saradomin has granted you wisdom. The evil creatures of this land are cunning and you are right to question anyone's purposes here. I am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { stage++ } + 8 -> npcl(FacialExpression.FRIENDLY, "A noble cause indeed. One that I can sympathise with, for I myself am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { stage++ } + 9 -> npcl(FacialExpression.FRIENDLY, "Then leave me, I have no time to listen to your poisonous tongue.").also { stage++ } + 10 -> npcl(FacialExpression.FRIENDLY, "Saradomin has granted you wisdom. The evil creatures of this land are cunning and you are right to question anyone's purposes here. I am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { + stage = END_DIALOGUE + } + 11 -> npcl(FacialExpression.FRIENDLY, "Then begone. Normally I would strike you down in an instant, but for now I have no time. I am on a quest of the utmost importance.").also { stage++ } + 12 -> showTopics( + Topic(FacialExpression.FRIENDLY, "What is this quest of which you speak?", 13), + Topic(FacialExpression.FRIENDLY, "Fine, I didn't want to talk to you either.", 16), + ) + 13 -> npcl(FacialExpression.FRIENDLY, "It is no concern of yours, but rest assured it will help in crushing you and those others who serve your vile master.").also { stage++ } + 14 -> playerl(FacialExpression.FRIENDLY, "I doubt that.").also { stage++ } + 15 -> npcl(FacialExpression.FRIENDLY, "I would expect nothing less of you, misguided as you already are.").also { + stage = END_DIALOGUE + } + 16 -> npcl(FacialExpression.FRIENDLY, "Fear not fiend, even though I may leave you be, you shall not escape justice at the hands of the righteous.").also { stage++ } + 17 -> npcl(FacialExpression.FRIENDLY, "It is no concern of yours, but rest assured it will help in crushing you and those others who serve your vile master.").also { stage++ } + 18 -> playerl(FacialExpression.FRIENDLY, "I doubt that.").also { stage++ } + 19 -> npcl(FacialExpression.FRIENDLY, "I would expect nothing less of you, misguided as you already are.").also { stage++ } + 20 -> npcl(FacialExpression.FRIENDLY, "Fear not fiend, even though I may leave you be, you shall not escape justice at the hands of the righteous.").also { + stage = END_DIALOGUE + } + 21 -> npcl(FacialExpression.FRIENDLY, "A wishy washy set of beliefs. You should follow Saradomin and find a real purpose in your life.").also { stage++ } + 22 -> showTopics( + Topic(FacialExpression.FRIENDLY, "And what sort of purpose would that be?", 23), + Topic(FacialExpression.FRIENDLY, "I can make my own choices.", 24), + ) + 23 -> npcl(FacialExpression.FRIENDLY, "To further the glory of Saradomin of course. Take myself, I am upon a quest that will allow Saradomin to be glorified even in these dark lands.").also { + stage = END_DIALOGUE + } + 24 -> npcl(FacialExpression.FRIENDLY, "I look only to help those who are misguided.").also { stage++ } + 25 -> npcl(FacialExpression.FRIENDLY, "To further the glory of Saradomin of course. Take myself, I am upon a quest that will allow Saradomin to be glorified even in these dark lands.").also { stage++ } + 26 -> npcl(FacialExpression.FRIENDLY, "I look only to help those who are misguided.").also { + stage = END_DIALOGUE + } + 27 -> npcl(FacialExpression.FRIENDLY, "Then your life is without reason or direction. I would talk to you further on this matter, but for now my attentions must be elsewhere.").also { stage++ } + 28 -> showTopics( + Topic(FacialExpression.FRIENDLY, "Then I shall leave you to your business.", 29), + Topic(FacialExpression.FRIENDLY, "Why, what are you doing?", 30), + ) + 29 -> npcl(FacialExpression.FRIENDLY, "I shall pray that Saradomin grants you the wisdom to see through your folly.").also { + stage = END_DIALOGUE + } + 30 -> npcl(FacialExpression.FRIENDLY, "I am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { stage++ } + 31 -> npcl(FacialExpression.FRIENDLY, "I shall pray that Saradomin grants you the wisdom to see through your folly.").also { stage++ } + 32 -> npcl(FacialExpression.FRIENDLY, "I am upon a quest. One that will allow Saradomin to be glorified even in these dark lands.").also { + stage = END_DIALOGUE + } + } + + // dialogue when quest is in progress + in 1..99 -> when (stage) { + 0 -> sendDialogue(player!!, "where crystal").also { stage = END_DIALOGUE } + } + + // dialogue after completing quest + 100 -> when (stage) { + 0 -> sendDialogue(player!!, "gz on the necklace").also { stage = END_DIALOGUE } + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/requirement/Requirement.kt b/Server/src/main/core/game/requirement/Requirement.kt index d43b68dac..5937d3dbd 100644 --- a/Server/src/main/core/game/requirement/Requirement.kt +++ b/Server/src/main/core/game/requirement/Requirement.kt @@ -126,7 +126,7 @@ enum class QuestRequirements(val quest: Quests, vararg val requirements: Require HORROR_DEEP (Quests.HORROR_FROM_THE_DEEP, SkillReq(Skills.AGILITY, 35, true)), THRONE (Quests.THRONE_OF_MISCELLANIA, QuestReq(HERO), QuestReq(FREM_TRIALS)), MONKEY (Quests.MONKEY_MADNESS, QuestReq(GRAND_TREE), QuestReq(GNOME_VILLAGE)), - MINE (Quests.HAUNTED_MINE, QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 35, true)), + MINE (Quests.HAUNTED_MINE, QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 35, true), SkillReq(Skills.AGILITY, 15, true)), TROLL_ROMANCE (Quests.TROLL_ROMANCE, QuestReq(TROLL_STRONGHOLD), SkillReq(Skills.AGILITY, 28, true)), SEARCH_MYREQUE (Quests.IN_SEARCH_OF_THE_MYREQUE, QuestReq(NATURE_SPIRIT), SkillReq(Skills.AGILITY, 25, true)), FENKENSTRAIN (Quests.CREATURE_OF_FENKENSTRAIN, QuestReq(PRIEST), QuestReq(RESTLESS_GHOST), SkillReq(Skills.THIEVING, 25, true), SkillReq(Skills.CRAFTING, 20, true)),